diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng')
102 files changed, 9480 insertions, 4270 deletions
diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS index 8c3ef117dd..7434bcada0 100644 --- a/src/3rdparty/harfbuzz-ng/NEWS +++ b/src/3rdparty/harfbuzz-ng/NEWS @@ -1,3 +1,261 @@ +Overview of changes leading to 1.7.4 +Wednesday, December 20, 2017 +==================================== + +- Fix collect_glyphs() regression caused by hb_set_t changes. + + +Overview of changes leading to 1.7.3 +Monday, December 18, 2017 +==================================== + +- hb_set_t performance tuning and optimizations. +- Speed up collect_glyphs() and reject garbage data. +- In hb_coretext_font_create() set font point-size (ptem). +- Misc fixes. + + +Overview of changes leading to 1.7.2 +Monday, December 4, 2017 +==================================== + +- Optimize hb_set_add_range(). +- Misc fixes. +- New API: +hb_coretext_font_create() + + +Overview of changes leading to 1.7.1 +Tuesday, November 14, 2017 +==================================== + +- Fix atexit object destruction regression. +- Fix minor integer-overflow. + + +Overview of changes leading to 1.7.0 +Monday, November 13, 2017 +==================================== + +- Minor Indic fixes. +- Implement kerning and glyph names in hb-ot-font. +- Various DSO optimization re .data and .bss sizes. +- Make C++11 optional; build fixes. +- Mark all other backends "unsafe-to-break". +- Graphite fix. + + +Overview of changes leading to 1.6.3 +Thursday, October 26th, 2017 +==================================== + +- Fix hb_set_t some more. Should be solid now. +- Implement get_glyph_name() for hb-ot-font. +- Misc fixes. + + +Overview of changes leading to 1.6.2 +Monday, October 23nd, 2017 +==================================== + +- Yesterday's release had a bad crasher; don't use it. That's what + happens when one works on Sunday... + https://github.com/harfbuzz/harfbuzz/issues/578 +- Build fixes for FreeBSD and Chrome Android. + + +Overview of changes leading to 1.6.1 +Sunday, October 22nd, 2017 +==================================== + +- Don't skip over COMBINING GRAPHEME JOINER when ligating, etc. + To be refined: https://github.com/harfbuzz/harfbuzz/issues/554 +- Faster hb_set_t implementation. +- Don't use deprecated ICU API. +- Fix undefined-behavior in Myanmar shaper, introduced in 1.6.0 +- Deprecated API: + hb_set_invert() + + +Overview of changes leading to 1.6.0 +Friday, October the 13th, 2017 +==================================== + +- Update to Unicode 10. + +- Various Indic and Universal Shaping Engine fixes as a result of + HarfBuzz Hackfest with Jonathan Kew at Web Engines Hackfest at + the Igalia offices in A Coruña, Spain. Thanks Igalia for having + us! + +- Implement Unicode Arabic Mark Ordering Algorithm UTR#53. + +- Implement optical sizing / tracking in CoreText backend, using + new API hb_font_set_ptem(). + +- Allow notifying hb_font_t that underlying FT_Face changed sizing, + using new API hb_ft_font_changed(). + +- More Graphite backend RTL fixes. + +- Fix caching of variable font shaping plans. + +- hb-view / hb-shape now accept following new arguments: + + o --unicodes: takes a list of hex numbers that represent Unicode + codepoints. + +New API: ++hb_face_get_table_tags() ++hb_font_set_ptem() ++hb_font_get_ptem() ++hb_ft_font_changed() + + +Overview of changes leading to 1.5.1 +Tuesday, September 5, 2017 +==================================== + +- Fix "unsafe-to-break" in fallback shaping and other corner cases. + All our tests pass with --verify now, meaning unsafe-to-break API + works as expected. +- Add --unicodes to hb-view / hb-shape. +- [indic] Treat Consonant_With_Stacker as consonant. This will need + further tweaking. +- hb_buffer_diff() tweaks. + + +Overview of changes leading to 1.5.0 +Wednesday, August 23, 2017 +==================================== + +- Misc new API, for appending a buffer to another, and for comparing + contents of two buffers for types of differences. + +- New "unsafe-to-break" API. Can be used to speed up reshaping + in line-breaking situations. Essentially, after shaping, it returns + positions in the input string (some of the cluster boundaries) that + are "safe to break" in that if the text is segmented at that position + and two sides reshaped and concatenated, the shaping result is + exactly the same as shaping the text in one piece. + + hb-view and hb-shape and hb-shape now take --verify, which verifies + the above property. + + Some corner cases of the implementation are still not quite working. + Those will be fixed in subsequent releases. + +- New API: + +hb_buffer_append() + +hb_glyph_flags_t +HB_GLYPH_FLAG_UNSAFE_TO_BREAK +HB_GLYPH_FLAG_DEFINED +hb_glyph_info_get_glyph_flags() + +HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS + +hb_buffer_diff_flags_t +HB_BUFFER_DIFF_FLAG_EQUAL +HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH +HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH +HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT +HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT +HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH +HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH +HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH +HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH +hb_buffer_diff + + +Overview of changes leading to 1.4.8 +Tuesday, August 8, 2017 +==================================== + +- Major fix to avar table handling. +- Rename hb-shape --show-message to --trace. +- Build fixes. + + +Overview of changes leading to 1.4.7 +Tuesday, July 18, 2017 +==================================== + +- Multiple Indic, Tibetan, and Cham fixes. +- CoreText: Allow disabling kerning. +- Adjust Arabic feature order again. +- Misc build fixes. + + +Overview of changes leading to 1.4.6 +Sunday, April 23, 2017 +==================================== + +- Graphite2: Fix RTL positioning issue. +- Backlist GDEF of more versions of Padauk and Tahoma. +- New, experimental, cmake alternative build system. + + +Overview of changes leading to 1.4.5 +Friday, March 10, 2017 +==================================== + +- Revert "Fix Context lookup application when moving back after a glyph..." + This introduced memory access problems. To be fixed properly soon. + + +Overview of changes leading to 1.4.4 +Sunday, March 5, 2017 +==================================== + +- Fix Context lookup application when moving back after a glyph deletion. +- Fix buffer-overrun in Bengali. + + +Overview of changes leading to 1.4.3 +Saturday, February 25, 2017 +==================================== + +- Route Adlam script to Arabic shaper. +- Misc fixes. +- New API: + hb_font_set_face() +- Deprecate API: + hb_graphite2_font_get_gr_font() + + +Overview of changes leading to 1.4.2 +Monday, January 23, 2017 +==================================== + +- Implement OpenType Font Variation tables avar/fvar/HVAR/VVAR. +- hb-shape and hb-view now accept --variations. +- New API: + +hb_variation_t +hb_variation_from_string() +hb_variation_to_string() + +hb_font_set_variations() +hb_font_set_var_coords_design() +hb_font_get_var_coords_normalized() + +hb-ot-var.h: +hb_ot_var_axis_t +hb_ot_var_has_data() +hb_ot_var_get_axis_count() +hb_ot_var_get_axes() +hb_ot_var_find_axis() +hb_ot_var_normalize_variations() +hb_ot_var_normalize_coords() + +- MVAR to be implemented later. Access to named instances to be + implemented later as well. + +- Misc fixes. + + Overview of changes leading to 1.4.1 Thursday, January 5, 2017 ==================================== @@ -212,7 +470,7 @@ Tuesday, February 23, 2016 - CoreText: Drastically speed up font initialization. - CoreText: Fix tiny leak. - Group ZWJ/ZWNJ with previous syllable under cluster-level=0. - https://github.com/behdad/harfbuzz/issues/217 + https://github.com/harfbuzz/harfbuzz/issues/217 - Add test/shaping/README.md about how to add tests to the suite. @@ -228,8 +486,8 @@ Friday, February 19, 2016 - Allow GPOS cursive connection on marks, and fix the interaction with mark attachment. This work resulted in some changes to how mark attachments work. See: - https://github.com/behdad/harfbuzz/issues/211 - https://github.com/behdad/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2 + https://github.com/harfbuzz/harfbuzz/issues/211 + https://github.com/harfbuzz/harfbuzz/commit/86c68c7a2c971efe8e35b1f1bd99401dc8b688d2 - Graphite2 shaper: improved negative advance handling (eg. Nastaliq). - Add nmake-based build system for Windows. - Minor speedup. @@ -270,7 +528,7 @@ Wednesday, November 26, 2015 ==================================== - Fix badly-broken fallback shaper that affected terminology. - https://github.com/behdad/harfbuzz/issues/187 + https://github.com/harfbuzz/harfbuzz/issues/187 - Fix y_scaling in Graphite shaper. - API changes: * An unset glyph_h_origin() function in font-funcs now (sensibly) @@ -292,11 +550,11 @@ Wednesday, November 18, 2015 ==================================== - Implement 'stch' stretch feature for Syriac Abbreviation Mark. - https://github.com/behdad/harfbuzz/issues/141 + https://github.com/harfbuzz/harfbuzz/issues/141 - Disable use of decompose_compatibility() callback. - Implement "shaping" of various Unicode space characters, even if the font does not support them. - https://github.com/behdad/harfbuzz/issues/153 + https://github.com/harfbuzz/harfbuzz/issues/153 - If font does not support U+2011 NO-BREAK HYPHEN, fallback to U+2010 HYPHEN. - Changes resulting from libFuzzer continuous fuzzing: @@ -319,7 +577,7 @@ Thursday, October 15, 2015 - Revert default load-flags of fonts created using hb_ft_font_create() back to FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING. This was changed in last release (1.0.5), but caused major issues, so revert. - https://github.com/behdad/harfbuzz/issues/143 + https://github.com/harfbuzz/harfbuzz/issues/143 Overview of changes leading to 1.0.5 @@ -327,7 +585,7 @@ Tuesday, October 13, 2015 ==================================== - Fix multiple memory access bugs discovered using libFuzzer. - https://github.com/behdad/harfbuzz/issues/139 + https://github.com/harfbuzz/harfbuzz/issues/139 Everyone should upgrade to this version as soon as possible. We now have continuous fuzzing set up, to avoid issues like these creeping in again. @@ -598,7 +856,7 @@ Wednesday, July 16, 2014 U+FFFD REPLACEMENT CHARACTER now. - With all changes in this release, the buffer will contain fully valid Unicode after hb_buffer_add_utf8/16/32 no matter how - broken the input is. This can be overriden though. See below. + broken the input is. This can be overridden though. See below. - Fix Mongolian Variation Selectors for fonts without GDEF. - Fix minor invalid buffer access. - Accept zh-Hant and zh-Hans language tags. hb_ot_tag_to_language() diff --git a/src/3rdparty/harfbuzz-ng/README b/src/3rdparty/harfbuzz-ng/README index 69a1bdd9ff..aa055169d5 100644 --- a/src/3rdparty/harfbuzz-ng/README +++ b/src/3rdparty/harfbuzz-ng/README @@ -1,6 +1,7 @@ -[![Build Status](https://travis-ci.org/behdad/harfbuzz.svg)](https://travis-ci.org/behdad/harfbuzz) -[![Build Status](https://ci.appveyor.com/api/projects/status/4oaq58ns2h0m2soa?svg=true)](https://ci.appveyor.com/project/behdad/harfbuzz) -[![Coverage Status](https://img.shields.io/coveralls/behdad/harfbuzz.svg)](https://coveralls.io/r/behdad/harfbuzz) +[![Build Status](https://travis-ci.org/harfbuzz/harfbuzz.svg)](https://travis-ci.org/harfbuzz/harfbuzz) +[![Build status](https://ci.appveyor.com/api/projects/status/0t0flrxpstj9lb9w?svg=true)](https://ci.appveyor.com/project/harfbuzz/harfbuzz) +[![CircleCI](https://circleci.com/gh/harfbuzz/harfbuzz.svg?style=svg)](https://circleci.com/gh/harfbuzz/harfbuzz) +[![Coverage Status](https://img.shields.io/coveralls/harfbuzz/harfbuzz.svg)](https://coveralls.io/r/harfbuzz/harfbuzz) [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/) This is HarfBuzz, a text shaping library. @@ -10,3 +11,5 @@ For bug reports, mailing list, and other information please visit: http://harfbuzz.org/ For license information, see the file COPYING. + +Documentation: https://harfbuzz.github.io diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro index 3b7b11c8ee..ad40b98753 100644 --- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro +++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro @@ -56,6 +56,8 @@ HEADERS += \ $$PWD/src/hb-buffer-deserialize-json.hh \ $$PWD/src/hb-buffer-deserialize-text.hh \ $$PWD/src/hb-cache-private.hh \ + $$PWD/src/hb-debug.hh \ + $$PWD/src/hb-dsalgs.hh \ $$PWD/src/hb-face-private.hh \ $$PWD/src/hb-font-private.hh \ $$PWD/src/hb-mutex-private.hh \ @@ -73,11 +75,13 @@ HEADERS += \ $$PWD/src/hb-ot-os2-table.hh \ $$PWD/src/hb-ot-post-table.hh \ $$PWD/src/hb-private.hh \ + $$PWD/src/hb-set-digest-private.hh \ $$PWD/src/hb-set-private.hh \ $$PWD/src/hb-shape-plan-private.hh \ $$PWD/src/hb-shaper-impl-private.hh \ $$PWD/src/hb-shaper-list.hh \ $$PWD/src/hb-shaper-private.hh \ + $$PWD/src/hb-string-array.hh \ $$PWD/src/hb-unicode-private.hh \ $$PWD/src/hb-utf-private.hh @@ -116,9 +120,11 @@ contains(SHAPERS, opentype) { $$PWD/src/hb-ot-shape-complex-use.cc \ $$PWD/src/hb-ot-shape-complex-use-table.cc \ $$PWD/src/hb-ot-shape-fallback.cc \ - $$PWD/src/hb-ot-shape-normalize.cc + $$PWD/src/hb-ot-shape-normalize.cc \ + $$PWD/src/hb-ot-var.cc HEADERS += \ + $$PWD/src/hb-ot-kern-table.hh \ $$PWD/src/hb-ot-layout-common-private.hh \ $$PWD/src/hb-ot-layout-gdef-table.hh \ $$PWD/src/hb-ot-layout-gpos-table.hh \ @@ -128,6 +134,8 @@ contains(SHAPERS, opentype) { $$PWD/src/hb-ot-layout-math-table.hh \ $$PWD/src/hb-ot-layout-private.hh \ $$PWD/src/hb-ot-map-private.hh \ + $$PWD/src/hb-ot-math-table.hh \ + $$PWD/src/hb-ot-post-macroman.hh \ $$PWD/src/hb-ot-shape-complex-arabic-fallback.hh \ $$PWD/src/hb-ot-shape-complex-arabic-private.hh \ $$PWD/src/hb-ot-shape-complex-arabic-table.hh \ @@ -140,7 +148,11 @@ contains(SHAPERS, opentype) { $$PWD/src/hb-ot-shape-complex-use-private.hh \ $$PWD/src/hb-ot-shape-fallback-private.hh \ $$PWD/src/hb-ot-shape-normalize-private.hh \ - $$PWD/src/hb-ot-shape-private.hh + $$PWD/src/hb-ot-shape-private.hh \ + $$PWD/src/hb-ot-var-avar-table.hh \ + $$PWD/src/hb-ot-var-fvar-table.hh \ + $$PWD/src/hb-ot-var-hvar-table.hh \ + $$PWD/src/hb-ot-var-mvar-table.hh HEADERS += \ $$PWD/src/hb-ot.h \ @@ -148,7 +160,8 @@ contains(SHAPERS, opentype) { $$PWD/src/hb-ot-layout.h \ $$PWD/src/hb-ot-math.h \ $$PWD/src/hb-ot-shape.h \ - $$PWD/src/hb-ot-tag.h + $$PWD/src/hb-ot-tag.h \ + $$PWD/src/hb-ot-var.h } contains(SHAPERS, coretext) { @@ -168,21 +181,7 @@ contains(SHAPERS, coretext) { # even in 10.8 where they were also made available stand-alone. LIBS_PRIVATE += -framework ApplicationServices - # CoreText is documented to be available on watchOS, but the headers aren't present - # in the watchOS Simulator SDK like they are supposed to be. Work around the problem - # by adding the device SDK's headers to the search path as a fallback. - # rdar://25314492, rdar://27844864 - watchos:simulator { - simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks - device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks - for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) { - QMAKE_CXXFLAGS += \ - -Xarch_$${arch} \ - -F$$simulator_system_frameworks \ - -Xarch_$${arch} \ - -F$$device_system_frameworks - } - } + CONFIG += watchos_coretext } contains(SHAPERS, fallback)|isEmpty(SHAPERS) { diff --git a/src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-var.h b/src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-var.h new file mode 100644 index 0000000000..629acbcb64 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/include/harfbuzz/hb-ot-var.h @@ -0,0 +1 @@ +#include "../../src/hb-ot-var.h" diff --git a/src/3rdparty/harfbuzz-ng/patches/0001-Qt-specific-workaround-for-AAT-shaper.patch b/src/3rdparty/harfbuzz-ng/patches/0001-Qt-specific-workaround-for-AAT-shaper.patch new file mode 100644 index 0000000000..470e0ffe5a --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/patches/0001-Qt-specific-workaround-for-AAT-shaper.patch @@ -0,0 +1,58 @@ +From: Konstantin Ritt <ritt.ks@gmail.com> +Date: Sun, 17 Dec 2017 07:46:20 +0400 +Subject: Qt-specific workaround for AAT shaper + +CoreText API doesn't give us a fontdata to reconstruct the original font, +so we have to store the CTFont and CGFont of interest in context object +passed to HB from native font engine +--- + src/3rdparty/harfbuzz-ng/src/hb-coretext.cc | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc +index 2dd10d2..c993ec0 100644 +--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc ++++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc +@@ -35,6 +35,20 @@ + #include "hb-coretext.h" + #include <math.h> + ++ ++typedef bool (*qt_get_font_table_func_t) (void *user_data, unsigned int tag, unsigned char *buffer, unsigned int *length); ++ ++struct FontEngineFaceData { ++ void *user_data; ++ qt_get_font_table_func_t get_font_table; ++}; ++ ++struct CoreTextFontEngineData { ++ CTFontRef ctFont; ++ CGFontRef cgFont; ++}; ++ ++ + /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ + #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f + +@@ -129,6 +143,7 @@ create_cg_font (hb_face_t *face) + } + else + { ++#if 0 + hb_blob_t *blob = hb_face_reference_blob (face); + unsigned int blob_length; + const char *blob_data = hb_blob_get_data (blob, &blob_length); +@@ -143,6 +158,11 @@ create_cg_font (hb_face_t *face) + DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); + CGDataProviderRelease (provider); + } ++#else ++ FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data; ++ CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data; ++ cg_font = CGFontRetain (coreTextFontEngineData->cgFont); ++#endif + } + return cg_font; + } +-- + diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json index a5eee600d6..0cf6a746f5 100644 --- a/src/3rdparty/harfbuzz-ng/qt_attribution.json +++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "HarfBuzz is an OpenType text shaping engine.", "Homepage": "http://harfbuzz.org", - "Version": "1.4.1", + "Version": "1.7.4", "License": "MIT License", "LicenseId": "MIT", diff --git a/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh index 100ba539e3..9343840140 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-atomic-private.hh @@ -89,9 +89,9 @@ typedef int32_t hb_atomic_int_impl_t; #define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P)) #else #if __ppc64__ || __x86_64__ || __aarch64__ -#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P)) #else -#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P)) #endif #endif @@ -124,13 +124,13 @@ typedef unsigned int hb_atomic_int_impl_t; #include <builtins.h> -static inline int hb_fetch_and_add(volatile int* AI, unsigned int V) { +static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) { __lwsync(); int result = __fetch_and_add(AI, V); __isync(); return result; } -static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) { +static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) { __sync(); int result = __compare_and_swaplp (P, &O, N); __sync(); @@ -139,10 +139,10 @@ static inline int hb_compare_and_swaplp(volatile long* P, long O, long N) { typedef int hb_atomic_int_impl_t; #define HB_ATOMIC_INT_IMPL_INIT(V) (V) -#define hb_atomic_int_impl_add(AI, V) hb_fetch_and_add (&(AI), (V)) +#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add (&(AI), (V)) #define hb_atomic_ptr_impl_get(P) (__sync(), (void *) *(P)) -#define hb_atomic_ptr_impl_cmpexch(P,O,N) hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) +#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N)) #elif !defined(HB_NO_MT) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc index fb48f03cab..59c8333637 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-blob.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-blob.cc @@ -30,6 +30,7 @@ #endif #include "hb-private.hh" +#include "hb-debug.hh" #include "hb-object-private.hh" @@ -44,12 +45,6 @@ #include <errno.h> - -#ifndef HB_DEBUG_BLOB -#define HB_DEBUG_BLOB (HB_DEBUG+0) -#endif - - struct hb_blob_t { hb_object_header_t header; ASSERT_POD (); @@ -72,8 +67,8 @@ _hb_blob_destroy_user_data (hb_blob_t *blob) { if (blob->destroy) { blob->destroy (blob->user_data); - blob->user_data = NULL; - blob->destroy = NULL; + blob->user_data = nullptr; + blob->destroy = nullptr; } } @@ -128,6 +123,12 @@ hb_blob_create (const char *data, return blob; } +static void +_hb_blob_destroy (void *data) +{ + hb_blob_destroy ((hb_blob_t *) data); +} + /** * hb_blob_create_sub_blob: * @parent: Parent blob. @@ -164,7 +165,7 @@ hb_blob_create_sub_blob (hb_blob_t *parent, MIN (length, parent->length - offset), HB_MEMORY_MODE_READONLY, hb_blob_reference (parent), - (hb_destroy_func_t) hb_blob_destroy); + _hb_blob_destroy); return blob; } @@ -188,12 +189,12 @@ hb_blob_get_empty (void) true, /* immutable */ - NULL, /* data */ + nullptr, /* data */ 0, /* length */ HB_MEMORY_MODE_READONLY, /* mode */ - NULL, /* user_data */ - NULL /* destroy */ + nullptr, /* user_data */ + nullptr /* destroy */ }; return const_cast<hb_blob_t *> (&_hb_blob_nil); @@ -373,7 +374,7 @@ hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) if (length) *length = 0; - return NULL; + return nullptr; } if (length) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh index bca308da2f..97bdc1be30 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-private.hh @@ -35,8 +35,8 @@ #include "hb-unicode-private.hh" -#ifndef HB_BUFFER_MAX_EXPANSION_FACTOR -#define HB_BUFFER_MAX_EXPANSION_FACTOR 32 +#ifndef HB_BUFFER_MAX_LEN_FACTOR +#define HB_BUFFER_MAX_LEN_FACTOR 32 #endif #ifndef HB_BUFFER_MAX_LEN_MIN #define HB_BUFFER_MAX_LEN_MIN 8192 @@ -45,11 +45,22 @@ #define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */ #endif -ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20); -ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)); +#ifndef HB_BUFFER_MAX_OPS_FACTOR +#define HB_BUFFER_MAX_OPS_FACTOR 64 +#endif +#ifndef HB_BUFFER_MAX_OPS_MIN +#define HB_BUFFER_MAX_OPS_MIN 1024 +#endif +#ifndef HB_BUFFER_MAX_OPS_DEFAULT +#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */ +#endif + +static_assert ((sizeof (hb_glyph_info_t) == 20), ""); +static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), ""); HB_MARK_AS_FLAG_T (hb_buffer_flags_t); HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); +HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t); enum hb_buffer_scratch_flags_t { HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u, @@ -57,6 +68,8 @@ enum hb_buffer_scratch_flags_t { HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, + HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK = 0x00000010u, + /* Reserved for complex shapers' internal use. */ HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u, HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u, @@ -81,6 +94,7 @@ struct hb_buffer_t { hb_codepoint_t replacement; /* U+FFFD or something else. */ hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */ unsigned int max_len; /* Maximum allowed len. */ + int max_ops; /* Maximum allowed operations. */ /* Buffer contents */ hb_buffer_content_type_t content_type; @@ -99,17 +113,6 @@ struct hb_buffer_t { hb_glyph_info_t *out_info; hb_glyph_position_t *pos; - inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; } - inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; } - - inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; } - inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; } - - inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; } - inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; } - - inline bool has_separate_output (void) const { return info != out_info; } - unsigned int serial; /* Text before / after the main buffer contents. @@ -129,6 +132,10 @@ struct hb_buffer_t { #ifndef HB_NDEBUG uint8_t allocated_var_bits; #endif + + + /* Methods */ + inline void allocate_var (unsigned int start, unsigned int count) { #ifndef HB_NDEBUG @@ -165,8 +172,17 @@ struct hb_buffer_t { #endif } + inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; } + inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; } + + inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; } + inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; } + + inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; } + inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; } + + inline bool has_separate_output (void) const { return info != out_info; } - /* Methods */ HB_INTERNAL void reset (void); HB_INTERNAL void clear (void); @@ -232,25 +248,31 @@ struct hb_buffer_t { for (unsigned int j = 0; j < len; j++) info[j].mask |= mask; } - HB_INTERNAL void set_masks (hb_mask_t value, - hb_mask_t mask, - unsigned int cluster_start, - unsigned int cluster_end); + HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask, + unsigned int cluster_start, unsigned int cluster_end); - HB_INTERNAL void merge_clusters (unsigned int start, - unsigned int end) + inline void merge_clusters (unsigned int start, unsigned int end) { if (end - start < 2) return; merge_clusters_impl (start, end); } - HB_INTERNAL void merge_clusters_impl (unsigned int start, - unsigned int end); - HB_INTERNAL void merge_out_clusters (unsigned int start, - unsigned int end); + HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end); + HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end); /* Merge clusters for deleting current glyph, and skip it. */ HB_INTERNAL void delete_glyph (void); + inline void unsafe_to_break (unsigned int start, + unsigned int end) + { + if (end - start < 2) + return; + unsafe_to_break_impl (start, end); + } + HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end); + HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end); + + /* Internal methods */ HB_INTERNAL bool enlarge (unsigned int size); @@ -282,9 +304,79 @@ struct hb_buffer_t { return ret; } HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0); + + static inline void + set_cluster (hb_glyph_info_t &info, unsigned int cluster, unsigned int mask = 0) + { + if (info.cluster != cluster) + { + if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) + info.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + else + info.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + } + info.cluster = cluster; + } + + inline int + _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *info, + unsigned int start, unsigned int end, + unsigned int cluster) const + { + for (unsigned int i = start; i < end; i++) + cluster = MIN<unsigned int> (cluster, info[i].cluster); + return cluster; + } + inline void + _unsafe_to_break_set_mask (hb_glyph_info_t *info, + unsigned int start, unsigned int end, + unsigned int cluster) + { + for (unsigned int i = start; i < end; i++) + if (cluster != info[i].cluster) + { + scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK; + info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + } + } + + inline void + unsafe_to_break_all (void) + { + for (unsigned int i = 0; i < len; i++) + info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + } + inline void + safe_to_break_all (void) + { + for (unsigned int i = 0; i < len; i++) + info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + } }; +/* Loop over clusters. Duplicated in foreach_syllable(). */ +#define foreach_cluster(buffer, start, end) \ + for (unsigned int \ + _count = buffer->len, \ + start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \ + start < _count; \ + start = end, end = _next_cluster (buffer, start)) + +static inline unsigned int +_next_cluster (hb_buffer_t *buffer, unsigned int start) +{ + hb_glyph_info_t *info = buffer->info; + unsigned int count = buffer->len; + + unsigned int cluster = info[start].cluster; + while (++start < count && cluster == info[start].cluster) + ; + + return start; +} + + #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \ b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ sizeof (b->info[0].var)) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc index 63a0f34669..ea62e9ffdb 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-serialize.cc @@ -30,7 +30,7 @@ static const char *serialize_formats[] = { "text", "json", - NULL + nullptr }; /** @@ -90,7 +90,7 @@ hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format) case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0]; case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1]; default: - case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return NULL; + case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr; } } @@ -104,9 +104,9 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, hb_font_t *font, hb_buffer_serialize_flags_t flags) { - hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr); hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? - NULL : hb_buffer_get_glyph_positions (buffer, NULL); + nullptr : hb_buffer_get_glyph_positions (buffer, nullptr); *buf_consumed = 0; for (unsigned int i = start; i < end; i++) @@ -145,10 +145,16 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS)) { - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", - pos[i].x_offset, pos[i].y_offset); - p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", - pos[i].x_advance, pos[i].y_advance); + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d", + pos[i].x_offset, pos[i].y_offset)); + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d", + pos[i].x_advance, pos[i].y_advance)); + } + + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) + { + if (info[i].mask & HB_GLYPH_FLAG_DEFINED) + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED)); } if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) @@ -156,9 +162,9 @@ _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer, hb_glyph_extents_t extents; hb_font_get_glyph_extents(font, info[i].codepoint, &extents); p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d", - extents.x_bearing, extents.y_bearing)); + extents.x_bearing, extents.y_bearing)); p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d", - extents.width, extents.height)); + extents.width, extents.height)); } *p++ = '}'; @@ -188,9 +194,9 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, hb_font_t *font, hb_buffer_serialize_flags_t flags) { - hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL); + hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr); hb_glyph_position_t *pos = (flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS) ? - NULL : hb_buffer_get_glyph_positions (buffer, NULL); + nullptr : hb_buffer_get_glyph_positions (buffer, nullptr); *buf_consumed = 0; for (unsigned int i = start; i < end; i++) @@ -226,6 +232,12 @@ _hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer, p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance)); } + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS) + { + if (info[i].mask &HB_GLYPH_FLAG_DEFINED) + p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED)); + } + if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS) { hb_glyph_extents_t extents; @@ -311,6 +323,8 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, if (!buf_consumed) buf_consumed = &sconsumed; *buf_consumed = 0; + if (buf_size) + *buf = '\0'; assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) || buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); @@ -408,8 +422,8 @@ hb_bool_t hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, const char *buf, int buf_len, /* -1 means nul-terminated */ - const char **end_ptr, /* May be NULL */ - hb_font_t *font, /* May be NULL */ + const char **end_ptr, /* May be nullptr */ + hb_font_t *font, /* May be nullptr */ hb_buffer_serialize_format_t format) { const char *end; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index 3940a3dbf8..7ead43b018 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -31,10 +31,6 @@ #include "hb-utf-private.hh" -#ifndef HB_DEBUG_BUFFER -#define HB_DEBUG_BUFFER (HB_DEBUG+0) -#endif - /** * SECTION: hb-buffer * @title: Buffers @@ -124,8 +120,8 @@ hb_buffer_t::enlarge (unsigned int size) } unsigned int new_allocated = allocated; - hb_glyph_position_t *new_pos = NULL; - hb_glyph_info_t *new_info = NULL; + hb_glyph_position_t *new_pos = nullptr; + hb_glyph_info_t *new_info = nullptr; bool separate_out = out_info != info; if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0])))) @@ -134,7 +130,7 @@ hb_buffer_t::enlarge (unsigned int size) while (size >= new_allocated) new_allocated += (new_allocated >> 1) + 32; - ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0])); + static_assert ((sizeof (info[0]) == sizeof (pos[0])), ""); if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0])))) goto done; @@ -267,7 +263,7 @@ hb_buffer_t::add (hb_codepoint_t codepoint, memset (glyph, 0, sizeof (*glyph)); glyph->codepoint = codepoint; - glyph->mask = 1; + glyph->mask = 0; glyph->cluster = cluster; len++; @@ -550,12 +546,15 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, unsigned int end) { if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) + { + unsafe_to_break (start, end); return; + } unsigned int cluster = info[start].cluster; for (unsigned int i = start + 1; i < end; i++) - cluster = MIN (cluster, info[i].cluster); + cluster = MIN<unsigned int> (cluster, info[i].cluster); /* Extend end */ while (end < len && info[end - 1].cluster == info[end].cluster) @@ -568,10 +567,10 @@ hb_buffer_t::merge_clusters_impl (unsigned int start, /* If we hit the start of buffer, continue in out-buffer. */ if (idx == start) for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--) - out_info[i - 1].cluster = cluster; + set_cluster (out_info[i - 1], cluster); for (unsigned int i = start; i < end; i++) - info[i].cluster = cluster; + set_cluster (info[i], cluster); } void hb_buffer_t::merge_out_clusters (unsigned int start, @@ -586,7 +585,7 @@ hb_buffer_t::merge_out_clusters (unsigned int start, unsigned int cluster = out_info[start].cluster; for (unsigned int i = start + 1; i < end; i++) - cluster = MIN (cluster, out_info[i].cluster); + cluster = MIN<unsigned int> (cluster, out_info[i].cluster); /* Extend start */ while (start && out_info[start - 1].cluster == out_info[start].cluster) @@ -599,14 +598,16 @@ hb_buffer_t::merge_out_clusters (unsigned int start, /* If we hit the end of out-buffer, continue in buffer. */ if (end == out_len) for (unsigned int i = idx; i < len && info[i].cluster == out_info[end - 1].cluster; i++) - info[i].cluster = cluster; + set_cluster (info[i], cluster); for (unsigned int i = start; i < end; i++) - out_info[i].cluster = cluster; + set_cluster (out_info[i], cluster); } void hb_buffer_t::delete_glyph () { + /* The logic here is duplicated in hb_ot_hide_default_ignorables(). */ + unsigned int cluster = info[idx].cluster; if (idx + 1 < len && cluster == info[idx + 1].cluster) { @@ -619,9 +620,10 @@ hb_buffer_t::delete_glyph () /* Merge cluster backward. */ if (cluster < out_info[out_len - 1].cluster) { + unsigned int mask = info[idx].mask; unsigned int old_cluster = out_info[out_len - 1].cluster; for (unsigned i = out_len; i && out_info[i - 1].cluster == old_cluster; i--) - out_info[i - 1].cluster = cluster; + set_cluster (out_info[i - 1], cluster, mask); } goto done; } @@ -638,6 +640,32 @@ done: } void +hb_buffer_t::unsafe_to_break_impl (unsigned int start, unsigned int end) +{ + unsigned int cluster = (unsigned int) -1; + cluster = _unsafe_to_break_find_min_cluster (info, start, end, cluster); + _unsafe_to_break_set_mask (info, start, end, cluster); +} +void +hb_buffer_t::unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end) +{ + if (!have_output) + { + unsafe_to_break_impl (start, end); + return; + } + + assert (start <= out_len); + assert (idx <= end); + + unsigned int cluster = (unsigned int) -1; + cluster = _unsafe_to_break_find_min_cluster (out_info, start, out_len, cluster); + cluster = _unsafe_to_break_find_min_cluster (info, idx, end, cluster); + _unsafe_to_break_set_mask (out_info, start, out_len, cluster); + _unsafe_to_break_set_mask (info, idx, end, cluster); +} + +void hb_buffer_t::guess_segment_properties (void) { assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || @@ -694,6 +722,7 @@ hb_buffer_create (void) return hb_buffer_get_empty (); buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; + buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT; buffer->reset (); @@ -721,6 +750,7 @@ hb_buffer_get_empty (void) HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT, HB_BUFFER_SCRATCH_FLAG_DEFAULT, HB_BUFFER_MAX_LEN_DEFAULT, + HB_BUFFER_MAX_OPS_DEFAULT, HB_BUFFER_CONTENT_TYPE_INVALID, HB_SEGMENT_PROPERTIES_DEFAULT, @@ -1380,6 +1410,23 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer, } /** + * hb_glyph_info_get_glyph_flags: + * @info: a #hb_glyph_info_t. + * + * Returns glyph flags encoded within a #hb_glyph_info_t. + * + * Return value: + * The #hb_glyph_flags_t encoded within @info. + * + * Since: 1.5.0 + **/ +hb_glyph_flags_t +(hb_glyph_info_get_glyph_flags) (const hb_glyph_info_t *info) +{ + return hb_glyph_info_get_glyph_flags (info); +} + +/** * hb_buffer_reverse: * @buffer: an #hb_buffer_t. * @@ -1666,6 +1713,58 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer, } +/** + * hb_buffer_append: + * @buffer: an #hb_buffer_t. + * @source: source #hb_buffer_t. + * @start: start index into source buffer to copy. Use 0 to copy from start of buffer. + * @end: end index into source buffer to copy. Use (unsigned int) -1 to copy to end of buffer. + * + * Append (part of) contents of another buffer to this buffer. + * + * Since: 1.5.0 + **/ +HB_EXTERN void +hb_buffer_append (hb_buffer_t *buffer, + hb_buffer_t *source, + unsigned int start, + unsigned int end) +{ + assert (!buffer->have_output && !source->have_output); + assert (buffer->have_positions == source->have_positions || + !buffer->len || !source->len); + assert (buffer->content_type == source->content_type || + !buffer->len || !source->len); + + if (end > source->len) + end = source->len; + if (start > end) + start = end; + if (start == end) + return; + + if (!buffer->len) + buffer->content_type = source->content_type; + if (!buffer->have_positions && source->have_positions) + buffer->clear_positions (); + + if (buffer->len + (end - start) < buffer->len) /* Overflows. */ + { + buffer->in_error = true; + return; + } + + unsigned int orig_len = buffer->len; + hb_buffer_set_length (buffer, buffer->len + (end - start)); + if (buffer->in_error) + return; + + memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); + if (buffer->have_positions) + memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); +} + + static int compare_info_codepoint (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb) @@ -1736,7 +1835,8 @@ void hb_buffer_normalize_glyphs (hb_buffer_t *buffer) { assert (buffer->have_positions); - assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS); + assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS || + (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); @@ -1775,6 +1875,98 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g } } + +/* + * Comparing buffers. + */ + +/** + * hb_buffer_diff: + * + * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT + * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most + * callers if just comparing two buffers is needed. + * + * Since: 1.5.0 + **/ +hb_buffer_diff_flags_t +hb_buffer_diff (hb_buffer_t *buffer, + hb_buffer_t *reference, + hb_codepoint_t dottedcircle_glyph, + unsigned int position_fuzz) +{ + if (buffer->content_type != reference->content_type && buffer->len && reference->len) + return HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH; + + hb_buffer_diff_flags_t result = HB_BUFFER_DIFF_FLAG_EQUAL; + bool contains = dottedcircle_glyph != (hb_codepoint_t) -1; + + unsigned int count = reference->len; + + if (buffer->len != count) + { + /* + * we can't compare glyph-by-glyph, but we do want to know if there + * are .notdef or dottedcircle glyphs present in the reference buffer + */ + const hb_glyph_info_t *info = reference->info; + unsigned int i; + for (i = 0; i < count; i++) + { + if (contains && info[i].codepoint == dottedcircle_glyph) + result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; + if (contains && info[i].codepoint == 0) + result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT; + } + result |= HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH; + return hb_buffer_diff_flags_t (result); + } + + if (!count) + return hb_buffer_diff_flags_t (result); + + const hb_glyph_info_t *buf_info = buffer->info; + const hb_glyph_info_t *ref_info = reference->info; + for (unsigned int i = 0; i < count; i++) + { + if (buf_info->codepoint != ref_info->codepoint) + result |= HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH; + if (buf_info->cluster != ref_info->cluster) + result |= HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH; + if ((buf_info->mask & HB_GLYPH_FLAG_DEFINED) != (ref_info->mask & HB_GLYPH_FLAG_DEFINED)) + result |= HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH; + if (contains && ref_info->codepoint == dottedcircle_glyph) + result |= HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT; + if (contains && ref_info->codepoint == 0) + result |= HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT; + buf_info++; + ref_info++; + } + + if (buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS) + { + assert (buffer->have_positions); + const hb_glyph_position_t *buf_pos = buffer->pos; + const hb_glyph_position_t *ref_pos = reference->pos; + for (unsigned int i = 0; i < count; i++) + { + if ((unsigned int) abs (buf_pos->x_advance - ref_pos->x_advance) > position_fuzz || + (unsigned int) abs (buf_pos->y_advance - ref_pos->y_advance) > position_fuzz || + (unsigned int) abs (buf_pos->x_offset - ref_pos->x_offset) > position_fuzz || + (unsigned int) abs (buf_pos->y_offset - ref_pos->y_offset) > position_fuzz) + { + result |= HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH; + break; + } + buf_pos++; + ref_pos++; + } + } + + return result; +} + + /* * Debugging. */ @@ -1803,9 +1995,9 @@ hb_buffer_set_message_func (hb_buffer_t *buffer, buffer->message_data = user_data; buffer->message_destroy = destroy; } else { - buffer->message_func = NULL; - buffer->message_data = NULL; - buffer->message_destroy = NULL; + buffer->message_func = nullptr; + buffer->message_data = nullptr; + buffer->message_destroy = nullptr; } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h index bf289c19b3..a8a4b84e97 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.h @@ -63,7 +63,7 @@ HB_BEGIN_DECLS */ typedef struct hb_glyph_info_t { hb_codepoint_t codepoint; - hb_mask_t mask; + hb_mask_t mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */ uint32_t cluster; /*< private >*/ @@ -71,6 +71,19 @@ typedef struct hb_glyph_info_t { hb_var_int_t var2; } hb_glyph_info_t; +typedef enum { /*< flags >*/ + HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001, + + HB_GLYPH_FLAG_DEFINED = 0x00000001 /* OR of all defined flags */ +} hb_glyph_flags_t; + +HB_EXTERN hb_glyph_flags_t +hb_glyph_info_get_glyph_flags (const hb_glyph_info_t *info); + +#define hb_glyph_info_get_glyph_flags(info) \ + ((hb_glyph_flags_t) ((unsigned int) (info)->mask & HB_GLYPH_FLAG_DEFINED)) + + /** * hb_glyph_position_t: * @x_advance: how much the line advances after drawing this glyph when setting @@ -119,8 +132,8 @@ typedef struct hb_segment_properties_t { #define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \ HB_SCRIPT_INVALID, \ HB_LANGUAGE_INVALID, \ - NULL, \ - NULL} + (void *) 0, \ + (void *) 0} HB_EXTERN hb_bool_t hb_segment_properties_equal (const hb_segment_properties_t *a, @@ -163,6 +176,7 @@ HB_EXTERN void * hb_buffer_get_user_data (hb_buffer_t *buffer, hb_user_data_key_t *key); + /** * hb_buffer_content_type_t: * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer. @@ -359,6 +373,11 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer, unsigned int item_offset, int item_length); +HB_EXTERN void +hb_buffer_append (hb_buffer_t *buffer, + hb_buffer_t *source, + unsigned int start, + unsigned int end); HB_EXTERN hb_bool_t hb_buffer_set_length (hb_buffer_t *buffer, @@ -403,7 +422,8 @@ typedef enum { /*< flags >*/ HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001u, HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002u, HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u, - HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u + HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u, + HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u } hb_buffer_serialize_flags_t; /** @@ -453,6 +473,45 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, /* + * Compare buffers + */ + +typedef enum { /*< flags >*/ + HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000, + + /* Buffers with different content_type cannot be meaningfully compared + * in any further detail. */ + HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH = 0x0001, + + /* For buffers with differing length, the per-glyph comparison is not + * attempted, though we do still scan reference for dottedcircle / .notdef + * glyphs. */ + HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH = 0x0002, + + /* We want to know if dottedcircle / .notdef glyphs are present in the + * reference, as we may not care so much about other differences in this + * case. */ + HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT = 0x0004, + HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT = 0x0008, + + /* If the buffers have the same length, we compare them glyph-by-glyph + * and report which aspect(s) of the glyph info/position are different. */ + HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH = 0x0010, + HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH = 0x0020, + HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH = 0x0040, + HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH = 0x0080 + +} hb_buffer_diff_flags_t; + +/* Compare the contents of two buffers, report types of differences. */ +HB_EXTERN hb_buffer_diff_flags_t +hb_buffer_diff (hb_buffer_t *buffer, + hb_buffer_t *reference, + hb_codepoint_t dottedcircle_glyph, + unsigned int position_fuzz); + + +/* * Debugging. */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.cc b/src/3rdparty/harfbuzz-ng/src/hb-common.cc index 3564e43557..cb1fb43ffb 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-common.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.cc @@ -32,6 +32,9 @@ #include "hb-object-private.hh" #include <locale.h> +#ifdef HAVE_XLOCALE_H +#include <xlocale.h> +#endif /* hb_options_t */ @@ -82,7 +85,7 @@ hb_tag_from_string (const char *str, int len) for (; i < 4; i++) tag[i] = ' '; - return HB_TAG_CHAR4 (tag); + return HB_TAG (tag[0], tag[1], tag[2], tag[3]); } /** @@ -186,8 +189,10 @@ lang_equal (hb_language_t v1, const unsigned char *p1 = (const unsigned char *) v1; const unsigned char *p2 = (const unsigned char *) v2; - while (*p1 && *p1 == canon_map[*p2]) - p1++, p2++; + while (*p1 && *p1 == canon_map[*p2]) { + p1++; + p2++; + } return *p1 == canon_map[*p2]; } @@ -219,9 +224,18 @@ struct hb_language_item_t { } inline hb_language_item_t & operator = (const char *s) { - lang = (hb_language_t) strdup (s); - for (unsigned char *p = (unsigned char *) lang; *p; p++) - *p = canon_map[*p]; + /* If a custom allocated is used calling strdup() pairs + badly with a call to the custom free() in finish() below. + Therefore don't call strdup(), implement its behavior. + */ + size_t len = strlen(s) + 1; + lang = (hb_language_t) malloc(len); + if (likely (lang)) + { + memcpy((unsigned char *) lang, s, len); + for (unsigned char *p = (unsigned char *) lang; *p; p++) + *p = canon_map[*p]; + } return *this; } @@ -235,8 +249,8 @@ struct hb_language_item_t { static hb_language_item_t *langs; #ifdef HB_USE_ATEXIT -static -void free_langs (void) +static void +free_langs (void) { while (langs) { hb_language_item_t *next = langs->next; @@ -260,9 +274,14 @@ retry: /* Not found; allocate one. */ hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t)); if (unlikely (!lang)) - return NULL; + return nullptr; lang->next = first_lang; *lang = key; + if (unlikely (!lang->lang)) + { + free (lang); + return nullptr; + } if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) { lang->finish (); @@ -299,7 +318,7 @@ hb_language_from_string (const char *str, int len) if (!str || !len || !*str) return HB_LANGUAGE_INVALID; - hb_language_item_t *item = NULL; + hb_language_item_t *item = nullptr; if (len >= 0) { /* NUL-terminate it. */ @@ -330,7 +349,7 @@ hb_language_from_string (const char *str, int len) const char * hb_language_to_string (hb_language_t language) { - /* This is actually NULL-safe! */ + /* This is actually nullptr-safe! */ return language->s; } @@ -350,7 +369,7 @@ hb_language_get_default (void) hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language); if (unlikely (language == HB_LANGUAGE_INVALID)) { - language = hb_language_from_string (setlocale (LC_CTYPE, NULL), -1); + language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1); (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language); } @@ -543,9 +562,9 @@ hb_user_data_array_t::set (hb_user_data_key_t *key, void * hb_user_data_array_t::get (hb_user_data_key_t *key) { - hb_user_data_item_t item = {NULL, NULL, NULL}; + hb_user_data_item_t item = {nullptr, nullptr, nullptr}; - return items.find (key, &item, lock) ? item.data : NULL; + return items.find (key, &item, lock) ? item.data : nullptr; } @@ -605,3 +624,426 @@ hb_version_atleast (unsigned int major, { return HB_VERSION_ATLEAST (major, minor, micro); } + + + +/* hb_feature_t and hb_variation_t */ + +static bool +parse_space (const char **pp, const char *end) +{ + while (*pp < end && ISSPACE (**pp)) + (*pp)++; + return true; +} + +static bool +parse_char (const char **pp, const char *end, char c) +{ + parse_space (pp, end); + + if (*pp == end || **pp != c) + return false; + + (*pp)++; + return true; +} + +static bool +parse_uint (const char **pp, const char *end, unsigned int *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + unsigned int v; + + /* Intentionally use strtol instead of strtoul, such that + * -1 turns into "big number"... */ + errno = 0; + v = strtol (p, &pend, 0); + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +static bool +parse_uint32 (const char **pp, const char *end, uint32_t *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + unsigned int v; + + /* Intentionally use strtol instead of strtoul, such that + * -1 turns into "big number"... */ + errno = 0; + v = strtol (p, &pend, 0); + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L) +#define USE_XLOCALE 1 +#define HB_LOCALE_T locale_t +#define HB_CREATE_LOCALE(locName) newlocale (LC_ALL_MASK, locName, nullptr) +#define HB_FREE_LOCALE(loc) freelocale (loc) +#elif defined(_MSC_VER) +#define USE_XLOCALE 1 +#define HB_LOCALE_T _locale_t +#define HB_CREATE_LOCALE(locName) _create_locale (LC_ALL, locName) +#define HB_FREE_LOCALE(loc) _free_locale (loc) +#define strtod_l(a, b, c) _strtod_l ((a), (b), (c)) +#endif + +#ifdef USE_XLOCALE + +static HB_LOCALE_T C_locale; + +#ifdef HB_USE_ATEXIT +static void +free_C_locale (void) +{ + if (C_locale) + HB_FREE_LOCALE (C_locale); +} +#endif + +static HB_LOCALE_T +get_C_locale (void) +{ +retry: + HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale); + + if (unlikely (!C)) + { + C = HB_CREATE_LOCALE ("C"); + + if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C)) + { + HB_FREE_LOCALE (C_locale); + goto retry; + } + +#ifdef HB_USE_ATEXIT + atexit (free_C_locale); /* First person registers atexit() callback. */ +#endif + } + + return C; +} +#endif + +static bool +parse_float (const char **pp, const char *end, float *pv) +{ + char buf[32]; + unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); + strncpy (buf, *pp, len); + buf[len] = '\0'; + + char *p = buf; + char *pend = p; + float v; + + errno = 0; +#ifdef USE_XLOCALE + v = strtod_l (p, &pend, get_C_locale ()); +#else + v = strtod (p, &pend); +#endif + if (errno || p == pend) + return false; + + *pv = v; + *pp += pend - p; + return true; +} + +static bool +parse_bool (const char **pp, const char *end, uint32_t *pv) +{ + parse_space (pp, end); + + const char *p = *pp; + while (*pp < end && ISALPHA(**pp)) + (*pp)++; + + /* CSS allows on/off as aliases 1/0. */ + if (*pp - p == 2 && 0 == strncmp (p, "on", 2)) + *pv = 1; + else if (*pp - p == 3 && 0 == strncmp (p, "off", 3)) + *pv = 0; + else + return false; + + return true; +} + +/* hb_feature_t */ + +static bool +parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) +{ + if (parse_char (pp, end, '-')) + feature->value = 0; + else { + parse_char (pp, end, '+'); + feature->value = 1; + } + + return true; +} + +static bool +parse_tag (const char **pp, const char *end, hb_tag_t *tag) +{ + parse_space (pp, end); + + char quote = 0; + + if (*pp < end && (**pp == '\'' || **pp == '"')) + { + quote = **pp; + (*pp)++; + } + + const char *p = *pp; + while (*pp < end && ISALNUM(**pp)) + (*pp)++; + + if (p == *pp || *pp - p > 4) + return false; + + *tag = hb_tag_from_string (p, *pp - p); + + if (quote) + { + /* CSS expects exactly four bytes. And we only allow quotations for + * CSS compatibility. So, enforce the length. */ + if (*pp - p != 4) + return false; + if (*pp == end || **pp != quote) + return false; + (*pp)++; + } + + return true; +} + +static bool +parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) +{ + parse_space (pp, end); + + bool has_start; + + feature->start = 0; + feature->end = (unsigned int) -1; + + if (!parse_char (pp, end, '[')) + return true; + + has_start = parse_uint (pp, end, &feature->start); + + if (parse_char (pp, end, ':')) { + parse_uint (pp, end, &feature->end); + } else { + if (has_start) + feature->end = feature->start + 1; + } + + return parse_char (pp, end, ']'); +} + +static bool +parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) +{ + bool had_equal = parse_char (pp, end, '='); + bool had_value = parse_uint32 (pp, end, &feature->value) || + parse_bool (pp, end, &feature->value); + /* CSS doesn't use equal-sign between tag and value. + * If there was an equal-sign, then there *must* be a value. + * A value without an eqaul-sign is ok, but not required. */ + return !had_equal || had_value; +} + +static bool +parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) +{ + return parse_feature_value_prefix (pp, end, feature) && + parse_tag (pp, end, &feature->tag) && + parse_feature_indices (pp, end, feature) && + parse_feature_value_postfix (pp, end, feature) && + parse_space (pp, end) && + *pp == end; +} + +/** + * hb_feature_from_string: + * @str: (array length=len) (element-type uint8_t): a string to parse + * @len: length of @str, or -1 if string is %NULL terminated + * @feature: (out): the #hb_feature_t to initialize with the parsed values + * + * Parses a string into a #hb_feature_t. + * + * TODO: document the syntax here. + * + * Return value: + * %true if @str is successfully parsed, %false otherwise. + * + * Since: 0.9.5 + **/ +hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature) +{ + hb_feature_t feat; + + if (len < 0) + len = strlen (str); + + if (likely (parse_one_feature (&str, str + len, &feat))) + { + if (feature) + *feature = feat; + return true; + } + + if (feature) + memset (feature, 0, sizeof (*feature)); + return false; +} + +/** + * hb_feature_to_string: + * @feature: an #hb_feature_t to convert + * @buf: (array length=size) (out): output string + * @size: the allocated size of @buf + * + * Converts a #hb_feature_t into a %NULL-terminated string in the format + * understood by hb_feature_from_string(). The client in responsible for + * allocating big enough size for @buf, 128 bytes is more than enough. + * + * Since: 0.9.5 + **/ +void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size) +{ + if (unlikely (!size)) return; + + char s[128]; + unsigned int len = 0; + if (feature->value == 0) + s[len++] = '-'; + hb_tag_to_string (feature->tag, s + len); + len += 4; + while (len && s[len - 1] == ' ') + len--; + if (feature->start != 0 || feature->end != (unsigned int) -1) + { + s[len++] = '['; + if (feature->start) + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); + if (feature->end != feature->start + 1) { + s[len++] = ':'; + if (feature->end != (unsigned int) -1) + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); + } + s[len++] = ']'; + } + if (feature->value > 1) + { + s[len++] = '='; + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); + } + assert (len < ARRAY_LENGTH (s)); + len = MIN (len, size - 1); + memcpy (buf, s, len); + buf[len] = '\0'; +} + +/* hb_variation_t */ + +static bool +parse_variation_value (const char **pp, const char *end, hb_variation_t *variation) +{ + parse_char (pp, end, '='); /* Optional. */ + return parse_float (pp, end, &variation->value); +} + +static bool +parse_one_variation (const char **pp, const char *end, hb_variation_t *variation) +{ + return parse_tag (pp, end, &variation->tag) && + parse_variation_value (pp, end, variation) && + parse_space (pp, end) && + *pp == end; +} + +/** + * hb_variation_from_string: + * + * Since: 1.4.2 + */ +hb_bool_t +hb_variation_from_string (const char *str, int len, + hb_variation_t *variation) +{ + hb_variation_t var; + + if (len < 0) + len = strlen (str); + + if (likely (parse_one_variation (&str, str + len, &var))) + { + if (variation) + *variation = var; + return true; + } + + if (variation) + memset (variation, 0, sizeof (*variation)); + return false; +} + +/** + * hb_variation_to_string: + * + * Since: 1.4.2 + */ +void +hb_variation_to_string (hb_variation_t *variation, + char *buf, unsigned int size) +{ + if (unlikely (!size)) return; + + char s[128]; + unsigned int len = 0; + hb_tag_to_string (variation->tag, s + len); + len += 4; + while (len && s[len - 1] == ' ') + len--; + s[len++] = '='; + len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value)); + + assert (len < ARRAY_LENGTH (s)); + len = MIN (len, size - 1); + memcpy (buf, s, len); + buf[len] = '\0'; +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-common.h b/src/3rdparty/harfbuzz-ng/src/hb-common.h index 2cbee76a8f..26200ce125 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-common.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-common.h @@ -43,30 +43,16 @@ # endif /* !__cplusplus */ #endif -#if !defined (HB_DONT_DEFINE_STDINT) - #if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \ defined (_sgi) || defined (__sun) || defined (sun) || \ defined (__digital__) || defined (__HP_cc) # include <inttypes.h> #elif defined (_AIX) # include <sys/inttypes.h> -/* VS 2010 (_MSC_VER 1600) has stdint.h */ -#elif defined (_MSC_VER) && _MSC_VER < 1600 -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; #else # include <stdint.h> #endif -#endif - HB_BEGIN_DECLS @@ -148,7 +134,7 @@ hb_language_from_string (const char *str, int len); HB_EXTERN const char * hb_language_to_string (hb_language_t language); -#define HB_LANGUAGE_INVALID ((hb_language_t) NULL) +#define HB_LANGUAGE_INVALID ((hb_language_t) 0) HB_EXTERN hb_language_t hb_language_get_default (void); @@ -321,6 +307,14 @@ typedef enum /*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), + /* + * Since 1.6.0 + */ + /*10.0*/HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), + /*10.0*/HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), + /*10.0*/HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), + /*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), + /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, @@ -362,6 +356,42 @@ typedef struct hb_user_data_key_t { typedef void (*hb_destroy_func_t) (void *user_data); +/* Font features and variations. */ + +typedef struct hb_feature_t { + hb_tag_t tag; + uint32_t value; + unsigned int start; + unsigned int end; +} hb_feature_t; + +HB_EXTERN hb_bool_t +hb_feature_from_string (const char *str, int len, + hb_feature_t *feature); + +HB_EXTERN void +hb_feature_to_string (hb_feature_t *feature, + char *buf, unsigned int size); + +/** + * hb_variation_t: + * + * Since: 1.4.2 + */ +typedef struct hb_variation_t { + hb_tag_t tag; + float value; +} hb_variation_t; + +HB_EXTERN hb_bool_t +hb_variation_from_string (const char *str, int len, + hb_variation_t *variation); + +HB_EXTERN void +hb_variation_to_string (hb_variation_t *variation, + char *buf, unsigned int size); + + HB_END_DECLS #endif /* HB_COMMON_H */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc index 9865bbba41..9431ba5fe1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc @@ -27,14 +27,13 @@ */ #define HB_SHAPER coretext + +#include "hb-private.hh" +#include "hb-debug.hh" #include "hb-shaper-impl-private.hh" #include "hb-coretext.h" - - -#ifndef HB_DEBUG_CORETEXT -#define HB_DEBUG_CORETEXT (HB_DEBUG+0) -#endif +#include <math.h> typedef bool (*qt_get_font_table_func_t) (void *user_data, unsigned int tag, unsigned char *buffer, unsigned int *length); @@ -50,6 +49,27 @@ struct CoreTextFontEngineData { }; +/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */ +#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f + +static CGFloat +coretext_font_size_from_ptem (float ptem) +{ + /* CoreText points are CSS pixels (96 per inch), + * NOT typographic points (72 per inch). + * + * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html + */ + ptem *= 96.f / 72.f; + return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem; +} +static float +coretext_font_size_to_ptem (CGFloat size) +{ + size *= 72.f / 96.f; + return size <= 0.f ? 0 : size; +} + static void release_table_data (void *user_data) { @@ -63,32 +83,29 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) CGFontRef cg_font = reinterpret_cast<CGFontRef> (user_data); CFDataRef cf_data = CGFontCopyTableForTag (cg_font, tag); if (unlikely (!cf_data)) - return NULL; + return nullptr; const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data)); const size_t length = CFDataGetLength (cf_data); if (!data || !length) - return NULL; + return nullptr; return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY, reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)), release_table_data); } -hb_face_t * -hb_coretext_face_create (CGFontRef cg_font) +static void +_hb_cg_font_release (void *data) { - return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), (hb_destroy_func_t) CGFontRelease); + CGFontRelease ((CGFontRef) data); } -HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face) -HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font) - - -/* - * shaper face data - */ +HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face) +HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font, + fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5 +) static CTFontDescriptorRef get_last_resort_font_desc (void) @@ -117,7 +134,7 @@ static void release_data (void *info, const void *data, size_t size) { assert (hb_blob_get_length ((hb_blob_t *) info) == size && - hb_blob_get_data ((hb_blob_t *) info, NULL) == data); + hb_blob_get_data ((hb_blob_t *) info, nullptr) == data); hb_blob_destroy ((hb_blob_t *) info); } @@ -125,14 +142,14 @@ release_data (void *info, const void *data, size_t size) static CGFontRef create_cg_font (hb_face_t *face) { - CGFontRef cg_font = NULL; -#if 0 - if (face->destroy == (hb_destroy_func_t) CGFontRelease) + CGFontRef cg_font = nullptr; + if (face->destroy == _hb_cg_font_release) { cg_font = CGFontRetain ((CGFontRef) face->user_data); } else { +#if 0 hb_blob_t *blob = hb_face_reference_blob (face); unsigned int blob_length; const char *blob_data = hb_blob_get_data (blob, &blob_length); @@ -147,22 +164,48 @@ create_cg_font (hb_face_t *face) DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed"); CGDataProviderRelease (provider); } - } #else - FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data; - CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data; - cg_font = CGFontRetain (coreTextFontEngineData->cgFont); + FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data; + CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data; + cg_font = CGFontRetain (coreTextFontEngineData->cgFont); #endif + } return cg_font; } static CTFontRef create_ct_font (CGFontRef cg_font, CGFloat font_size) { - CTFontRef ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, NULL, NULL); + CTFontRef ct_font = nullptr; + + /* CoreText does not enable trak table usage / tracking when creating a CTFont + * using CTFontCreateWithGraphicsFont. The only way of enabling tracking seems + * to be through the CTFontCreateUIFontForLanguage call. */ + CFStringRef cg_postscript_name = CGFontCopyPostScriptName (cg_font); + if (CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSText")) || + CFStringHasPrefix (cg_postscript_name, CFSTR (".SFNSDisplay"))) + { + CTFontUIFontType font_type = kCTFontUIFontSystem; + if (CFStringHasSuffix (cg_postscript_name, CFSTR ("-Bold"))) + font_type = kCTFontUIFontEmphasizedSystem; + + ct_font = CTFontCreateUIFontForLanguage (font_type, font_size, nullptr); + CFStringRef ct_result_name = CTFontCopyPostScriptName(ct_font); + if (CFStringCompare (ct_result_name, cg_postscript_name, 0) != kCFCompareEqualTo) + { + CFRelease(ct_font); + ct_font = nullptr; + } + CFRelease (ct_result_name); + } + CFRelease (cg_postscript_name); + + if (!ct_font) + ct_font = CTFontCreateWithGraphicsFont (cg_font, font_size, nullptr, nullptr); + if (unlikely (!ct_font)) { DEBUG_MSG (CORETEXT, cg_font, "Font CTFontCreateWithGraphicsFont() failed"); - return NULL; + return nullptr; } /* crbug.com/576941 and crbug.com/625902 and the investigation in the latter @@ -172,7 +215,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * reconfiguring the cascade list causes CoreText crashes. For details, see * crbug.com/549610 */ // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h - if (&CTGetCoreTextVersion != NULL && CTGetCoreTextVersion() < 0x00070000) { + if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) { CFStringRef fontName = CTFontCopyPostScriptName (ct_font); bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo; CFRelease (fontName); @@ -186,7 +229,7 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * font fallback which we don't need anyway. */ { CTFontDescriptorRef last_resort_font_desc = get_last_resort_font_desc (); - CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, NULL, last_resort_font_desc); + CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, last_resort_font_desc); CFRelease (last_resort_font_desc); if (new_ct_font) { @@ -221,51 +264,30 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) return ct_font; } -struct hb_coretext_shaper_face_data_t { - CGFontRef cg_font; - CTFontRef ct_font; -}; - hb_coretext_shaper_face_data_t * _hb_coretext_shaper_face_data_create (hb_face_t *face) { - hb_coretext_shaper_face_data_t *data = (hb_coretext_shaper_face_data_t *) calloc (1, sizeof (hb_coretext_shaper_face_data_t)); - if (unlikely (!data)) - return NULL; + CGFontRef cg_font = create_cg_font (face); - data->cg_font = create_cg_font (face); - if (unlikely (!data->cg_font)) + if (unlikely (!cg_font)) { DEBUG_MSG (CORETEXT, face, "CGFont creation failed.."); - free (data); - return NULL; + return nullptr; } - /* We use 36pt size instead of UPEM, because CoreText implements the 'trak' table, - * which can make the font too tight at large sizes. 36pt should be a good semi-neutral - * size. - * - * Since we always create CTFont at a fixed size, our CTFont lives in face_data - * instead of font_data. Which is good, because when people change scale on - * hb_font_t, we won't need to update our CTFont. */ - data->ct_font = create_ct_font (data->cg_font, 36.); - if (unlikely (!data->ct_font)) - { - DEBUG_MSG (CORETEXT, face, "CTFont creation failed."); - CFRelease (data->cg_font); - free (data); - return NULL; - } - - return data; + return (hb_coretext_shaper_face_data_t *) cg_font; } void _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) { - CFRelease (data->ct_font); - CFRelease (data->cg_font); - free (data); + CFRelease ((CGFontRef) data); +} + +hb_face_t * +hb_coretext_face_create (CGFontRef cg_font) +{ + return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release); } /* @@ -274,29 +296,66 @@ _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data) CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face) { - if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return face_data->cg_font; + if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; + return (CGFontRef) HB_SHAPER_DATA_GET (face); } -/* - * shaper font data - */ - -struct hb_coretext_shaper_font_data_t {}; - hb_coretext_shaper_font_data_t * -_hb_coretext_shaper_font_data_create (hb_font_t *font HB_UNUSED) +_hb_coretext_shaper_font_data_create (hb_font_t *font) { - return (hb_coretext_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; + hb_face_t *face = font->face; + if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr; + CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); + + CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem)); + + if (unlikely (!ct_font)) + { + DEBUG_MSG (CORETEXT, font, "CGFont creation failed.."); + return nullptr; + } + + return (hb_coretext_shaper_font_data_t *) ct_font; } void _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data) { + CFRelease ((CTFontRef) data); } +/* + * Since: 1.7.2 + */ +hb_font_t * +hb_coretext_font_create (CTFontRef ct_font) +{ + CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, 0); + hb_face_t *face = hb_coretext_face_create (cg_font); + CFRelease (cg_font); + hb_font_t *font = hb_font_create (face); + hb_face_destroy (face); + + if (unlikely (hb_object_is_inert (font))) + return font; + + hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font))); + + /* Let there be dragons here... */ + HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font); + + return font; +} + +CTFontRef +hb_coretext_font_get_ct_font (hb_font_t *font) +{ + if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr; + return (CTFontRef) HB_SHAPER_DATA_GET (font); +} + + /* * shaper shape_plan data @@ -319,15 +378,6 @@ _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_ { } -CTFontRef -hb_coretext_font_get_ct_font (hb_font_t *font) -{ - hb_face_t *face = font->face; - if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return NULL; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); - return face_data->ct_font; -} - /* * shaper @@ -342,7 +392,9 @@ struct active_feature_t { feature_record_t rec; unsigned int order; - static int cmp (const active_feature_t *a, const active_feature_t *b) { + static int cmp (const void *pa, const void *pb) { + const active_feature_t *a = (const active_feature_t *) pa; + const active_feature_t *b = (const active_feature_t *) pb; return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 : a->order < b->order ? -1 : a->order > b->order ? 1 : a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 : @@ -358,7 +410,9 @@ struct feature_event_t { bool start; active_feature_t feature; - static int cmp (const feature_event_t *a, const feature_event_t *b) { + static int cmp (const void *pa, const void *pb) { + const feature_event_t *a = (const feature_event_t *) pa; + const feature_event_t *b = (const feature_event_t *) pb; return a->index < b->index ? -1 : a->index > b->index ? 1 : a->start < b->start ? -1 : a->start > b->start ? 1 : active_feature_t::cmp (&a->feature, &b->feature); @@ -557,9 +611,10 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, unsigned int num_features) { hb_face_t *face = font->face; - hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face); + CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face); + CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font); - CGFloat ct_font_size = CTFontGetSize (face_data->ct_font); + CGFloat ct_font_size = CTFontGetSize (ct_font); CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size; CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size; @@ -660,22 +715,23 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, /* active_features.qsort (); */ for (unsigned int j = 0; j < active_features.len; j++) { - CFStringRef keys[2] = { + CFStringRef keys[] = { kCTFontFeatureTypeIdentifierKey, kCTFontFeatureSelectorIdentifierKey }; - CFNumberRef values[2] = { + CFNumberRef values[] = { CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.feature), CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &active_features[j].rec.setting) }; + static_assert ((ARRAY_LENGTH_CONST (keys) == ARRAY_LENGTH_CONST (values)), ""); CFDictionaryRef dict = CFDictionaryCreate (kCFAllocatorDefault, (const void **) keys, (const void **) values, - 2, + ARRAY_LENGTH (keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease (values[0]); - CFRelease (values[1]); + for (unsigned int i = 0; i < ARRAY_LENGTH (values); i++) + CFRelease (values[i]); CFArrayAppendValue (features_array, dict); CFRelease (dict); @@ -693,12 +749,12 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, CTFontDescriptorRef font_desc = CTFontDescriptorCreateWithAttributes (attributes); CFRelease (attributes); - range->font = CTFontCreateCopyWithAttributes (face_data->ct_font, 0.0, NULL, font_desc); + range->font = CTFontCreateCopyWithAttributes (ct_font, 0.0, nullptr, font_desc); CFRelease (font_desc); } else { - range->font = NULL; + range->font = nullptr; } range->index_first = last_index; @@ -718,9 +774,6 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, active_features.remove (feature - active_features.array); } } - - if (!range_records.len) /* No active feature found. */ - goto fail_features; } else { @@ -771,14 +824,14 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, #define FAIL(...) \ HB_STMT_START { \ - DEBUG_MSG (CORETEXT, NULL, __VA_ARGS__); \ + DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \ ret = false; \ goto fail; \ } HB_STMT_END; bool ret = true; - CFStringRef string_ref = NULL; - CTLineRef line = NULL; + CFStringRef string_ref = nullptr; + CTLineRef line = nullptr; if (0) { @@ -790,8 +843,8 @@ resize_and_retry: assert (line); CFRelease (string_ref); CFRelease (line); - string_ref = NULL; - line = NULL; + string_ref = nullptr; + line = nullptr; /* Get previous start-of-scratch-area, that we use later for readjusting * our existing scratch arrays. */ @@ -812,7 +865,7 @@ resize_and_retry: scratch_size -= old_scratch_used; } { - string_ref = CFStringCreateWithCharactersNoCopy (NULL, + string_ref = CFStringCreateWithCharactersNoCopy (nullptr, pchars, chars_len, kCFAllocatorNull); if (unlikely (!string_ref)) @@ -850,9 +903,9 @@ resize_and_retry: CFRelease (lang); } CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len), - kCTFontAttributeName, face_data->ct_font); + kCTFontAttributeName, ct_font); - if (num_features) + if (num_features && range_records.len) { unsigned int start = 0; range_record_t *last_range = &range_records[0]; @@ -878,6 +931,30 @@ resize_and_retry: CFAttributedStringSetAttribute (attr_string, CFRangeMake (start, chars_len - start), kCTFontAttributeName, last_range->font); } + /* Enable/disable kern if requested. + * + * Note: once kern is disabled, reenabling it doesn't currently seem to work in CoreText. + */ + if (num_features) + { + unsigned int zeroint = 0; + CFNumberRef zero = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &zeroint); + for (unsigned int i = 0; i < num_features; i++) + { + const hb_feature_t &feature = features[i]; + if (feature.tag == HB_TAG('k','e','r','n') && + feature.start < chars_len && feature.start < feature.end) + { + CFRange feature_range = CFRangeMake (feature.start, + MIN (feature.end, chars_len) - feature.start); + if (feature.value) + CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName); + else + CFAttributedStringSetAttribute (attr_string, feature_range, kCTKernAttributeName, zero); + } + } + CFRelease (zero); + } int level = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; CFNumberRef level_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &level); @@ -887,6 +964,7 @@ resize_and_retry: 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease (level_number); if (unlikely (!options)) FAIL ("CFDictionaryCreate failed"); @@ -904,7 +982,7 @@ resize_and_retry: CFArrayRef glyph_runs = CTLineGetGlyphRuns (line); unsigned int num_runs = CFArrayGetCount (glyph_runs); - DEBUG_MSG (CORETEXT, NULL, "Num runs: %d", num_runs); + DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs); buffer->len = 0; uint32_t status_and = ~0, status_or = 0; @@ -930,7 +1008,7 @@ resize_and_retry: status_or |= run_status; status_and &= run_status; DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); - double run_advance = CTRunGetTypographicBounds (run, range_all, NULL, NULL, NULL); + double run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr); if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) run_advance = -run_advance; DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); @@ -943,7 +1021,7 @@ resize_and_retry: */ CFDictionaryRef attributes = CTRunGetAttributes (run); CTFontRef run_ct_font = static_cast<CTFontRef>(CFDictionaryGetValue (attributes, kCTFontAttributeName)); - if (!CFEqual (run_ct_font, face_data->ct_font)) + if (!CFEqual (run_ct_font, ct_font)) { /* The run doesn't use our main font instance. We have to figure out * whether font fallback happened, or this is just CoreText giving us @@ -965,7 +1043,7 @@ resize_and_retry: * However, even that wouldn't work if we were passed in the CGFont to * construct a hb_face to begin with. * - * See: http://github.com/behdad/harfbuzz/pull/36 + * See: http://github.com/harfbuzz/harfbuzz/pull/36 * * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098 */ @@ -981,13 +1059,13 @@ resize_and_retry: CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0); if (run_cg_font) { - matched = CFEqual (run_cg_font, face_data->cg_font); + matched = CFEqual (run_cg_font, cg_font); CFRelease (run_cg_font); } } if (!matched) { - CFStringRef font_ps_name = CTFontCopyName (face_data->ct_font, kCTFontPostScriptNameKey); + CFStringRef font_ps_name = CTFontCopyName (ct_font, kCTFontPostScriptNameKey); CFStringRef run_ps_name = CTFontCopyName (run_ct_font, kCTFontPostScriptNameKey); CFComparisonResult result = CFStringCompare (run_ps_name, font_ps_name, 0); CFRelease (run_ps_name); @@ -1056,7 +1134,7 @@ resize_and_retry: /* Testing used to indicate that CTRunGetGlyphsPtr, etc (almost?) always * succeed, and so copying data to our own buffer will be rare. Reports - * have it that this changed in OS X 10.10 Yosemite, and NULL is returned + * have it that this changed in OS X 10.10 Yosemite, and nullptr is returned * frequently. At any rate, we can test that codepath by setting USE_PTR * to false. */ @@ -1072,13 +1150,13 @@ resize_and_retry: { /* Setup glyphs */ SCRATCH_SAVE(); - const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : NULL; + const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : nullptr; if (!glyphs) { ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry); CTRunGetGlyphs (run, range_all, glyph_buf); glyphs = glyph_buf; } - const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run) : NULL; + const CFIndex* string_indices = USE_PTR ? CTRunGetStringIndicesPtr (run) : nullptr; if (!string_indices) { ALLOCATE_ARRAY (CFIndex, index_buf, num_glyphs, goto resize_and_retry); CTRunGetStringIndices (run, range_all, index_buf); @@ -1100,7 +1178,7 @@ resize_and_retry: * advance (in the advance direction only), and for last glyph we set * whatever is needed to make the whole run's advance add up. */ SCRATCH_SAVE(); - const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : NULL; + const CGPoint* positions = USE_PTR ? CTRunGetPositionsPtr (run) : nullptr; if (!positions) { ALLOCATE_ARRAY (CGPoint, position_buf, num_glyphs, goto resize_and_retry); CTRunGetPositions (run, range_all, position_buf); @@ -1176,6 +1254,9 @@ resize_and_retry: pos->x_advance = info->mask; pos->x_offset = info->var1.i32; pos->y_offset = info->var2.i32; + + info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + info++, pos++; } else @@ -1184,6 +1265,9 @@ resize_and_retry: pos->y_advance = info->mask; pos->x_offset = info->var1.i32; pos->y_offset = info->var2.i32; + + info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + info++, pos++; } @@ -1221,6 +1305,8 @@ resize_and_retry: } } + buffer->unsafe_to_break_all (); + #undef FAIL fail: @@ -1241,6 +1327,9 @@ fail: * AAT shaper */ +HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face) +HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font) + /* * shaper face data */ @@ -1250,22 +1339,20 @@ struct hb_coretext_aat_shaper_face_data_t {}; hb_coretext_aat_shaper_face_data_t * _hb_coretext_aat_shaper_face_data_create (hb_face_t *face) { - hb_blob_t *mort_blob = face->reference_table (HB_CORETEXT_TAG_MORT); - /* Umm, we just reference the table to check whether it exists. - * Maybe add better API for this? */ - if (!hb_blob_get_length (mort_blob)) + static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX}; + + for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++) { - hb_blob_destroy (mort_blob); - mort_blob = face->reference_table (HB_CORETEXT_TAG_MORX); - if (!hb_blob_get_length (mort_blob)) + hb_blob_t *blob = face->reference_table (tags[i]); + if (hb_blob_get_length (blob)) { - hb_blob_destroy (mort_blob); - return NULL; + hb_blob_destroy (blob); + return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr; } + hb_blob_destroy (blob); } - hb_blob_destroy (mort_blob); - return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; + return nullptr; } void @@ -1283,7 +1370,7 @@ struct hb_coretext_aat_shaper_font_data_t {}; hb_coretext_aat_shaper_font_data_t * _hb_coretext_aat_shaper_font_data_create (hb_font_t *font) { - return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : NULL; + return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr; } void diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h index 82066e4e0d..4b0a6f01b6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h @@ -42,11 +42,15 @@ HB_BEGIN_DECLS #define HB_CORETEXT_TAG_MORT HB_TAG('m','o','r','t') #define HB_CORETEXT_TAG_MORX HB_TAG('m','o','r','x') +#define HB_CORETEXT_TAG_KERX HB_TAG('k','e','r','x') HB_EXTERN hb_face_t * hb_coretext_face_create (CGFontRef cg_font); +HB_EXTERN hb_font_t * +hb_coretext_font_create (CTFontRef ct_font); + HB_EXTERN CGFontRef hb_coretext_face_get_cg_font (hb_face_t *face); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh new file mode 100644 index 0000000000..6c425f7b9d --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh @@ -0,0 +1,431 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_DEBUG_HH +#define HB_DEBUG_HH + +#include "hb-private.hh" + + +#ifndef HB_DEBUG +#define HB_DEBUG 0 +#endif + +static inline bool +_hb_debug (unsigned int level, + unsigned int max_level) +{ + return level < max_level; +} + +#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) +#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0)) + +static inline void +_hb_print_func (const char *func) +{ + if (func) + { + unsigned int func_len = strlen (func); + /* Skip "static" */ + if (0 == strncmp (func, "static ", 7)) + func += 7; + /* Skip "typename" */ + if (0 == strncmp (func, "typename ", 9)) + func += 9; + /* Skip return type */ + const char *space = strchr (func, ' '); + if (space) + func = space + 1; + /* Skip parameter list */ + const char *paren = strchr (func, '('); + if (paren) + func_len = paren - func; + fprintf (stderr, "%.*s", func_len, func); + } +} + +template <int max_level> static inline void +_hb_debug_msg_va (const char *what, + const void *obj, + const char *func, + bool indented, + unsigned int level, + int level_dir, + const char *message, + va_list ap) HB_PRINTF_FUNC(7, 0); +template <int max_level> static inline void +_hb_debug_msg_va (const char *what, + const void *obj, + const char *func, + bool indented, + unsigned int level, + int level_dir, + const char *message, + va_list ap) +{ + if (!_hb_debug (level, max_level)) + return; + + fprintf (stderr, "%-10s", what ? what : ""); + + if (obj) + fprintf (stderr, "(%*p) ", (unsigned int) (2 * sizeof (void *)), obj); + else + fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); + + if (indented) { +#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ +#define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ +#define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */ +#define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */ +#define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */ + static const char bars[] = + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR + VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR; + fprintf (stderr, "%2u %s" VRBAR "%s", + level, + bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level), + level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR); + } else + fprintf (stderr, " " VRBAR LBAR); + + _hb_print_func (func); + + if (message) + { + fprintf (stderr, ": "); + vfprintf (stderr, message, ap); + } + + fprintf (stderr, "\n"); +} +template <> inline void +_hb_debug_msg_va<0> (const char *what HB_UNUSED, + const void *obj HB_UNUSED, + const char *func HB_UNUSED, + bool indented HB_UNUSED, + unsigned int level HB_UNUSED, + int level_dir HB_UNUSED, + const char *message HB_UNUSED, + va_list ap HB_UNUSED) {} + +template <int max_level> static inline void +_hb_debug_msg (const char *what, + const void *obj, + const char *func, + bool indented, + unsigned int level, + int level_dir, + const char *message, + ...) HB_PRINTF_FUNC(7, 8); +template <int max_level> static inline void +_hb_debug_msg (const char *what, + const void *obj, + const char *func, + bool indented, + unsigned int level, + int level_dir, + const char *message, + ...) +{ + va_list ap; + va_start (ap, message); + _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap); + va_end (ap); +} +template <> inline void +_hb_debug_msg<0> (const char *what HB_UNUSED, + const void *obj HB_UNUSED, + const char *func HB_UNUSED, + bool indented HB_UNUSED, + unsigned int level HB_UNUSED, + int level_dir HB_UNUSED, + const char *message HB_UNUSED, + ...) HB_PRINTF_FUNC(7, 8); +template <> inline void +_hb_debug_msg<0> (const char *what HB_UNUSED, + const void *obj HB_UNUSED, + const char *func HB_UNUSED, + bool indented HB_UNUSED, + unsigned int level HB_UNUSED, + int level_dir HB_UNUSED, + const char *message HB_UNUSED, + ...) {} + +#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__) +#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), nullptr, false, 0, 0, __VA_ARGS__) +#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__) + + +/* + * Printer + */ + +template <typename T> +struct hb_printer_t { + const char *print (const T&) { return "something"; } +}; + +template <> +struct hb_printer_t<bool> { + const char *print (bool v) { return v ? "true" : "false"; } +}; + +template <> +struct hb_printer_t<hb_void_t> { + const char *print (hb_void_t) { return ""; } +}; + + +/* + * Trace + */ + +template <typename T> +static inline void _hb_warn_no_return (bool returned) +{ + if (unlikely (!returned)) { + fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n"); + } +} +template <> +/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED) +{} + +template <int max_level, typename ret_t> +struct hb_auto_trace_t +{ + explicit inline hb_auto_trace_t (unsigned int *plevel_, + const char *what_, + const void *obj_, + const char *func, + const char *message, + ...) HB_PRINTF_FUNC(6, 7) + : plevel (plevel_), what (what_), obj (obj_), returned (false) + { + if (plevel) ++*plevel; + + va_list ap; + va_start (ap, message); + _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap); + va_end (ap); + } + inline ~hb_auto_trace_t (void) + { + _hb_warn_no_return<ret_t> (returned); + if (!returned) { + _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, " "); + } + if (plevel) --*plevel; + } + + inline ret_t ret (ret_t v, unsigned int line = 0) + { + if (unlikely (returned)) { + fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n"); + return v; + } + + _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1, + "return %s (line %d)", + hb_printer_t<ret_t>().print (v), line); + if (plevel) --*plevel; + plevel = nullptr; + returned = true; + return v; + } + + private: + unsigned int *plevel; + const char *what; + const void *obj; + bool returned; +}; +template <typename ret_t> /* Make sure we don't use hb_auto_trace_t when not tracing. */ +struct hb_auto_trace_t<0, ret_t> +{ + explicit inline hb_auto_trace_t (unsigned int *plevel_, + const char *what_, + const void *obj_, + const char *func, + const char *message, + ...) HB_PRINTF_FUNC(6, 7) {} + + inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; } +}; + +/* For disabled tracing; optimize out everything. + * https://github.com/harfbuzz/harfbuzz/pull/605 */ +template <typename ret_t> +struct hb_no_trace_t { + inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; } +}; + +#define return_trace(RET) return trace.ret (RET, __LINE__) + + +/* + * Instances. + */ + +#ifndef HB_DEBUG_ARABIC +#define HB_DEBUG_ARABIC (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_BLOB +#define HB_DEBUG_BLOB (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_CORETEXT +#define HB_DEBUG_CORETEXT (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_DIRECTWRITE +#define HB_DEBUG_DIRECTWRITE (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_FT +#define HB_DEBUG_FT (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_GET_COVERAGE +#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_OBJECT +#define HB_DEBUG_OBJECT (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_SHAPE_PLAN +#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0) +#endif + +#ifndef HB_DEBUG_UNISCRIBE +#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) +#endif + +/* + * With tracing. + */ + +#ifndef HB_DEBUG_APPLY +#define HB_DEBUG_APPLY (HB_DEBUG+0) +#endif +#if HB_DEBUG_APPLY +#define TRACE_APPLY(this) \ + hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "idx %d gid %u lookup %d", \ + c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index) +#else +#define TRACE_APPLY(this) hb_no_trace_t<bool> trace +#endif + +#ifndef HB_DEBUG_CLOSURE +#define HB_DEBUG_CLOSURE (HB_DEBUG+0) +#endif +#if HB_DEBUG_CLOSURE +#define TRACE_CLOSURE(this) \ + hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + " ") +#else +#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED +#endif + +#ifndef HB_DEBUG_COLLECT_GLYPHS +#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0) +#endif +#if HB_DEBUG_COLLECT_GLYPHS +#define TRACE_COLLECT_GLYPHS(this) \ + hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + " ") +#else +#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED +#endif + +#ifndef HB_DEBUG_SANITIZE +#define HB_DEBUG_SANITIZE (HB_DEBUG+0) +#endif +#if HB_DEBUG_SANITIZE +#define TRACE_SANITIZE(this) \ + hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + " "); +#else +#define TRACE_SANITIZE(this) hb_no_trace_t<bool> trace +#endif + +#ifndef HB_DEBUG_SERIALIZE +#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) +#endif +#if HB_DEBUG_SERIALIZE +#define TRACE_SERIALIZE(this) \ + hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ + (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ + " "); +#else +#define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace +#endif + +#ifndef HB_DEBUG_WOULD_APPLY +#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0) +#endif +#if HB_DEBUG_WOULD_APPLY +#define TRACE_WOULD_APPLY(this) \ + hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "%d glyphs", c->len); +#else +#define TRACE_WOULD_APPLY(this) hb_no_trace_t<bool> trace +#endif + +#ifndef HB_DEBUG_DISPATCH +#define HB_DEBUG_DISPATCH ( \ + HB_DEBUG_APPLY + \ + HB_DEBUG_CLOSURE + \ + HB_DEBUG_COLLECT_GLYPHS + \ + HB_DEBUG_SANITIZE + \ + HB_DEBUG_SERIALIZE + \ + HB_DEBUG_WOULD_APPLY + \ + 0) +#endif +#if HB_DEBUG_DISPATCH +#define TRACE_DISPATCH(this, format) \ + hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "format %d", (int) format); +#else +#define TRACE_DISPATCH(this, format) hb_no_trace_t<typename context_t::return_t> trace +#endif + + +#endif /* HB_DEBUG_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h index 0398dfae60..eac7efb42f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-deprecated.h @@ -34,6 +34,7 @@ #include "hb-common.h" #include "hb-unicode.h" #include "hb-font.h" +#include "hb-set.h" HB_BEGIN_DECLS @@ -54,6 +55,9 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, hb_font_get_glyph_func_t func, void *user_data, hb_destroy_func_t destroy); +HB_EXTERN void +hb_set_invert (hb_set_t *set); + #endif HB_END_DECLS diff --git a/src/3rdparty/harfbuzz-ng/src/hb-dsalgs.hh b/src/3rdparty/harfbuzz-ng/src/hb-dsalgs.hh new file mode 100644 index 0000000000..4e8f0431c6 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-dsalgs.hh @@ -0,0 +1,167 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_DSALGS_HH +#define HB_DSALGS_HH + +#include "hb-private.hh" + +#if defined(__ghs) +// GHS compiler doesn't support the __restrict keyword +#define __restrict +#endif + + + +static inline void * +hb_bsearch_r (const void *key, const void *base, + size_t nmemb, size_t size, + int (*compar)(const void *_key, const void *_item, void *_arg), + void *arg) +{ + int min = 0, max = (int) nmemb - 1; + while (min <= max) + { + int mid = (min + max) / 2; + const void *p = (const void *) (((const char *) base) + (mid * size)); + int c = compar (key, p, arg); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + return (void *) p; + } + return NULL; +} + + + +/* From https://github.com/noporpoise/sort_r */ + +/* Isaac Turner 29 April 2014 Public Domain */ + +/* + +hb_sort_r function to be exported. + +Parameters: + base is the array to be sorted + nel is the number of elements in the array + width is the size in bytes of each element of the array + compar is the comparison function + arg is a pointer to be passed to the comparison function + +void hb_sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, const void *_b, void *_arg), + void *arg); +*/ + + +/* swap a, b iff a>b */ +/* __restrict is same as restrict but better support on old machines */ +static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w, + int (*compar)(const void *_a, const void *_b, + void *_arg), + void *arg) +{ + char tmp, *end = a+w; + if(compar(a, b, arg) > 0) { + for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; } + return 1; + } + return 0; +} + +/* Note: quicksort is not stable, equivalent values may be swapped */ +static inline void sort_r_simple(void *base, size_t nel, size_t w, + int (*compar)(const void *_a, const void *_b, + void *_arg), + void *arg) +{ + char *b = (char *)base, *end = b + nel*w; + if(nel < 7) { + /* Insertion sort for arbitrarily small inputs */ + char *pi, *pj; + for(pi = b+w; pi < end; pi += w) { + for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {} + } + } + else + { + /* nel > 6; Quicksort */ + + /* Use median of first, middle and last items as pivot */ + char *x, *y, *xend, ch; + char *pl, *pr; + char *last = b+w*(nel-1), *tmp; + char *l[3]; + l[0] = b; + l[1] = b+w*(nel/2); + l[2] = last; + + if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; } + if(compar(l[1],l[2],arg) > 0) { + tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */ + if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; } + } + + /* swap l[id], l[2] to put pivot as last element */ + for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) { + ch = *x; *x = *y; *y = ch; + } + + pl = b; + pr = last; + + while(pl < pr) { + for(; pl < pr; pl += w) { + if(sort_r_cmpswap(pl, pr, w, compar, arg)) { + pr -= w; /* pivot now at pl */ + break; + } + } + for(; pl < pr; pr -= w) { + if(sort_r_cmpswap(pl, pr, w, compar, arg)) { + pl += w; /* pivot now at pr */ + break; + } + } + } + + sort_r_simple(b, (pl-b)/w, w, compar, arg); + sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg); + } +} + +static inline void hb_sort_r(void *base, size_t nel, size_t width, + int (*compar)(const void *_a, const void *_b, void *_arg), + void *arg) +{ + sort_r_simple(base, nel, width, compar, arg); +} + +#endif /* HB_DSALGS_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh index c4266fff4f..43e7b1cb3f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-face-private.hh @@ -50,12 +50,16 @@ struct hb_face_t { void *user_data; hb_destroy_func_t destroy; - unsigned int index; - mutable unsigned int upem; - mutable unsigned int num_glyphs; + unsigned int index; /* Face index in a collection, zero-based. */ + mutable unsigned int upem; /* Units-per-EM. */ + mutable unsigned int num_glyphs; /* Number of glyphs. */ - struct hb_shaper_data_t shaper_data; + struct hb_shaper_data_t shaper_data; /* Various shaper data. */ + /* Various non-shaping data. */ + /* ... */ + + /* Cache */ struct plan_node_t { hb_shape_plan_t *shape_plan; plan_node_t *next; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.cc b/src/3rdparty/harfbuzz-ng/src/hb-face.cc index 6b563bc8f1..26fddbe529 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-face.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-face.cc @@ -28,15 +28,11 @@ #include "hb-private.hh" -#include "hb-ot-layout-private.hh" - -#include "hb-font-private.hh" +#include "hb-face-private.hh" #include "hb-open-file-private.hh" #include "hb-ot-head-table.hh" #include "hb-ot-maxp-table.hh" -#include <string.h> - /* * hb_face_t @@ -47,9 +43,9 @@ const hb_face_t _hb_face_nil = { true, /* immutable */ - NULL, /* reference_table_func */ - NULL, /* user_data */ - NULL, /* destroy */ + nullptr, /* reference_table_func */ + nullptr, /* user_data */ + nullptr, /* destroy */ 0, /* index */ 1000, /* upem */ @@ -61,7 +57,7 @@ const hb_face_t _hb_face_nil = { #undef HB_SHAPER_IMPLEMENT }, - NULL, /* shape_plans */ + nullptr, /* shape_plans */ }; @@ -113,7 +109,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t)); if (unlikely (!closure)) - return NULL; + return nullptr; closure->blob = blob; closure->index = index; @@ -122,8 +118,10 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) } static void -_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure) +_hb_face_for_data_closure_destroy (void *data) { + hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data; + hb_blob_destroy (closure->blob); free (closure); } @@ -173,9 +171,9 @@ hb_face_create (hb_blob_t *blob, face = hb_face_create_for_tables (_hb_face_for_data_reference_table, closure, - (hb_destroy_func_t) _hb_face_for_data_closure_destroy); + _hb_face_for_data_closure_destroy); - hb_face_set_index (face, index); + face->index = index; return face; } @@ -476,4 +474,33 @@ hb_face_t::load_num_glyphs (void) const hb_blob_destroy (maxp_blob); } +/** + * hb_face_get_table_tags: + * @face: a face. + * + * Retrieves table tags for a face, if possible. + * + * Return value: total number of tables, or 0 if not possible to list. + * + * Since: 1.6.0 + **/ +unsigned int +hb_face_get_table_tags (hb_face_t *face, + unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */) +{ + if (face->destroy != _hb_face_for_data_closure_destroy) + { + if (table_count) + *table_count = 0; + return 0; + } + + hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data; + const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob); + const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); + + return ot_face.get_table_tags (start_offset, table_count, table_tags); +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.h b/src/3rdparty/harfbuzz-ng/src/hb-face.h index 91237b7085..9842d52b65 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-face.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-face.h @@ -111,6 +111,11 @@ hb_face_set_glyph_count (hb_face_t *face, HB_EXTERN unsigned int hb_face_get_glyph_count (hb_face_t *face); +HB_EXTERN unsigned int +hb_face_get_table_tags (hb_face_t *face, + unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */); HB_END_DECLS diff --git a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc index ac6d4b00f5..3f09c3f530 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-fallback-shape.cc @@ -28,6 +28,10 @@ #include "hb-shaper-impl-private.hh" +HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face) +HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font) + + /* * shaper face data */ @@ -125,7 +129,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, pos[i].y_advance = 0; continue; } - font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint); + (void) font->get_nominal_glyph (info[i].codepoint, &info[i].codepoint); font->get_glyph_advance_for_direction (info[i].codepoint, direction, &pos[i].x_advance, @@ -139,5 +143,7 @@ _hb_fallback_shape (hb_shape_plan_t *shape_plan HB_UNUSED, if (HB_DIRECTION_IS_BACKWARD (direction)) hb_buffer_reverse (buffer); + buffer->safe_to_break_all (); + return true; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh index 53671d78d2..d2801fb86e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-font-private.hh @@ -108,6 +108,8 @@ struct hb_font_t { unsigned int x_ppem; unsigned int y_ppem; + float ptem; + /* Font variation coordinates. */ unsigned int num_coords; int *coords; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-font.cc index 2935c4b4fd..f3534b686b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.cc @@ -28,14 +28,7 @@ #include "hb-private.hh" -#include "hb-ot-layout-private.hh" - #include "hb-font-private.hh" -#include "hb-open-file-private.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-maxp-table.hh" - -#include <string.h> /* @@ -43,7 +36,7 @@ */ static hb_bool_t -hb_font_get_font_h_extents_nil (hb_font_t *font, +hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_font_extents_t *metrics, void *user_data HB_UNUSED) @@ -67,7 +60,7 @@ hb_font_get_font_h_extents_parent (hb_font_t *font, } static hb_bool_t -hb_font_get_font_v_extents_nil (hb_font_t *font, +hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_font_extents_t *metrics, void *user_data HB_UNUSED) @@ -354,12 +347,12 @@ static const hb_font_funcs_t _hb_font_funcs_nil = { true, /* immutable */ { -#define HB_FONT_FUNC_IMPLEMENT(name) NULL, +#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT }, { -#define HB_FONT_FUNC_IMPLEMENT(name) NULL, +#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT }, @@ -377,12 +370,12 @@ static const hb_font_funcs_t _hb_font_funcs_parent = { true, /* immutable */ { -#define HB_FONT_FUNC_IMPLEMENT(name) NULL, +#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT }, { -#define HB_FONT_FUNC_IMPLEMENT(name) NULL, +#define HB_FONT_FUNC_IMPLEMENT(name) nullptr, HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT }, @@ -570,8 +563,8 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ ffuncs->destroy.name = destroy; \ } else { \ ffuncs->get.f.name = hb_font_get_##name##_parent; \ - ffuncs->user_data.name = NULL; \ - ffuncs->destroy.name = NULL; \ + ffuncs->user_data.name = nullptr; \ + ffuncs->destroy.name = nullptr; \ } \ } @@ -1164,8 +1157,20 @@ hb_font_create_sub_font (hb_font_t *parent) font->y_scale = parent->y_scale; font->x_ppem = parent->x_ppem; font->y_ppem = parent->y_ppem; + font->ptem = parent->ptem; - /* TODO: copy variation coordinates. */ + font->num_coords = parent->num_coords; + if (!font->num_coords) + font->coords = nullptr; + else + { + unsigned int size = parent->num_coords * sizeof (parent->coords[0]); + font->coords = (int *) malloc (size); + if (unlikely (!font->coords)) + font->num_coords = 0; + else + memcpy (font->coords, parent->coords, size); + } return font; } @@ -1187,7 +1192,7 @@ hb_font_get_empty (void) true, /* immutable */ - NULL, /* parent */ + nullptr, /* parent */ const_cast<hb_face_t *> (&_hb_face_nil), 1000, /* x_scale */ @@ -1195,13 +1200,14 @@ hb_font_get_empty (void) 0, /* x_ppem */ 0, /* y_ppem */ + 0, /* ptem */ 0, /* num_coords */ - NULL, /* coords */ + nullptr, /* coords */ const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */ - NULL, /* user_data */ - NULL, /* destroy */ + nullptr, /* user_data */ + nullptr, /* destroy */ { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, @@ -1379,6 +1385,32 @@ hb_font_get_parent (hb_font_t *font) } /** + * hb_font_set_face: + * @font: a font. + * @face: new face. + * + * Sets font-face of @font. + * + * Since: 1.4.3 + **/ +void +hb_font_set_face (hb_font_t *font, + hb_face_t *face) +{ + if (font->immutable) + return; + + if (unlikely (!face)) + face = hb_face_get_empty (); + + hb_face_t *old = font->face; + + font->face = hb_face_reference (face); + + hb_face_destroy (old); +} + +/** * hb_font_get_face: * @font: a font. * @@ -1543,30 +1575,146 @@ hb_font_get_ppem (hb_font_t *font, if (y_ppem) *y_ppem = font->y_ppem; } +/** + * hb_font_set_ptem: + * @font: a font. + * @ptem: + * + * Sets "point size" of the font. + * + * Since: 1.6.0 + **/ +void +hb_font_set_ptem (hb_font_t *font, float ptem) +{ + if (font->immutable) + return; + + font->ptem = ptem; +} + +/** + * hb_font_get_ptem: + * @font: a font. + * + * Gets the "point size" of the font. A value of 0 means unset. + * + * Return value: Point size. + * + * Since: 0.9.2 + **/ +float +hb_font_get_ptem (hb_font_t *font) +{ + return font->ptem; +} +/* + * Variations + */ + +static void +_hb_font_adopt_var_coords_normalized (hb_font_t *font, + int *coords, /* 2.14 normalized */ + unsigned int coords_length) +{ + free (font->coords); + + font->coords = coords; + font->num_coords = coords_length; +} + +/** + * hb_font_set_variations: + * + * Since: 1.4.2 + */ +void +hb_font_set_variations (hb_font_t *font, + const hb_variation_t *variations, + unsigned int variations_length) +{ + if (font->immutable) + return; + + if (!variations_length) + { + hb_font_set_var_coords_normalized (font, nullptr, 0); + return; + } + + unsigned int coords_length = hb_ot_var_get_axis_count (font->face); + + int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; + if (unlikely (coords_length && !normalized)) + return; + + hb_ot_var_normalize_variations (font->face, + variations, variations_length, + normalized, coords_length); + _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); +} + +/** + * hb_font_set_var_coords_design: + * + * Since: 1.4.2 + */ +void +hb_font_set_var_coords_design (hb_font_t *font, + const float *coords, + unsigned int coords_length) +{ + if (font->immutable) + return; + + int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; + if (unlikely (coords_length && !normalized)) + return; + + hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized); + _hb_font_adopt_var_coords_normalized (font, normalized, coords_length); +} + +/** + * hb_font_set_var_coords_normalized: + * + * Since: 1.4.2 + */ void hb_font_set_var_coords_normalized (hb_font_t *font, - int *coords, /* XXX 2.14 normalized */ + const int *coords, /* 2.14 normalized */ unsigned int coords_length) { if (font->immutable) return; - /* Skip tail zero entries. */ - while (coords_length && !coords[coords_length - 1]) - coords_length--; - - int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : NULL; + int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr; if (unlikely (coords_length && !copy)) return; - free (font->coords); - if (coords_length) memcpy (copy, coords, coords_length * sizeof (coords[0])); - font->coords = copy; - font->num_coords = coords_length; + _hb_font_adopt_var_coords_normalized (font, copy, coords_length); +} + +/** + * hb_font_get_var_coords_normalized: + * + * Return value is valid as long as variation coordinates of the font + * are not modified. + * + * Since: 1.4.2 + */ +const int * +hb_font_get_var_coords_normalized (hb_font_t *font, + unsigned int *length) +{ + if (length) + *length = font->num_coords; + + return font->coords; } @@ -1601,7 +1749,7 @@ trampoline_create (FuncType func, trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t)); if (unlikely (!trampoline)) - return NULL; + return nullptr; trampoline->closure.user_data = user_data; trampoline->closure.destroy = destroy; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-font.h b/src/3rdparty/harfbuzz-ng/src/hb-font.h index 8813286726..540cdcab95 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-font.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-font.h @@ -563,6 +563,10 @@ hb_font_set_parent (hb_font_t *font, HB_EXTERN hb_font_t * hb_font_get_parent (hb_font_t *font); +HB_EXTERN void +hb_font_set_face (hb_font_t *font, + hb_face_t *face); + HB_EXTERN hb_face_t * hb_font_get_face (hb_font_t *font); @@ -603,12 +607,35 @@ hb_font_get_ppem (hb_font_t *font, unsigned int *x_ppem, unsigned int *y_ppem); +/* + * Point size per EM. Used for optical-sizing in CoreText. + * A value of zero means "not set". + */ +HB_EXTERN void +hb_font_set_ptem (hb_font_t *font, float ptem); + +HB_EXTERN float +hb_font_get_ptem (hb_font_t *font); + +HB_EXTERN void +hb_font_set_variations (hb_font_t *font, + const hb_variation_t *variations, + unsigned int variations_length); + +HB_EXTERN void +hb_font_set_var_coords_design (hb_font_t *font, + const float *coords, + unsigned int coords_length); HB_EXTERN void hb_font_set_var_coords_normalized (hb_font_t *font, - int *coords, /* XXX 2.14 normalized */ + const int *coords, /* 2.14 normalized */ unsigned int coords_length); +HB_EXTERN const int * +hb_font_get_var_coords_normalized (hb_font_t *font, + unsigned int *length); + HB_END_DECLS #endif /* HB_FONT_H */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh index ed2703571c..49ed10e08a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-mutex-private.hh @@ -68,7 +68,7 @@ typedef CRITICAL_SECTION hb_mutex_impl_t; #include <pthread.h> typedef pthread_mutex_t hb_mutex_impl_t; #define HB_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER -#define hb_mutex_impl_init(M) pthread_mutex_init (M, NULL) +#define hb_mutex_impl_init(M) pthread_mutex_init (M, nullptr) #define hb_mutex_impl_lock(M) pthread_mutex_lock (M) #define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M) #define hb_mutex_impl_finish(M) pthread_mutex_destroy (M) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-object-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-object-private.hh index 6b73ff92d0..baa1f8f05c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-object-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-object-private.hh @@ -33,18 +33,12 @@ #define HB_OBJECT_PRIVATE_HH #include "hb-private.hh" +#include "hb-debug.hh" #include "hb-atomic-private.hh" #include "hb-mutex-private.hh" -/* Debug */ - -#ifndef HB_DEBUG_OBJECT -#define HB_DEBUG_OBJECT (HB_DEBUG+0) -#endif - - /* reference_count */ #define HB_REFERENCE_COUNT_INERT_VALUE -1 @@ -193,7 +187,7 @@ static inline void *hb_object_get_user_data (Type *obj, hb_user_data_key_t *key) { if (unlikely (!obj || hb_object_is_inert (obj))) - return NULL; + return nullptr; assert (hb_object_is_valid (obj)); return obj->header.user_data.get (key); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh index 5357ddcf5b..644e0b40f6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh @@ -53,6 +53,9 @@ struct TTCHeader; typedef struct TableRecord { + int cmp (Tag t) const + { return t.cmp (tag); } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -61,9 +64,9 @@ typedef struct TableRecord Tag tag; /* 4-byte identifier. */ CheckSum checkSum; /* CheckSum for this table. */ - ULONG offset; /* Offset from beginning of TrueType font + UINT32 offset; /* Offset from beginning of TrueType font * file. */ - ULONG length; /* Length of this table. */ + UINT32 length; /* Length of this table. */ public: DEFINE_SIZE_STATIC (16); } OpenTypeTable; @@ -73,27 +76,39 @@ typedef struct OffsetTable friend struct OpenTypeFontFile; inline unsigned int get_table_count (void) const - { return numTables; } + { return tables.len; } inline const TableRecord& get_table (unsigned int i) const { - if (unlikely (i >= numTables)) return Null(TableRecord); return tables[i]; } + inline unsigned int get_table_tags (unsigned int start_offset, + unsigned int *table_count, /* IN/OUT */ + hb_tag_t *table_tags /* OUT */) const + { + if (table_count) + { + if (start_offset >= tables.len) + *table_count = 0; + else + *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset); + + const TableRecord *sub_tables = tables.array + start_offset; + unsigned int count = *table_count; + for (unsigned int i = 0; i < count; i++) + table_tags[i] = sub_tables[i].tag; + } + return tables.len; + } inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const { Tag t; t.set (tag); - unsigned int count = numTables; - for (unsigned int i = 0; i < count; i++) - { - if (t == tables[i].tag) - { - if (table_index) *table_index = i; - return true; - } - } - if (table_index) *table_index = Index::NOT_FOUND_INDEX; - return false; + /* Linear-search for small tables to work around fonts with unsorted + * table list. */ + int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t); + if (table_index) + *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i; + return i != -1; } inline const TableRecord& get_table_by_tag (hb_tag_t tag) const { @@ -106,16 +121,13 @@ typedef struct OffsetTable inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); + return_trace (c->check_struct (this) && tables.sanitize (c)); } protected: Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */ - USHORT numTables; /* Number of tables. */ - USHORT searchRangeZ; /* (Maximum power of 2 <= numTables) x 16 */ - USHORT entrySelectorZ; /* Log2(maximum power of 2 <= numTables). */ - USHORT rangeShiftZ; /* NumTables x 16-searchRange. */ - TableRecord tables[VAR]; /* TableRecord entries. numTables items */ + BinSearchArrayOf<TableRecord> + tables; public: DEFINE_SIZE_ARRAY (12, tables); } OpenTypeFontFace; @@ -142,7 +154,7 @@ struct TTCHeaderVersion1 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - ArrayOf<OffsetTo<OffsetTable, ULONG>, ULONG> + ArrayOf<LOffsetTo<OffsetTable>, UINT32> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh index 2cc1fb20d2..2f4e1b9e9e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh @@ -30,6 +30,8 @@ #define HB_OPEN_TYPE_PRIVATE_HH #include "hb-private.hh" +#include "hb-debug.hh" +#include "hb-face-private.hh" namespace OT { @@ -84,7 +86,7 @@ static inline Type& StructAfter(TObject &X) #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ inline void _instance_assertion_on_line_##_line (void) const \ { \ - ASSERT_STATIC (_assertion); \ + static_assert ((_assertion), ""); \ ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ } # define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) @@ -129,14 +131,16 @@ static inline Type& StructAfter(TObject &X) */ /* Global nul-content Null pool. Enlarge as necessary. */ -/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ -static const void *_NullPool[(256+8) / sizeof (void *)]; + +#define HB_NULL_POOL_SIZE 264 +static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); +extern HB_INTERNAL const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]; /* Generic nul-content Null objects. */ template <typename Type> static inline const Type& Null (void) { - ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); - return *CastP<Type> (_NullPool); + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + return *CastP<Type> (_hb_NullPool); } /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ @@ -146,7 +150,7 @@ template <> \ /*static*/ inline const Type& Null<Type> (void) { \ return *CastP<Type> (_Null##Type); \ } /* The following line really exists such that we end in a place needing semicolon */ \ -ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) +static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") /* Accessor macro. */ #define Null(Type) Null<Type>() @@ -171,16 +175,6 @@ struct hb_dispatch_context_t * Sanitize */ -#ifndef HB_DEBUG_SANITIZE -#define HB_DEBUG_SANITIZE (HB_DEBUG+0) -#endif - - -#define TRACE_SANITIZE(this) \ - hb_auto_trace_t<HB_DEBUG_SANITIZE, bool> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - /* This limits sanitizing time on really broken fonts. */ #ifndef HB_SANITIZE_MAX_EDITS #define HB_SANITIZE_MAX_EDITS 32 @@ -191,9 +185,9 @@ struct hb_sanitize_context_t : { inline hb_sanitize_context_t (void) : debug_depth (0), - start (NULL), end (NULL), + start (nullptr), end (nullptr), writable (false), edit_count (0), - blob (NULL) {} + blob (nullptr) {} inline const char *get_name (void) { return "SANITIZE"; } template <typename T, typename F> @@ -213,7 +207,7 @@ struct hb_sanitize_context_t : inline void start_processing (void) { - this->start = hb_blob_get_data (this->blob, NULL); + this->start = hb_blob_get_data (this->blob, nullptr); this->end = this->start + hb_blob_get_length (this->blob); assert (this->start <= this->end); /* Must not overflow. */ this->edit_count = 0; @@ -232,8 +226,8 @@ struct hb_sanitize_context_t : this->start, this->end, this->edit_count); hb_blob_destroy (this->blob); - this->blob = NULL; - this->start = this->end = NULL; + this->blob = nullptr; + this->start = this->end = nullptr; } inline bool check_range (const void *base, unsigned int len) const @@ -348,7 +342,7 @@ struct Sanitizer } else { unsigned int edit_count = c->edit_count; if (edit_count && !c->writable) { - c->start = hb_blob_get_data_writable (blob, NULL); + c->start = hb_blob_get_data_writable (blob, nullptr); c->end = c->start + hb_blob_get_length (blob); if (c->start) { @@ -373,7 +367,7 @@ struct Sanitizer static const Type* lock_instance (hb_blob_t *blob) { hb_blob_make_immutable (blob); - const char *base = hb_blob_get_data (blob, NULL); + const char *base = hb_blob_get_data (blob, nullptr); return unlikely (!base) ? &Null(Type) : CastP<Type> (base); } }; @@ -384,16 +378,6 @@ struct Sanitizer * Serialize */ -#ifndef HB_DEBUG_SERIALIZE -#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) -#endif - - -#define TRACE_SERIALIZE(this) \ - hb_auto_trace_t<HB_DEBUG_SERIALIZE, bool> trace \ - (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ - ""); - struct hb_serialize_context_t { @@ -444,7 +428,7 @@ struct hb_serialize_context_t { if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { this->ran_out_of_room = true; - return NULL; + return nullptr; } memset (this->head, 0, size); char *ret = this->head; @@ -470,7 +454,7 @@ struct hb_serialize_context_t { unsigned int size = obj.get_size (); Type *ret = this->allocate_size<Type> (size); - if (unlikely (!ret)) return NULL; + if (unlikely (!ret)) return nullptr; memcpy (ret, obj, size); return ret; } @@ -480,7 +464,7 @@ struct hb_serialize_context_t { unsigned int size = obj.min_size; assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); - if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; + if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr; return reinterpret_cast<Type *> (&obj); } @@ -489,7 +473,7 @@ struct hb_serialize_context_t { unsigned int size = obj.get_size (); assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); - if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return NULL; + if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr; return reinterpret_cast<Type *> (&obj); } @@ -631,10 +615,11 @@ struct IntType inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; } inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); } static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); } - inline int cmp (Type a) const + template <typename Type2> + inline int cmp (Type2 a) const { Type b = v; - if (sizeof (Type) < sizeof (int)) + if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int)) return (int) a - (int) b; else return a < b ? -1 : a == b ? 0 : +1; @@ -650,23 +635,22 @@ struct IntType DEFINE_SIZE_STATIC (Size); }; -typedef IntType<int8_t , 1> CHAR; /* 8-bit signed integer. */ -typedef IntType<uint8_t , 1> BYTE; /* 8-bit unsigned integer. */ -typedef IntType<int8_t , 1> INT8; /* 8-bit signed integer. */ -typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */ -typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */ -typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */ -typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */ +typedef IntType<uint8_t, 1> UINT8; /* 8-bit unsigned integer. */ +typedef IntType<int8_t, 1> INT8; /* 8-bit signed integer. */ +typedef IntType<uint16_t, 2> UINT16; /* 16-bit unsigned integer. */ +typedef IntType<int16_t, 2> INT16; /* 16-bit signed integer. */ +typedef IntType<uint32_t, 4> UINT32; /* 32-bit unsigned integer. */ +typedef IntType<int32_t, 4> INT32; /* 32-bit signed integer. */ typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */ -/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */ -typedef SHORT FWORD; +/* 16-bit signed integer (INT16) that describes a quantity in FUnits. */ +typedef INT16 FWORD; -/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */ -typedef USHORT UFWORD; +/* 16-bit unsigned integer (UINT16) that describes a quantity in FUnits. */ +typedef UINT16 UFWORD; /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */ -struct F2DOT14 : SHORT +struct F2DOT14 : INT16 { //inline float to_float (void) const { return ???; } //inline void set_float (float f) { v.set (f * ???); } @@ -675,7 +659,7 @@ struct F2DOT14 : SHORT }; /* 32-bit signed fixed-point number (16.16). */ -struct Fixed: LONG +struct Fixed: INT32 { //inline float to_float (void) const { return ???; } //inline void set_float (float f) { v.set (f * ???); } @@ -693,15 +677,15 @@ struct LONGDATETIME return_trace (likely (c->check_struct (this))); } protected: - LONG major; - ULONG minor; + INT32 major; + UINT32 minor; public: DEFINE_SIZE_STATIC (8); }; /* Array of four uint8s (length = 32 bits) used to identify a script, language * system, feature, or baseline */ -struct Tag : ULONG +struct Tag : UINT32 { /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); } @@ -712,19 +696,16 @@ struct Tag : ULONG DEFINE_NULL_DATA (Tag, " "); /* Glyph index number, same as uint16 (length = 16 bits) */ -struct GlyphID : USHORT { - static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); } - inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } -}; +typedef UINT16 GlyphID; /* Script/language-system/feature index */ -struct Index : USHORT { +struct Index : UINT16 { static const unsigned int NOT_FOUND_INDEX = 0xFFFFu; }; DEFINE_NULL_DATA (Index, "\xff\xff"); /* Offset, Null offset = 0 */ -template <typename Type=USHORT> +template <typename Type> struct Offset : Type { inline bool is_null (void) const { return 0 == *this; } @@ -732,15 +713,18 @@ struct Offset : Type DEFINE_SIZE_STATIC (sizeof(Type)); }; +typedef Offset<UINT16> Offset16; +typedef Offset<UINT32> Offset32; + /* CheckSum */ -struct CheckSum : ULONG +struct CheckSum : UINT32 { /* This is reference implementation from the spec. */ - static inline uint32_t CalcTableChecksum (const ULONG *Table, uint32_t Length) + static inline uint32_t CalcTableChecksum (const UINT32 *Table, uint32_t Length) { uint32_t Sum = 0L; - const ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::static_size; + const UINT32 *EndPtr = Table+((Length+3) & ~3) / UINT32::static_size; while (Table < EndPtr) Sum += *Table++; @@ -749,7 +733,7 @@ struct CheckSum : ULONG /* Note: data should be 4byte aligned and have 4byte padding at the end. */ inline void set_for_data (const void *data, unsigned int length) - { set (CalcTableChecksum ((const ULONG *) data, length)); } + { set (CalcTableChecksum ((const UINT32 *) data, length)); } public: DEFINE_SIZE_STATIC (4); @@ -760,7 +744,7 @@ struct CheckSum : ULONG * Version Numbers */ -template <typename FixedType=USHORT> +template <typename FixedType=UINT16> struct FixedVersion { inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; } @@ -784,7 +768,7 @@ struct FixedVersion * Use: (base+offset) */ -template <typename Type, typename OffsetType=USHORT> +template <typename Type, typename OffsetType=UINT16> struct OffsetTo : Offset<OffsetType> { inline const Type& operator () (const void *base) const @@ -829,6 +813,7 @@ struct OffsetTo : Offset<OffsetType> } DEFINE_SIZE_STATIC (sizeof(OffsetType)); }; +template <typename Type> struct LOffsetTo : OffsetTo<Type, UINT32> {}; template <typename Base, typename OffsetType, typename Type> static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); } template <typename Base, typename OffsetType, typename Type> @@ -840,7 +825,7 @@ static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) */ /* An array with a number of elements. */ -template <typename Type, typename LenType=USHORT> +template <typename Type, typename LenType=UINT16> struct ArrayOf { const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const @@ -941,7 +926,7 @@ struct ArrayOf inline bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len)); + return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len)); } public: @@ -950,9 +935,10 @@ struct ArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), array); }; +template <typename Type> struct LArrayOf : ArrayOf<Type, UINT32> {}; /* Array of Offset's */ -template <typename Type, typename OffsetType=USHORT> +template <typename Type, typename OffsetType=UINT16> struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {}; /* Array of offsets relative to the beginning of the array itself. */ @@ -980,7 +966,7 @@ struct OffsetListOf : OffsetArrayOf<Type> /* An array starting at second element. */ -template <typename Type, typename LenType=USHORT> +template <typename Type, typename LenType=UINT16> struct HeadlessArrayOf { inline const Type& operator [] (unsigned int i) const @@ -1006,12 +992,6 @@ struct HeadlessArrayOf return_trace (true); } - inline bool sanitize_shallow (hb_sanitize_context_t *c) const - { - return c->check_struct (this) - && c->check_array (this, Type::static_size, len); - } - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1029,6 +1009,15 @@ struct HeadlessArrayOf return_trace (true); } + private: + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (len.sanitize (c) && + (!len || c->check_array (array, Type::static_size, len - 1))); + } + + public: LenType len; Type array[VAR]; public: @@ -1036,19 +1025,22 @@ struct HeadlessArrayOf }; -/* An array with sorted elements. Supports binary searching. */ -template <typename Type, typename LenType=USHORT> +/* + * An array with sorted elements. Supports binary searching. + */ +template <typename Type, typename LenType=UINT16> struct SortedArrayOf : ArrayOf<Type, LenType> { template <typename SearchType> inline int bsearch (const SearchType &x) const { /* Hand-coded bsearch here since this is in the hot inner loop. */ + const Type *array = this->array; int min = 0, max = (int) this->len - 1; while (min <= max) { int mid = (min + max) / 2; - int c = this->array[mid].cmp (x); + int c = array[mid].cmp (x); if (c < 0) max = mid - 1; else if (c > 0) @@ -1060,6 +1052,131 @@ struct SortedArrayOf : ArrayOf<Type, LenType> } }; +/* + * Binary-search arrays + */ + +struct BinSearchHeader +{ + inline operator uint32_t (void) const { return len; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + UINT16 len; + UINT16 searchRangeZ; + UINT16 entrySelectorZ; + UINT16 rangeShiftZ; + + public: + DEFINE_SIZE_STATIC (8); +}; + +template <typename Type> +struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {}; + + +/* Lazy struct and blob loaders. */ + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template <typename T> +struct hb_lazy_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = nullptr; + } + + inline void fini (void) + { + if (instance && instance != &OT::Null(T)) + { + instance->fini(); + free (instance); + } + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + p = (T *) calloc (1, sizeof (T)); + if (unlikely (!p)) + p = const_cast<T *> (&OT::Null(T)); + else + p->init (face); + if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p))) + { + if (p != &OT::Null(T)) + p->fini (); + goto retry; + } + } + return p; + } + + inline const T* operator-> (void) const + { + return get (); + } + + private: + hb_face_t *face; + T *instance; +}; + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template <typename T> +struct hb_lazy_table_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = nullptr; + blob = nullptr; + } + + inline void fini (void) + { + hb_blob_destroy (blob); + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + hb_blob_t *blob_ = OT::Sanitizer<T>::sanitize (face->reference_table (T::tableTag)); + p = const_cast<T *>(OT::Sanitizer<T>::lock_instance (blob_)); + if (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)) + { + hb_blob_destroy (blob_); + goto retry; + } + blob = blob_; + } + return p; + } + + inline const T* operator-> (void) const + { + return get(); + } + + private: + hb_face_t *face; + T *instance; + mutable hb_blob_t *blob; +}; + } /* namespace OT */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cbdt-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cbdt-table.hh index 52897abd3a..415625e5f8 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cbdt-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cbdt-table.hh @@ -47,20 +47,20 @@ struct SmallGlyphMetrics extents->height = -height; } - BYTE height; - BYTE width; - CHAR bearingX; - CHAR bearingY; - BYTE advance; + UINT8 height; + UINT8 width; + INT8 bearingX; + INT8 bearingY; + UINT8 advance; DEFINE_SIZE_STATIC(5); }; struct BigGlyphMetrics : SmallGlyphMetrics { - CHAR vertBearingX; - CHAR vertBearingY; - BYTE vertAdvance; + INT8 vertBearingX; + INT8 vertBearingY; + UINT8 vertAdvance; DEFINE_SIZE_STATIC(8); }; @@ -73,18 +73,18 @@ struct SBitLineMetrics return_trace (c->check_struct (this)); } - CHAR ascender; - CHAR decender; - BYTE widthMax; - CHAR caretSlopeNumerator; - CHAR caretSlopeDenominator; - CHAR caretOffset; - CHAR minOriginSB; - CHAR minAdvanceSB; - CHAR maxBeforeBL; - CHAR minAfterBL; - CHAR padding1; - CHAR padding2; + INT8 ascender; + INT8 decender; + UINT8 widthMax; + INT8 caretSlopeNumerator; + INT8 caretSlopeDenominator; + INT8 caretOffset; + INT8 minOriginSB; + INT8 minAdvanceSB; + INT8 maxBeforeBL; + INT8 minAfterBL; + INT8 padding1; + INT8 padding2; DEFINE_SIZE_STATIC(12); }; @@ -102,9 +102,9 @@ struct IndexSubtableHeader return_trace (c->check_struct (this)); } - USHORT indexFormat; - USHORT imageFormat; - ULONG imageDataOffset; + UINT16 indexFormat; + UINT16 imageFormat; + UINT32 imageDataOffset; DEFINE_SIZE_STATIC(8); }; @@ -137,8 +137,8 @@ struct IndexSubtableFormat1Or3 DEFINE_SIZE_ARRAY(8, offsetArrayZ); }; -struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<ULONG> {}; -struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<USHORT> {}; +struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<UINT32> {}; +struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<UINT16> {}; struct IndexSubtable { @@ -214,9 +214,9 @@ struct IndexSubtableRecord offset, length, format); } - USHORT firstGlyphIndex; - USHORT lastGlyphIndex; - OffsetTo<IndexSubtable, ULONG> offsetToSubtable; + UINT16 firstGlyphIndex; + UINT16 lastGlyphIndex; + LOffsetTo<IndexSubtable> offsetToSubtable; DEFINE_SIZE_STATIC(8); }; @@ -245,7 +245,7 @@ struct IndexSubtableArray return &indexSubtablesZ[i]; } } - return NULL; + return nullptr; } protected: @@ -275,20 +275,20 @@ struct BitmapSizeTable } protected: - OffsetTo<IndexSubtableArray, ULONG> indexSubtableArrayOffset; - ULONG indexTablesSize; - ULONG numberOfIndexSubtables; - ULONG colorRef; + LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset; + UINT32 indexTablesSize; + UINT32 numberOfIndexSubtables; + UINT32 colorRef; SBitLineMetrics horizontal; SBitLineMetrics vertical; - USHORT startGlyphIndex; - USHORT endGlyphIndex; - BYTE ppemX; - BYTE ppemY; - BYTE bitDepth; - CHAR flags; - -public: + UINT16 startGlyphIndex; + UINT16 endGlyphIndex; + UINT8 ppemX; + UINT8 ppemY; + UINT8 bitDepth; + INT8 flags; + + public: DEFINE_SIZE_STATIC(48); }; @@ -300,8 +300,8 @@ public: struct GlyphBitmapDataFormat17 { SmallGlyphMetrics glyphMetrics; - ULONG dataLen; - BYTE dataZ[VAR]; + UINT32 dataLen; + UINT8 dataZ[VAR]; DEFINE_SIZE_ARRAY(9, dataZ); }; @@ -315,6 +315,8 @@ struct GlyphBitmapDataFormat17 struct CBLC { + friend struct CBDT; + static const hb_tag_t tableTag = HB_OT_TAG_CBLC; inline bool sanitize (hb_sanitize_context_t *c) const @@ -325,7 +327,7 @@ struct CBLC sizeTables.sanitize (c, this)); } - public: + protected: const IndexSubtableRecord *find_table (hb_codepoint_t glyph, unsigned int *x_ppem, unsigned int *y_ppem) const { @@ -344,12 +346,12 @@ struct CBLC } } - return NULL; + return nullptr; } protected: - FixedVersion<>version; - ArrayOf<BitmapSizeTable, ULONG> sizeTables; + FixedVersion<> version; + LArrayOf<BitmapSizeTable> sizeTables; public: DEFINE_SIZE_ARRAY(8, sizeTables); @@ -371,9 +373,94 @@ struct CBDT likely (version.major == 2 || version.major == 3)); } + struct accelerator_t + { + inline void init (hb_face_t *face) + { + upem = face->get_upem(); + + cblc_blob = Sanitizer<CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC)); + cbdt_blob = Sanitizer<CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT)); + cbdt_len = hb_blob_get_length (cbdt_blob); + + if (hb_blob_get_length (cblc_blob) == 0) { + cblc = nullptr; + cbdt = nullptr; + return; /* Not a bitmap font. */ + } + cblc = Sanitizer<CBLC>::lock_instance (cblc_blob); + cbdt = Sanitizer<CBDT>::lock_instance (cbdt_blob); + + } + + inline void fini (void) + { + hb_blob_destroy (this->cblc_blob); + hb_blob_destroy (this->cbdt_blob); + } + + inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const + { + unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */ + + if (!cblc) + return false; // Not a color bitmap font. + + const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem); + if (!subtable_record || !x_ppem || !y_ppem) + return false; + + if (subtable_record->get_extents (extents)) + return true; + + unsigned int image_offset = 0, image_length = 0, image_format = 0; + if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) + return false; + + { + if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) + return false; + + switch (image_format) + { + case 17: { + if (unlikely (image_length < GlyphBitmapDataFormat17::min_size)) + return false; + + const GlyphBitmapDataFormat17& glyphFormat17 = + StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset); + glyphFormat17.glyphMetrics.get_extents (extents); + } + break; + default: + // TODO: Support other image formats. + return false; + } + } + + /* Convert to the font units. */ + extents->x_bearing *= upem / (float) x_ppem; + extents->y_bearing *= upem / (float) y_ppem; + extents->width *= upem / (float) x_ppem; + extents->height *= upem / (float) y_ppem; + + return true; + } + + private: + hb_blob_t *cblc_blob; + hb_blob_t *cbdt_blob; + const CBLC *cblc; + const CBDT *cbdt; + + unsigned int cbdt_len; + unsigned int upem; + }; + + protected: FixedVersion<>version; - BYTE dataZ[VAR]; + UINT8 dataZ[VAR]; public: DEFINE_SIZE_ARRAY(4, dataZ); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh index d7a94a1ef0..883d7b3f0b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh @@ -58,10 +58,10 @@ struct CmapSubtableFormat0 } protected: - USHORT format; /* Format number is set to 0. */ - USHORT lengthZ; /* Byte length of this subtable. */ - USHORT languageZ; /* Ignore. */ - BYTE glyphIdArray[256];/* An array that maps character + UINT16 format; /* Format number is set to 0. */ + UINT16 lengthZ; /* Byte length of this subtable. */ + UINT16 languageZ; /* Ignore. */ + UINT8 glyphIdArray[256];/* An array that maps character * code to glyph index values. */ public: DEFINE_SIZE_STATIC (6 + 256); @@ -88,8 +88,8 @@ struct CmapSubtableFormat4 /* Custom two-array bsearch. */ int min = 0, max = (int) thiz->segCount - 1; - const USHORT *startCount = thiz->startCount; - const USHORT *endCount = thiz->endCount; + const UINT16 *startCount = thiz->startCount; + const UINT16 *endCount = thiz->endCount; unsigned int i; while (min <= max) { @@ -127,11 +127,11 @@ struct CmapSubtableFormat4 return true; } - const USHORT *endCount; - const USHORT *startCount; - const USHORT *idDelta; - const USHORT *idRangeOffset; - const USHORT *glyphIdArray; + const UINT16 *endCount; + const UINT16 *startCount; + const UINT16 *idDelta; + const UINT16 *idRangeOffset; + const UINT16 *glyphIdArray; unsigned int segCount; unsigned int glyphIdArrayLength; }; @@ -165,24 +165,24 @@ struct CmapSubtableFormat4 } protected: - USHORT format; /* Format number is set to 4. */ - USHORT length; /* This is the length in bytes of the + UINT16 format; /* Format number is set to 4. */ + UINT16 length; /* This is the length in bytes of the * subtable. */ - USHORT languageZ; /* Ignore. */ - USHORT segCountX2; /* 2 x segCount. */ - USHORT searchRangeZ; /* 2 * (2**floor(log2(segCount))) */ - USHORT entrySelectorZ; /* log2(searchRange/2) */ - USHORT rangeShiftZ; /* 2 x segCount - searchRange */ + UINT16 languageZ; /* Ignore. */ + UINT16 segCountX2; /* 2 x segCount. */ + UINT16 searchRangeZ; /* 2 * (2**floor(log2(segCount))) */ + UINT16 entrySelectorZ; /* log2(searchRange/2) */ + UINT16 rangeShiftZ; /* 2 x segCount - searchRange */ - USHORT values[VAR]; + UINT16 values[VAR]; #if 0 - USHORT endCount[segCount]; /* End characterCode for each segment, + UINT16 endCount[segCount]; /* End characterCode for each segment, * last=0xFFFFu. */ - USHORT reservedPad; /* Set to 0. */ - USHORT startCount[segCount]; /* Start character code for each segment. */ - SHORT idDelta[segCount]; /* Delta for all character codes in segment. */ - USHORT idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */ - USHORT glyphIdArray[VAR]; /* Glyph index array (arbitrary length) */ + UINT16 reservedPad; /* Set to 0. */ + UINT16 startCount[segCount]; /* Start character code for each segment. */ + INT16 idDelta[segCount]; /* Delta for all character codes in segment. */ + UINT16 idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */ + UINT16 glyphIdArray[VAR]; /* Glyph index array (arbitrary length) */ #endif public: @@ -208,9 +208,9 @@ struct CmapSubtableLongGroup } private: - ULONG startCharCode; /* First character code in this group. */ - ULONG endCharCode; /* Last character code in this group. */ - ULONG glyphID; /* Glyph index; interpretation depends on + UINT32 startCharCode; /* First character code in this group. */ + UINT32 endCharCode; /* Last character code in this group. */ + UINT32 glyphID; /* Glyph index; interpretation depends on * subtable format. */ public: DEFINE_SIZE_STATIC (12); @@ -247,8 +247,8 @@ struct CmapSubtableTrimmed DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray); }; -struct CmapSubtableFormat6 : CmapSubtableTrimmed<USHORT> {}; -struct CmapSubtableFormat10 : CmapSubtableTrimmed<ULONG > {}; +struct CmapSubtableFormat6 : CmapSubtableTrimmed<UINT16> {}; +struct CmapSubtableFormat10 : CmapSubtableTrimmed<UINT32 > {}; template <typename T> struct CmapSubtableLongSegmented @@ -269,11 +269,11 @@ struct CmapSubtableLongSegmented } protected: - USHORT format; /* Subtable format; set to 12. */ - USHORT reservedZ; /* Reserved; set to 0. */ - ULONG lengthZ; /* Byte length of this subtable. */ - ULONG languageZ; /* Ignore. */ - SortedArrayOf<CmapSubtableLongGroup, ULONG> + UINT16 format; /* Subtable format; set to 12. */ + UINT16 reservedZ; /* Reserved; set to 0. */ + UINT32 lengthZ; /* Byte length of this subtable. */ + UINT32 languageZ; /* Ignore. */ + SortedArrayOf<CmapSubtableLongGroup, UINT32> groups; /* Groupings. */ public: DEFINE_SIZE_ARRAY (16, groups); @@ -316,13 +316,13 @@ struct UnicodeValueRange } UINT24 startUnicodeValue; /* First value in this range. */ - BYTE additionalCount; /* Number of additional values in this + UINT8 additionalCount; /* Number of additional values in this * range. */ public: DEFINE_SIZE_STATIC (4); }; -typedef SortedArrayOf<UnicodeValueRange, ULONG> DefaultUVS; +typedef SortedArrayOf<UnicodeValueRange, UINT32> DefaultUVS; struct UVSMapping { @@ -343,7 +343,7 @@ struct UVSMapping DEFINE_SIZE_STATIC (5); }; -typedef SortedArrayOf<UVSMapping, ULONG> NonDefaultUVS; +typedef SortedArrayOf<UVSMapping, UINT32> NonDefaultUVS; struct VariationSelectorRecord { @@ -380,9 +380,9 @@ struct VariationSelectorRecord } UINT24 varSelector; /* Variation selector. */ - OffsetTo<DefaultUVS, ULONG> + LOffsetTo<DefaultUVS> defaultUVS; /* Offset to Default UVS Table. May be 0. */ - OffsetTo<NonDefaultUVS, ULONG> + LOffsetTo<NonDefaultUVS> nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ public: DEFINE_SIZE_STATIC (11); @@ -405,9 +405,9 @@ struct CmapSubtableFormat14 } protected: - USHORT format; /* Format number is set to 14. */ - ULONG lengthZ; /* Byte length of this subtable. */ - SortedArrayOf<VariationSelectorRecord, ULONG> + UINT16 format; /* Format number is set to 14. */ + UINT32 lengthZ; /* Byte length of this subtable. */ + SortedArrayOf<VariationSelectorRecord, UINT32> record; /* Variation selector records; sorted * in increasing order of `varSelector'. */ public: @@ -451,7 +451,7 @@ struct CmapSubtable public: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ CmapSubtableFormat0 format0; CmapSubtableFormat4 format4; CmapSubtableFormat6 format6; @@ -484,9 +484,9 @@ struct EncodingRecord subtable.sanitize (c, base)); } - USHORT platformID; /* Platform ID. */ - USHORT encodingID; /* Platform-specific encoding ID. */ - OffsetTo<CmapSubtable, ULONG> + UINT16 platformID; /* Platform ID. */ + UINT16 encodingID; /* Platform-specific encoding ID. */ + LOffsetTo<CmapSubtable> subtable; /* Byte offset from beginning of table to the subtable for this encoding. */ public: DEFINE_SIZE_STATIC (8); @@ -496,6 +496,146 @@ struct cmap { static const hb_tag_t tableTag = HB_OT_TAG_cmap; + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + likely (version == 0) && + encodingRecord.sanitize (c, this)); + } + + struct accelerator_t + { + inline void init (hb_face_t *face) + { + this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap)); + const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob); + const OT::CmapSubtable *subtable = nullptr; + const OT::CmapSubtableFormat14 *subtable_uvs = nullptr; + + bool symbol = false; + /* 32-bit subtables. */ + if (!subtable) subtable = cmap->find_subtable (3, 10); + if (!subtable) subtable = cmap->find_subtable (0, 6); + if (!subtable) subtable = cmap->find_subtable (0, 4); + /* 16-bit subtables. */ + if (!subtable) subtable = cmap->find_subtable (3, 1); + if (!subtable) subtable = cmap->find_subtable (0, 3); + if (!subtable) subtable = cmap->find_subtable (0, 2); + if (!subtable) subtable = cmap->find_subtable (0, 1); + if (!subtable) subtable = cmap->find_subtable (0, 0); + if (!subtable) + { + subtable = cmap->find_subtable (3, 0); + if (subtable) symbol = true; + } + /* Meh. */ + if (!subtable) subtable = &OT::Null(OT::CmapSubtable); + + /* UVS subtable. */ + if (!subtable_uvs) + { + const OT::CmapSubtable *st = cmap->find_subtable (0, 5); + if (st && st->u.format == 14) + subtable_uvs = &st->u.format14; + } + /* Meh. */ + if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14); + + this->uvs_table = subtable_uvs; + + this->get_glyph_data = subtable; + if (unlikely (symbol)) + this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>; + else + switch (subtable->u.format) { + /* Accelerate format 4 and format 12. */ + default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>; break; + case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>; break; + case 4: + { + this->format4_accel.init (&subtable->u.format4); + this->get_glyph_data = &this->format4_accel; + this->get_glyph_func = this->format4_accel.get_glyph_func; + } + break; + } + } + + inline void fini (void) + { + hb_blob_destroy (this->blob); + } + + inline bool get_nominal_glyph (hb_codepoint_t unicode, + hb_codepoint_t *glyph) const + { + return this->get_glyph_func (this->get_glyph_data, unicode, glyph); + } + + inline bool get_variation_glyph (hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph) const + { + switch (this->uvs_table->get_glyph_variant (unicode, + variation_selector, + glyph)) + { + case OT::GLYPH_VARIANT_NOT_FOUND: return false; + case OT::GLYPH_VARIANT_FOUND: return true; + case OT::GLYPH_VARIANT_USE_DEFAULT: break; + } + + return get_nominal_glyph (unicode, glyph); + } + + protected: + typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph); + + template <typename Type> + static inline bool get_glyph_from (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) + { + const Type *typed_obj = (const Type *) obj; + return typed_obj->get_glyph (codepoint, glyph); + } + + template <typename Type> + static inline bool get_glyph_from_symbol (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) + { + const Type *typed_obj = (const Type *) obj; + if (likely (typed_obj->get_glyph (codepoint, glyph))) + return true; + + if (codepoint <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". */ + return typed_obj->get_glyph (0xF000u + codepoint, glyph); + } + + return false; + } + + private: + hb_cmap_get_glyph_func_t get_glyph_func; + const void *get_glyph_data; + OT::CmapSubtableFormat4::accelerator_t format4_accel; + + const OT::CmapSubtableFormat14 *uvs_table; + hb_blob_t *blob; + }; + + protected: + inline const CmapSubtable *find_subtable (unsigned int platform_id, unsigned int encoding_id) const { @@ -508,20 +648,13 @@ struct cmap * unsorted subtable list. */ int result = encodingRecord./*bsearch*/lsearch (key); if (result == -1 || !encodingRecord[result].subtable) - return NULL; + return nullptr; return &(this+encodingRecord[result].subtable); } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && - likely (version == 0) && - encodingRecord.sanitize (c, this)); - } - - USHORT version; /* Table version number (0). */ + protected: + UINT16 version; /* Table version number (0). */ SortedArrayOf<EncodingRecord> encodingRecord; /* Encoding tables. */ public: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc index 5be055d344..9864064b11 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc @@ -33,443 +33,20 @@ #include "hb-ot-cmap-table.hh" #include "hb-ot-cbdt-table.hh" #include "hb-ot-glyf-table.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-hhea-table.hh" #include "hb-ot-hmtx-table.hh" -#include "hb-ot-os2-table.hh" -//#include "hb-ot-post-table.hh" +#include "hb-ot-kern-table.hh" +#include "hb-ot-post-table.hh" -struct hb_ot_face_metrics_accelerator_t -{ - unsigned int num_metrics; - unsigned int num_advances; - unsigned int default_advance; - unsigned short ascender; - unsigned short descender; - unsigned short line_gap; - bool has_font_extents; - - const OT::_mtx *table; - hb_blob_t *blob; - - inline void init (hb_face_t *face, - hb_tag_t _hea_tag, - hb_tag_t _mtx_tag, - hb_tag_t os2_tag, - unsigned int default_advance = 0) - { - this->default_advance = default_advance ? default_advance : face->get_upem (); - - bool got_font_extents = false; - if (os2_tag) - { - hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag)); - const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob); -#define USE_TYPO_METRICS (1u<<7) - if (0 != (os2->fsSelection & USE_TYPO_METRICS)) - { - this->ascender = os2->sTypoAscender; - this->descender = os2->sTypoDescender; - this->line_gap = os2->sTypoLineGap; - got_font_extents = (this->ascender | this->descender) != 0; - } - hb_blob_destroy (os2_blob); - } - - hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag)); - const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob); - this->num_advances = _hea->numberOfLongMetrics; - if (!got_font_extents) - { - this->ascender = _hea->ascender; - this->descender = _hea->descender; - this->line_gap = _hea->lineGap; - got_font_extents = (this->ascender | this->descender) != 0; - } - hb_blob_destroy (_hea_blob); - - this->has_font_extents = got_font_extents; - - this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag)); - - /* Cap num_metrics() and num_advances() based on table length. */ - unsigned int len = hb_blob_get_length (this->blob); - if (unlikely (this->num_advances * 4 > len)) - this->num_advances = len / 4; - this->num_metrics = this->num_advances + (len - 4 * this->num_advances) / 2; - - /* We MUST set num_metrics to zero if num_advances is zero. - * Our get_advance() depends on that. */ - if (unlikely (!this->num_advances)) - { - this->num_metrics = this->num_advances = 0; - hb_blob_destroy (this->blob); - this->blob = hb_blob_get_empty (); - } - this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob); - } - - inline void fini (void) - { - hb_blob_destroy (this->blob); - } - - inline unsigned int get_advance (hb_codepoint_t glyph) const - { - if (unlikely (glyph >= this->num_metrics)) - { - /* If this->num_metrics is zero, it means we don't have the metrics table - * for this direction: return default advance. Otherwise, it means that the - * glyph index is out of bound: return zero. */ - if (this->num_metrics) - return 0; - else - return this->default_advance; - } - - if (glyph >= this->num_advances) - glyph = this->num_advances - 1; - - return this->table->longMetric[glyph].advance; - } -}; - -struct hb_ot_face_glyf_accelerator_t -{ - bool short_offset; - unsigned int num_glyphs; - const OT::loca *loca; - const OT::glyf *glyf; - hb_blob_t *loca_blob; - hb_blob_t *glyf_blob; - unsigned int glyf_len; - - inline void init (hb_face_t *face) - { - hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head)); - const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob); - if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0) - { - /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ - hb_blob_destroy (head_blob); - return; - } - this->short_offset = 0 == head->indexToLocFormat; - hb_blob_destroy (head_blob); - - this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca)); - this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob); - this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf)); - this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob); - - this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1; - this->glyf_len = hb_blob_get_length (this->glyf_blob); - } - - inline void fini (void) - { - hb_blob_destroy (this->loca_blob); - hb_blob_destroy (this->glyf_blob); - } - - inline bool get_extents (hb_codepoint_t glyph, - hb_glyph_extents_t *extents) const - { - if (unlikely (glyph >= this->num_glyphs)) - return false; - - unsigned int start_offset, end_offset; - if (this->short_offset) - { - start_offset = 2 * this->loca->u.shortsZ[glyph]; - end_offset = 2 * this->loca->u.shortsZ[glyph + 1]; - } - else - { - start_offset = this->loca->u.longsZ[glyph]; - end_offset = this->loca->u.longsZ[glyph + 1]; - } - - if (start_offset > end_offset || end_offset > this->glyf_len) - return false; - - if (end_offset - start_offset < OT::glyfGlyphHeader::static_size) - return true; /* Empty glyph; zero extents. */ - - const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset); - - extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); - extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); - extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing; - extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; - - return true; - } -}; - -struct hb_ot_face_cbdt_accelerator_t -{ - hb_blob_t *cblc_blob; - hb_blob_t *cbdt_blob; - const OT::CBLC *cblc; - const OT::CBDT *cbdt; - - unsigned int cbdt_len; - float upem; - - inline void init (hb_face_t *face) - { - upem = face->get_upem(); - - cblc_blob = OT::Sanitizer<OT::CBLC>::sanitize (face->reference_table (HB_OT_TAG_CBLC)); - cbdt_blob = OT::Sanitizer<OT::CBDT>::sanitize (face->reference_table (HB_OT_TAG_CBDT)); - cbdt_len = hb_blob_get_length (cbdt_blob); - - if (hb_blob_get_length (cblc_blob) == 0) { - cblc = NULL; - cbdt = NULL; - return; /* Not a bitmap font. */ - } - cblc = OT::Sanitizer<OT::CBLC>::lock_instance (cblc_blob); - cbdt = OT::Sanitizer<OT::CBDT>::lock_instance (cbdt_blob); - - } - - inline void fini (void) - { - hb_blob_destroy (this->cblc_blob); - hb_blob_destroy (this->cbdt_blob); - } - - inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const - { - unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */ - - if (cblc == NULL) - return false; // Not a color bitmap font. - - const OT::IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem); - if (subtable_record == NULL) - return false; - - if (subtable_record->get_extents (extents)) - return true; - - unsigned int image_offset = 0, image_length = 0, image_format = 0; - if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) - return false; - - { - /* TODO Move the following into CBDT struct when adding more formats. */ - - if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length)) - return false; - - switch (image_format) - { - case 17: { - if (unlikely (image_length < OT::GlyphBitmapDataFormat17::min_size)) - return false; - - const OT::GlyphBitmapDataFormat17& glyphFormat17 = - OT::StructAtOffset<OT::GlyphBitmapDataFormat17> (this->cbdt, image_offset); - glyphFormat17.glyphMetrics.get_extents (extents); - } - break; - default: - // TODO: Support other image formats. - return false; - } - } - - /* Convert to the font units. */ - extents->x_bearing *= upem / (float) x_ppem; - extents->y_bearing *= upem / (float) y_ppem; - extents->width *= upem / (float) x_ppem; - extents->height *= upem / (float) y_ppem; - - return true; - } -}; - -typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, - hb_codepoint_t codepoint, - hb_codepoint_t *glyph); - -template <typename Type> -static inline bool get_glyph_from (const void *obj, - hb_codepoint_t codepoint, - hb_codepoint_t *glyph) -{ - const Type *typed_obj = (const Type *) obj; - return typed_obj->get_glyph (codepoint, glyph); -} - -template <typename Type> -static inline bool get_glyph_from_symbol (const void *obj, - hb_codepoint_t codepoint, - hb_codepoint_t *glyph) -{ - const Type *typed_obj = (const Type *) obj; - if (likely (typed_obj->get_glyph (codepoint, glyph))) - return true; - - if (codepoint <= 0x00FFu) - { - /* For symbol-encoded OpenType fonts, we duplicate the - * U+F000..F0FF range at U+0000..U+00FF. That's what - * Windows seems to do, and that's hinted about at: - * http://www.microsoft.com/typography/otspec/recom.htm - * under "Non-Standard (Symbol) Fonts". */ - return typed_obj->get_glyph (0xF000u + codepoint, glyph); - } - - return false; -} - -struct hb_ot_face_cmap_accelerator_t -{ - hb_cmap_get_glyph_func_t get_glyph_func; - const void *get_glyph_data; - OT::CmapSubtableFormat4::accelerator_t format4_accel; - - const OT::CmapSubtableFormat14 *uvs_table; - hb_blob_t *blob; - - inline void init (hb_face_t *face) - { - this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap)); - const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob); - const OT::CmapSubtable *subtable = NULL; - const OT::CmapSubtableFormat14 *subtable_uvs = NULL; - - bool symbol = false; - /* 32-bit subtables. */ - if (!subtable) subtable = cmap->find_subtable (3, 10); - if (!subtable) subtable = cmap->find_subtable (0, 6); - if (!subtable) subtable = cmap->find_subtable (0, 4); - /* 16-bit subtables. */ - if (!subtable) subtable = cmap->find_subtable (3, 1); - if (!subtable) subtable = cmap->find_subtable (0, 3); - if (!subtable) subtable = cmap->find_subtable (0, 2); - if (!subtable) subtable = cmap->find_subtable (0, 1); - if (!subtable) subtable = cmap->find_subtable (0, 0); - if (!subtable) - { - subtable = cmap->find_subtable (3, 0); - if (subtable) symbol = true; - } - /* Meh. */ - if (!subtable) subtable = &OT::Null(OT::CmapSubtable); - - /* UVS subtable. */ - if (!subtable_uvs) - { - const OT::CmapSubtable *st = cmap->find_subtable (0, 5); - if (st && st->u.format == 14) - subtable_uvs = &st->u.format14; - } - /* Meh. */ - if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14); - - this->uvs_table = subtable_uvs; - - this->get_glyph_data = subtable; - if (unlikely (symbol)) - this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>; - else - switch (subtable->u.format) { - /* Accelerate format 4 and format 12. */ - default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>; break; - case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>; break; - case 4: - { - this->format4_accel.init (&subtable->u.format4); - this->get_glyph_data = &this->format4_accel; - this->get_glyph_func = this->format4_accel.get_glyph_func; - } - break; - } - } - - inline void fini (void) - { - hb_blob_destroy (this->blob); - } - - inline bool get_nominal_glyph (hb_codepoint_t unicode, - hb_codepoint_t *glyph) const - { - return this->get_glyph_func (this->get_glyph_data, unicode, glyph); - } - - inline bool get_variation_glyph (hb_codepoint_t unicode, - hb_codepoint_t variation_selector, - hb_codepoint_t *glyph) const - { - switch (this->uvs_table->get_glyph_variant (unicode, - variation_selector, - glyph)) - { - case OT::GLYPH_VARIANT_NOT_FOUND: return false; - case OT::GLYPH_VARIANT_FOUND: return true; - case OT::GLYPH_VARIANT_USE_DEFAULT: break; - } - - return get_nominal_glyph (unicode, glyph); - } -}; - -template <typename T> -struct hb_lazy_loader_t -{ - inline void init (hb_face_t *face_) - { - face = face_; - instance = NULL; - } - - inline void fini (void) - { - if (instance && instance != &OT::Null(T)) - { - instance->fini(); - free (instance); - } - } - - inline const T* operator-> (void) const - { - retry: - T *p = (T *) hb_atomic_ptr_get (&instance); - if (unlikely (!p)) - { - p = (T *) calloc (1, sizeof (T)); - if (unlikely (!p)) - return &OT::Null(T); - p->init (face); - if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p))) - { - p->fini (); - goto retry; - } - } - return p; - } - - private: - hb_face_t *face; - T *instance; -}; - struct hb_ot_font_t { - hb_ot_face_cmap_accelerator_t cmap; - hb_ot_face_metrics_accelerator_t h_metrics; - hb_ot_face_metrics_accelerator_t v_metrics; - hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf; - hb_lazy_loader_t<hb_ot_face_cbdt_accelerator_t> cbdt; + OT::cmap::accelerator_t cmap; + OT::hmtx::accelerator_t h_metrics; + OT::vmtx::accelerator_t v_metrics; + OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf; + OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt; + OT::hb_lazy_loader_t<OT::post::accelerator_t> post; + OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern; }; @@ -479,26 +56,31 @@ _hb_ot_font_create (hb_face_t *face) hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); if (unlikely (!ot_font)) - return NULL; + return nullptr; ot_font->cmap.init (face); - ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2); - ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE, - ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ + ot_font->h_metrics.init (face); + ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ ot_font->glyf.init (face); ot_font->cbdt.init (face); + ot_font->post.init (face); + ot_font->kern.init (face); return ot_font; } static void -_hb_ot_font_destroy (hb_ot_font_t *ot_font) +_hb_ot_font_destroy (void *data) { + hb_ot_font_t *ot_font = (hb_ot_font_t *) data; + ot_font->cmap.fini (); ot_font->h_metrics.fini (); ot_font->v_metrics.fini (); ot_font->glyf.fini (); ot_font->cbdt.fini (); + ot_font->post.fini (); + ot_font->kern.fini (); free (ot_font); } @@ -529,23 +111,34 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, } static hb_position_t -hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, +hb_ot_get_glyph_h_advance (hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); + return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font)); } static hb_position_t -hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, +hb_ot_get_glyph_v_advance (hb_font_t *font, void *font_data, hb_codepoint_t glyph, void *user_data HB_UNUSED) { const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; - return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); + return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font)); +} + +static hb_position_t +hb_ot_get_glyph_h_kerning (hb_font_t *font, + void *font_data, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) +{ + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph)); } static hb_bool_t @@ -559,6 +152,7 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, bool ret = ot_font->glyf->get_extents (glyph, extents); if (!ret) ret = ot_font->cbdt->get_extents (glyph, extents); + // TODO Hook up side-bearings variations. extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); extents->width = font->em_scale_x (extents->width); @@ -567,6 +161,28 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, } static hb_bool_t +hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, + void *font_data, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) +{ + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + return ot_font->post->get_glyph_name (glyph, name, size); +} + +static hb_bool_t +hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, + void *font_data, + const char *name, int len, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; + return ot_font->post->get_glyph_from_name (name, len, glyph); +} + +static hb_bool_t hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, void *font_data, hb_font_extents_t *metrics, @@ -576,6 +192,7 @@ hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); + // TODO Hook up variations. return ot_font->h_metrics.has_font_extents; } @@ -589,10 +206,11 @@ hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); + // TODO Hook up variations. return ot_font->v_metrics.has_font_extents; } -static hb_font_funcs_t *static_ot_funcs = NULL; +static hb_font_funcs_t *static_ot_funcs = nullptr; #ifdef HB_USE_ATEXIT static @@ -612,24 +230,24 @@ retry: { funcs = hb_font_funcs_create (); - hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL); - hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL); - hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, NULL, NULL); - hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, NULL, NULL); - hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); - hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); - //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); - //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); - //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO - //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); - hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL); - //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO - //hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO - //hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO + hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr); + hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr); + hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); + hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); + hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr); + //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr); + //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); + hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr); + //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr); + hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr); + //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr); + hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr); + hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr); hb_font_funcs_make_immutable (funcs); - if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) { + if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) { hb_font_funcs_destroy (funcs); goto retry; } @@ -658,5 +276,5 @@ hb_ot_font_set_funcs (hb_font_t *font) hb_font_set_funcs (font, _hb_ot_get_font_funcs (), ot_font, - (hb_destroy_func_t) _hb_ot_font_destroy); + _hb_ot_font_destroy); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh index dc7aa8469a..88d3850b6e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-glyf-table.hh @@ -28,6 +28,7 @@ #define HB_OT_GLYF_TABLE_HH #include "hb-open-type-private.hh" +#include "hb-ot-head-table.hh" namespace OT { @@ -42,6 +43,8 @@ namespace OT { struct loca { + friend struct glyf; + static const hb_tag_t tableTag = HB_OT_TAG_loca; inline bool sanitize (hb_sanitize_context_t *c) const @@ -50,12 +53,9 @@ struct loca return_trace (true); } - public: - union { - USHORT shortsZ[VAR]; /* Location offset divided by 2. */ - ULONG longsZ[VAR]; /* Location offset. */ - } u; - DEFINE_SIZE_ARRAY (0, u.longsZ); + protected: + UINT8 dataX[VAR]; /* Location data. */ + DEFINE_SIZE_ARRAY (0, dataX); }; @@ -78,26 +78,102 @@ struct glyf return_trace (true); } - public: - BYTE dataX[VAR]; /* Glyphs data. */ + struct GlyphHeader + { + INT16 numberOfContours; /* If the number of contours is + * greater than or equal to zero, + * this is a simple glyph; if negative, + * this is a composite glyph. */ + FWORD xMin; /* Minimum x for coordinate data. */ + FWORD yMin; /* Minimum y for coordinate data. */ + FWORD xMax; /* Maximum x for coordinate data. */ + FWORD yMax; /* Maximum y for coordinate data. */ + + DEFINE_SIZE_STATIC (10); + }; + + struct accelerator_t + { + inline void init (hb_face_t *face) + { + hb_blob_t *head_blob = Sanitizer<head>::sanitize (face->reference_table (HB_OT_TAG_head)); + const head *head_table = Sanitizer<head>::lock_instance (head_blob); + if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0) + { + /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ + hb_blob_destroy (head_blob); + return; + } + short_offset = 0 == head_table->indexToLocFormat; + hb_blob_destroy (head_blob); + + loca_blob = Sanitizer<loca>::sanitize (face->reference_table (HB_OT_TAG_loca)); + loca_table = Sanitizer<loca>::lock_instance (loca_blob); + glyf_blob = Sanitizer<glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf)); + glyf_table = Sanitizer<glyf>::lock_instance (glyf_blob); + + num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1; + glyf_len = hb_blob_get_length (glyf_blob); + } + + inline void fini (void) + { + hb_blob_destroy (loca_blob); + hb_blob_destroy (glyf_blob); + } + + inline bool get_extents (hb_codepoint_t glyph, + hb_glyph_extents_t *extents) const + { + if (unlikely (glyph >= num_glyphs)) + return false; + + unsigned int start_offset, end_offset; + if (short_offset) + { + const UINT16 *offsets = (const UINT16 *) loca_table->dataX; + start_offset = 2 * offsets[glyph]; + end_offset = 2 * offsets[glyph + 1]; + } + else + { + const UINT32 *offsets = (const UINT32 *) loca_table->dataX; + start_offset = offsets[glyph]; + end_offset = offsets[glyph + 1]; + } + + if (start_offset > end_offset || end_offset > glyf_len) + return false; + + if (end_offset - start_offset < GlyphHeader::static_size) + return true; /* Empty glyph; zero extents. */ + + const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset); + + extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); + extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); + extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing; + extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; + + return true; + } + + private: + bool short_offset; + unsigned int num_glyphs; + const loca *loca_table; + const glyf *glyf_table; + hb_blob_t *loca_blob; + hb_blob_t *glyf_blob; + unsigned int glyf_len; + }; + + protected: + UINT8 dataX[VAR]; /* Glyphs data. */ DEFINE_SIZE_ARRAY (0, dataX); }; -struct glyfGlyphHeader -{ - SHORT numberOfContours; /* If the number of contours is - * greater than or equal to zero, - * this is a simple glyph; if negative, - * this is a composite glyph. */ - FWORD xMin; /* Minimum x for coordinate data. */ - FWORD yMin; /* Minimum y for coordinate data. */ - FWORD xMax; /* Maximum x for coordinate data. */ - FWORD yMax; /* Maximum y for coordinate data. */ - - DEFINE_SIZE_STATIC (10); -}; - } /* namespace OT */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh index 9c3e51eb08..dd4349ef85 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh @@ -64,11 +64,11 @@ struct head FixedVersion<>version; /* Version of the head table--currently * 0x00010000u for version 1.0. */ FixedVersion<>fontRevision; /* Set by font manufacturer. */ - ULONG checkSumAdjustment; /* To compute: set it to 0, sum the - * entire font as ULONG, then store + UINT32 checkSumAdjustment; /* To compute: set it to 0, sum the + * entire font as UINT32, then store * 0xB1B0AFBAu - sum. */ - ULONG magicNumber; /* Set to 0x5F0F3CF5u. */ - USHORT flags; /* Bit 0: Baseline for font at y=0; + UINT32 magicNumber; /* Set to 0x5F0F3CF5u. */ + UINT16 flags; /* Bit 0: Baseline for font at y=0; * Bit 1: Left sidebearing point at x=0; * Bit 2: Instructions may depend on point size; * Bit 3: Force ppem to integer values for all @@ -114,18 +114,18 @@ struct head * encoded in the cmap subtables represent proper * support for those code points. * Bit 15: Reserved, set to 0. */ - USHORT unitsPerEm; /* Valid range is from 16 to 16384. This value + UINT16 unitsPerEm; /* Valid range is from 16 to 16384. This value * should be a power of 2 for fonts that have * TrueType outlines. */ LONGDATETIME created; /* Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer */ LONGDATETIME modified; /* Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer */ - SHORT xMin; /* For all glyph bounding boxes. */ - SHORT yMin; /* For all glyph bounding boxes. */ - SHORT xMax; /* For all glyph bounding boxes. */ - SHORT yMax; /* For all glyph bounding boxes. */ - USHORT macStyle; /* Bit 0: Bold (if set to 1); + INT16 xMin; /* For all glyph bounding boxes. */ + INT16 yMin; /* For all glyph bounding boxes. */ + INT16 xMax; /* For all glyph bounding boxes. */ + INT16 yMax; /* For all glyph bounding boxes. */ + UINT16 macStyle; /* Bit 0: Bold (if set to 1); * Bit 1: Italic (if set to 1) * Bit 2: Underline (if set to 1) * Bit 3: Outline (if set to 1) @@ -133,16 +133,16 @@ struct head * Bit 5: Condensed (if set to 1) * Bit 6: Extended (if set to 1) * Bits 7-15: Reserved (set to 0). */ - USHORT lowestRecPPEM; /* Smallest readable size in pixels. */ - SHORT fontDirectionHint; /* Deprecated (Set to 2). + UINT16 lowestRecPPEM; /* Smallest readable size in pixels. */ + INT16 fontDirectionHint; /* Deprecated (Set to 2). * 0: Fully mixed directional glyphs; * 1: Only strongly left to right; * 2: Like 1 but also contains neutrals; * -1: Only strongly right to left; * -2: Like -1 but also contains neutrals. */ public: - SHORT indexToLocFormat; /* 0 for short offsets, 1 for long. */ - SHORT glyphDataFormat; /* 0 for current format. */ + INT16 indexToLocFormat; /* 0 for short offsets, 1 for long. */ + INT16 glyphDataFormat; /* 0 for current format. */ DEFINE_SIZE_STATIC (54); }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh index c8e9536cf1..dca014148e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh @@ -44,11 +44,6 @@ namespace OT { struct _hea { - static const hb_tag_t tableTag = HB_TAG('_','h','e','a'); - - static const hb_tag_t hheaTag = HB_OT_TAG_hhea; - static const hb_tag_t vheaTag = HB_OT_TAG_vhea; - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -69,21 +64,21 @@ struct _hea * (xMax - xMin)) for horizontal. */ FWORD maxExtent; /* horizontal: Max(lsb + (xMax - xMin)), * vertical: minLeadingBearing+(yMax-yMin). */ - SHORT caretSlopeRise; /* Used to calculate the slope of the + INT16 caretSlopeRise; /* Used to calculate the slope of the * cursor (rise/run); 1 for vertical caret, * 0 for horizontal.*/ - SHORT caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */ - SHORT caretOffset; /* The amount by which a slanted + INT16 caretSlopeRun; /* 0 for vertical caret, 1 for horizontal. */ + INT16 caretOffset; /* The amount by which a slanted * highlight on a glyph needs * to be shifted to produce the * best appearance. Set to 0 for * non-slanted fonts. */ - SHORT reserved1; /* Set to 0. */ - SHORT reserved2; /* Set to 0. */ - SHORT reserved3; /* Set to 0. */ - SHORT reserved4; /* Set to 0. */ - SHORT metricDataFormat; /* 0 for current format. */ - USHORT numberOfLongMetrics; /* Number of LongMetric entries in metric + INT16 reserved1; /* Set to 0. */ + INT16 reserved2; /* Set to 0. */ + INT16 reserved3; /* Set to 0. */ + INT16 reserved4; /* Set to 0. */ + INT16 metricDataFormat; /* 0 for current format. */ + UINT16 numberOfLongMetrics; /* Number of LongMetric entries in metric * table. */ public: DEFINE_SIZE_STATIC (36); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh index a9606b3d27..e710aee42e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh @@ -28,6 +28,9 @@ #define HB_OT_HMTX_TABLE_HH #include "hb-open-type-private.hh" +#include "hb-ot-hhea-table.hh" +#include "hb-ot-os2-table.hh" +#include "hb-ot-var-hvar-table.hh" namespace OT { @@ -50,13 +53,9 @@ struct LongMetric DEFINE_SIZE_STATIC (4); }; -struct _mtx +template <typename T> +struct hmtxvmtx { - static const hb_tag_t tableTag = HB_TAG('_','m','t','x'); - - static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; - static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -65,7 +64,107 @@ struct _mtx return_trace (true); } - public: + struct accelerator_t + { + inline void init (hb_face_t *face, + unsigned int default_advance_ = 0) + { + default_advance = default_advance_ ? default_advance_ : face->get_upem (); + + bool got_font_extents = false; + if (T::os2Tag) + { + hb_blob_t *os2_blob = Sanitizer<os2>::sanitize (face->reference_table (T::os2Tag)); + const os2 *os2_table = Sanitizer<os2>::lock_instance (os2_blob); +#define USE_TYPO_METRICS (1u<<7) + if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) + { + ascender = os2_table->sTypoAscender; + descender = os2_table->sTypoDescender; + line_gap = os2_table->sTypoLineGap; + got_font_extents = (ascender | descender) != 0; + } + hb_blob_destroy (os2_blob); + } + + hb_blob_t *_hea_blob = Sanitizer<_hea>::sanitize (face->reference_table (T::headerTag)); + const _hea *_hea_table = Sanitizer<_hea>::lock_instance (_hea_blob); + num_advances = _hea_table->numberOfLongMetrics; + if (!got_font_extents) + { + ascender = _hea_table->ascender; + descender = _hea_table->descender; + line_gap = _hea_table->lineGap; + got_font_extents = (ascender | descender) != 0; + } + hb_blob_destroy (_hea_blob); + + has_font_extents = got_font_extents; + + blob = Sanitizer<hmtxvmtx>::sanitize (face->reference_table (T::tableTag)); + + /* Cap num_metrics() and num_advances() based on table length. */ + unsigned int len = hb_blob_get_length (blob); + if (unlikely (num_advances * 4 > len)) + num_advances = len / 4; + num_metrics = num_advances + (len - 4 * num_advances) / 2; + + /* We MUST set num_metrics to zero if num_advances is zero. + * Our get_advance() depends on that. */ + if (unlikely (!num_advances)) + { + num_metrics = num_advances = 0; + hb_blob_destroy (blob); + blob = hb_blob_get_empty (); + } + table = Sanitizer<hmtxvmtx>::lock_instance (blob); + + var_blob = Sanitizer<HVARVVAR>::sanitize (face->reference_table (T::variationsTag)); + var_table = Sanitizer<HVARVVAR>::lock_instance (var_blob); + } + + inline void fini (void) + { + hb_blob_destroy (blob); + hb_blob_destroy (var_blob); + } + + inline unsigned int get_advance (hb_codepoint_t glyph, + hb_font_t *font) const + { + if (unlikely (glyph >= num_metrics)) + { + /* If num_metrics is zero, it means we don't have the metrics table + * for this direction: return default advance. Otherwise, it means that the + * glyph index is out of bound: return zero. */ + if (num_metrics) + return 0; + else + return default_advance; + } + + return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance + + var_table->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?! + } + + public: + bool has_font_extents; + unsigned short ascender; + unsigned short descender; + unsigned short line_gap; + + private: + unsigned int num_metrics; + unsigned int num_advances; + unsigned int default_advance; + + const hmtxvmtx *table; + hb_blob_t *blob; + const HVARVVAR *var_table; + hb_blob_t *var_blob; + }; + + protected: LongMetric longMetric[VAR]; /* Paired advance width and leading * bearing values for each glyph. The * value numOfHMetrics comes from @@ -91,11 +190,17 @@ struct _mtx DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX); }; -struct hmtx : _mtx { +struct hmtx : hmtxvmtx<hmtx> { static const hb_tag_t tableTag = HB_OT_TAG_hmtx; + static const hb_tag_t headerTag = HB_OT_TAG_hhea; + static const hb_tag_t variationsTag = HB_OT_TAG_HVAR; + static const hb_tag_t os2Tag = HB_OT_TAG_os2; }; -struct vmtx : _mtx { +struct vmtx : hmtxvmtx<vmtx> { static const hb_tag_t tableTag = HB_OT_TAG_vmtx; + static const hb_tag_t headerTag = HB_OT_TAG_vhea; + static const hb_tag_t variationsTag = HB_OT_TAG_VVAR; + static const hb_tag_t os2Tag = HB_TAG_NONE; }; } /* namespace OT */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh new file mode 100644 index 0000000000..e07faca63f --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh @@ -0,0 +1,394 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_OT_KERN_TABLE_HH +#define HB_OT_KERN_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + + +/* + * kern -- Kerning + */ + +#define HB_OT_TAG_kern HB_TAG('k','e','r','n') + +struct hb_glyph_pair_t +{ + hb_codepoint_t left; + hb_codepoint_t right; +}; + +struct KernPair +{ + inline int get_kerning (void) const + { return value; } + + inline int cmp (const hb_glyph_pair_t &o) const + { + int ret = left.cmp (o.left); + if (ret) return ret; + return right.cmp (o.right); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + GlyphID left; + GlyphID right; + FWORD value; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct KernSubTableFormat0 +{ + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { + hb_glyph_pair_t pair = {left, right}; + int i = pairs.bsearch (pair); + if (i == -1) + return 0; + return pairs[i].get_kerning (); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (pairs.sanitize (c)); + } + + protected: + BinSearchArrayOf<KernPair> pairs; /* Array of kerning pairs. */ + public: + DEFINE_SIZE_ARRAY (8, pairs); +}; + +struct KernClassTable +{ + inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (firstGlyph.sanitize (c) && classes.sanitize (c)); + } + + protected: + UINT16 firstGlyph; /* First glyph in class range. */ + ArrayOf<UINT16> classes; /* Glyph classes. */ + public: + DEFINE_SIZE_ARRAY (4, classes); +}; + +struct KernSubTableFormat2 +{ + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + { + unsigned int l = (this+leftClassTable).get_class (left); + unsigned int r = (this+leftClassTable).get_class (left); + unsigned int offset = l * rowWidth + r * sizeof (FWORD); + const FWORD *arr = &(this+array); + if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end)) + return 0; + const FWORD *v = &StructAtOffset<FWORD> (arr, offset); + if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end)) + return 0; + return *v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (rowWidth.sanitize (c) && + leftClassTable.sanitize (c, this) && + rightClassTable.sanitize (c, this) && + array.sanitize (c, this)); + } + + protected: + UINT16 rowWidth; /* The width, in bytes, of a row in the table. */ + OffsetTo<KernClassTable> + leftClassTable; /* Offset from beginning of this subtable to + * left-hand class table. */ + OffsetTo<KernClassTable> + rightClassTable;/* Offset from beginning of this subtable to + * right-hand class table. */ + OffsetTo<FWORD> + array; /* Offset from beginning of this subtable to + * the start of the kerning array. */ + public: + DEFINE_SIZE_MIN (8); +}; + +struct KernSubTable +{ + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const + { + switch (format) { + case 0: return u.format0.get_kerning (left, right); + case 2: return u.format2.get_kerning (left, right, end); + default:return 0; + } + } + + inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const + { + TRACE_SANITIZE (this); + switch (format) { + case 0: return_trace (u.format0.sanitize (c)); + case 2: return_trace (u.format2.sanitize (c)); + default:return_trace (true); + } + } + + protected: + union { + KernSubTableFormat0 format0; + KernSubTableFormat2 format2; + } u; + public: + DEFINE_SIZE_MIN (0); +}; + + +template <typename T> +struct KernSubTableWrapper +{ + /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ + inline const T* thiz (void) const { return static_cast<const T *> (this); } + + inline bool is_horizontal (void) const + { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; } + + inline bool is_override (void) const + { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); } + + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); } + + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + { return is_horizontal () ? get_kerning (left, right, end) : 0; } + + inline unsigned int get_size (void) const { return thiz()->length; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (thiz()) && + thiz()->length >= thiz()->min_size && + c->check_array (thiz(), 1, thiz()->length) && + thiz()->subtable.sanitize (c, thiz()->format)); + } +}; + +template <typename T> +struct KernTable +{ + /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ + inline const T* thiz (void) const { return static_cast<const T *> (this); } + + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const + { + int v = 0; + const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data); + unsigned int count = thiz()->nTables; + for (unsigned int i = 0; i < count; i++) + { + if (st->is_override ()) + v = 0; + v += st->get_h_kerning (left, right, table_length + (const char *) this); + st = &StructAfter<typename T::SubTableWrapper> (*st); + } + return v; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!c->check_struct (thiz()) || + thiz()->version != T::VERSION)) + return_trace (false); + + const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data); + unsigned int count = thiz()->nTables; + for (unsigned int i = 0; i < count; i++) + { + if (unlikely (!st->sanitize (c))) + return_trace (false); + st = &StructAfter<typename T::SubTableWrapper> (*st); + } + + return_trace (true); + } +}; + +struct KernOT : KernTable<KernOT> +{ + friend struct KernTable<KernOT>; + + static const uint16_t VERSION = 0x0000u; + + struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper> + { + friend struct KernSubTableWrapper<SubTableWrapper>; + + enum coverage_flags_t { + COVERAGE_DIRECTION_FLAG = 0x01u, + COVERAGE_MINIMUM_FLAG = 0x02u, + COVERAGE_CROSSSTREAM_FLAG = 0x04u, + COVERAGE_OVERRIDE_FLAG = 0x08u, + + COVERAGE_VARIATION_FLAG = 0x00u, /* Not supported. */ + + COVERAGE_CHECK_FLAGS = 0x07u, + COVERAGE_CHECK_HORIZONTAL = 0x01u + }; + + protected: + UINT16 versionZ; /* Unused. */ + UINT16 length; /* Length of the subtable (including this header). */ + UINT8 format; /* Subtable format. */ + UINT8 coverage; /* Coverage bits. */ + KernSubTable subtable; /* Subtable data. */ + public: + DEFINE_SIZE_MIN (6); + }; + + protected: + UINT16 version; /* Version--0x0000u */ + UINT16 nTables; /* Number of subtables in the kerning table. */ + UINT8 data[VAR]; + public: + DEFINE_SIZE_ARRAY (4, data); +}; + +struct KernAAT : KernTable<KernAAT> +{ + friend struct KernTable<KernAAT>; + + static const uint32_t VERSION = 0x00010000u; + + struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper> + { + friend struct KernSubTableWrapper<SubTableWrapper>; + + enum coverage_flags_t { + COVERAGE_DIRECTION_FLAG = 0x80u, + COVERAGE_CROSSSTREAM_FLAG = 0x40u, + COVERAGE_VARIATION_FLAG = 0x20u, + + COVERAGE_OVERRIDE_FLAG = 0x00u, /* Not supported. */ + + COVERAGE_CHECK_FLAGS = 0xE0u, + COVERAGE_CHECK_HORIZONTAL = 0x00u + }; + + protected: + UINT32 length; /* Length of the subtable (including this header). */ + UINT8 coverage; /* Coverage bits. */ + UINT8 format; /* Subtable format. */ + UINT16 tupleIndex; /* The tuple index (used for variations fonts). + * This value specifies which tuple this subtable covers. */ + KernSubTable subtable; /* Subtable data. */ + public: + DEFINE_SIZE_MIN (8); + }; + + protected: + UINT32 version; /* Version--0x00010000u */ + UINT32 nTables; /* Number of subtables in the kerning table. */ + UINT8 data[VAR]; + public: + DEFINE_SIZE_ARRAY (8, data); +}; + +struct kern +{ + static const hb_tag_t tableTag = HB_OT_TAG_kern; + + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const + { + switch (u.major) { + case 0: return u.ot.get_h_kerning (left, right, table_length); + case 1: return u.aat.get_h_kerning (left, right, table_length); + default:return 0; + } + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.major.sanitize (c)) return_trace (false); + switch (u.major) { + case 0: return_trace (u.ot.sanitize (c)); + case 1: return_trace (u.aat.sanitize (c)); + default:return_trace (true); + } + } + + struct accelerator_t + { + inline void init (hb_face_t *face) + { + blob = Sanitizer<kern>::sanitize (face->reference_table (HB_OT_TAG_kern)); + table = Sanitizer<kern>::lock_instance (blob); + table_length = hb_blob_get_length (blob); + } + inline void fini (void) + { + hb_blob_destroy (blob); + } + + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return table->get_h_kerning (left, right, table_length); } + + private: + hb_blob_t *blob; + const kern *table; + unsigned int table_length; + }; + + protected: + union { + UINT16 major; + KernOT ot; + KernAAT aat; + } u; + public: + DEFINE_SIZE_UNION (2, major); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_KERN_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh index 62ca7a348e..5e699e1967 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh @@ -29,6 +29,8 @@ #ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH #define HB_OT_LAYOUT_COMMON_PRIVATE_HH +#include "hb-private.hh" +#include "hb-debug.hh" #include "hb-ot-layout-private.hh" #include "hb-open-type-private.hh" #include "hb-set-private.hh" @@ -45,12 +47,6 @@ namespace OT { -#define TRACE_DISPATCH(this, format) \ - hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - "format %d", (int) format); - - #define NOT_COVERED ((unsigned int) -1) @@ -159,13 +155,13 @@ struct RangeRecord } template <typename set_t> - inline void add_coverage (set_t *glyphs) const { - glyphs->add_range (start, end); + inline bool add_coverage (set_t *glyphs) const { + return glyphs->add_range (start, end); } GlyphID start; /* First GlyphID in the range */ GlyphID end; /* Last GlyphID in the range */ - USHORT value; /* Value */ + UINT16 value; /* Value */ public: DEFINE_SIZE_STATIC (6); }; @@ -179,7 +175,7 @@ struct IndexArray : ArrayOf<Index> unsigned int *_indexes /* OUT */) const { if (_count) { - const USHORT *arr = this->sub_array (start_offset, _count); + const UINT16 *arr = this->sub_array (start_offset, _count); unsigned int count = *_count; for (unsigned int i = 0; i < count; i++) _indexes[i] = arr[i]; @@ -214,15 +210,15 @@ struct LangSys } inline bool sanitize (hb_sanitize_context_t *c, - const Record<LangSys>::sanitize_closure_t * = NULL) const + const Record<LangSys>::sanitize_closure_t * = nullptr) const { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && featureIndex.sanitize (c)); } - Offset<> lookupOrderZ; /* = Null (reserved for an offset to a + Offset16 lookupOrderZ; /* = Null (reserved for an offset to a * reordering table) */ - USHORT reqFeatureIndex;/* Index of a feature required for this + UINT16 reqFeatureIndex;/* Index of a feature required for this * language system--if no required features * = 0xFFFFu */ IndexArray featureIndex; /* Array of indices into the FeatureList */ @@ -254,7 +250,7 @@ struct Script inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } inline bool sanitize (hb_sanitize_context_t *c, - const Record<Script>::sanitize_closure_t * = NULL) const + const Record<Script>::sanitize_closure_t * = nullptr) const { TRACE_SANITIZE (this); return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this)); @@ -347,12 +343,12 @@ struct FeatureParamsSize return_trace (true); } - USHORT designSize; /* Represents the design size in 720/inch + UINT16 designSize; /* Represents the design size in 720/inch * units (decipoints). The design size entry * must be non-zero. When there is a design * size but no recommended size range, the * rest of the array will consist of zeros. */ - USHORT subfamilyID; /* Has no independent meaning, but serves + UINT16 subfamilyID; /* Has no independent meaning, but serves * as an identifier that associates fonts * in a subfamily. All fonts which share a * Preferred or Font Family name and which @@ -362,7 +358,7 @@ struct FeatureParamsSize * same subfamily value. If this value is * zero, the remaining fields in the array * will be ignored. */ - USHORT subfamilyNameID;/* If the preceding value is non-zero, this + UINT16 subfamilyNameID;/* If the preceding value is non-zero, this * value must be set in the range 256 - 32767 * (inclusive). It records the value of a * field in the name table, which must @@ -376,10 +372,10 @@ struct FeatureParamsSize * subfamily in a menu. Applications will * choose the appropriate version based on * their selection criteria. */ - USHORT rangeStart; /* Large end of the recommended usage range + UINT16 rangeStart; /* Large end of the recommended usage range * (inclusive), stored in 720/inch units * (decipoints). */ - USHORT rangeEnd; /* Small end of the recommended usage range + UINT16 rangeEnd; /* Small end of the recommended usage range (exclusive), stored in 720/inch units * (decipoints). */ public: @@ -397,12 +393,12 @@ struct FeatureParamsStylisticSet return_trace (c->check_struct (this)); } - USHORT version; /* (set to 0): This corresponds to a “minor” + UINT16 version; /* (set to 0): This corresponds to a “minor” * version number. Additional data may be * added to the end of this Feature Parameters * table in the future. */ - USHORT uiNameID; /* The 'name' table name ID that specifies a + UINT16 uiNameID; /* The 'name' table name ID that specifies a * string (or strings, for multiple languages) * for a user-interface label for this * feature. The values of uiLabelNameId and @@ -430,25 +426,25 @@ struct FeatureParamsCharacterVariants characters.sanitize (c)); } - USHORT format; /* Format number is set to 0. */ - USHORT featUILableNameID; /* The ‘name’ table name ID that + UINT16 format; /* Format number is set to 0. */ + UINT16 featUILableNameID; /* The ‘name’ table name ID that * specifies a string (or strings, * for multiple languages) for a * user-interface label for this - * feature. (May be NULL.) */ - USHORT featUITooltipTextNameID;/* The ‘name’ table name ID that + * feature. (May be nullptr.) */ + UINT16 featUITooltipTextNameID;/* The ‘name’ table name ID that * specifies a string (or strings, * for multiple languages) that an * application can use for tooltip * text for this feature. (May be - * NULL.) */ - USHORT sampleTextNameID; /* The ‘name’ table name ID that + * nullptr.) */ + UINT16 sampleTextNameID; /* The ‘name’ table name ID that * specifies sample text that * illustrates the effect of this - * feature. (May be NULL.) */ - USHORT numNamedParameters; /* Number of named parameters. (May + * feature. (May be nullptr.) */ + UINT16 numNamedParameters; /* Number of named parameters. (May * be zero.) */ - USHORT firstParamUILabelNameID;/* The first ‘name’ table name ID + UINT16 firstParamUILabelNameID;/* The first ‘name’ table name ID * used to specify strings for * user-interface labels for the * feature parameters. (Must be zero @@ -507,7 +503,7 @@ struct Feature { return this+featureParams; } inline bool sanitize (hb_sanitize_context_t *c, - const Record<Feature>::sanitize_closure_t *closure = NULL) const + const Record<Feature>::sanitize_closure_t *closure = nullptr) const { TRACE_SANITIZE (this); if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c)))) @@ -566,7 +562,7 @@ struct Feature typedef RecordListOf<Feature> FeatureList; -struct LookupFlag : USHORT +struct LookupFlag : UINT16 { enum Flags { RightToLeft = 0x0001u, @@ -612,7 +608,7 @@ struct Lookup unsigned int flag = lookupFlag; if (unlikely (flag & LookupFlag::UseMarkFilteringSet)) { - const USHORT &markFilteringSet = StructAfter<USHORT> (subTable); + const UINT16 &markFilteringSet = StructAfter<UINT16> (subTable); flag += (markFilteringSet << 16); } return flag; @@ -644,7 +640,7 @@ struct Lookup if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false); if (lookupFlag & LookupFlag::UseMarkFilteringSet) { - USHORT &markFilteringSet = StructAfter<USHORT> (subTable); + UINT16 &markFilteringSet = StructAfter<UINT16> (subTable); markFilteringSet.set (lookup_props >> 16); } return_trace (true); @@ -657,18 +653,18 @@ struct Lookup if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false); if (lookupFlag & LookupFlag::UseMarkFilteringSet) { - const USHORT &markFilteringSet = StructAfter<USHORT> (subTable); + const UINT16 &markFilteringSet = StructAfter<UINT16> (subTable); if (!markFilteringSet.sanitize (c)) return_trace (false); } return_trace (true); } private: - USHORT lookupType; /* Different enumerations for GSUB and GPOS */ - USHORT lookupFlag; /* Lookup qualifiers */ - ArrayOf<Offset<> > + UINT16 lookupType; /* Different enumerations for GSUB and GPOS */ + UINT16 lookupFlag; /* Lookup qualifiers */ + ArrayOf<Offset16> subTable; /* Array of SubTables */ - USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets + UINT16 markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets * structure. This field is only present if bit * UseMarkFilteringSet of lookup flags is set. */ public: @@ -690,7 +686,7 @@ struct CoverageFormat1 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const { int i = glyphArray.bsearch (glyph_id); - ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED); + static_assert ((((unsigned int) -1) == NOT_COVERED), ""); return i; } @@ -719,10 +715,8 @@ struct CoverageFormat1 } template <typename set_t> - inline void add_coverage (set_t *glyphs) const { - unsigned int count = glyphArray.len; - for (unsigned int i = 0; i < count; i++) - glyphs->add (glyphArray[i]); + inline bool add_coverage (set_t *glyphs) const { + return glyphs->add_sorted_array (glyphArray.array, glyphArray.len); } public: @@ -741,7 +735,7 @@ struct CoverageFormat1 private: protected: - USHORT coverageFormat; /* Format identifier--format = 1 */ + UINT16 coverageFormat; /* Format identifier--format = 1 */ SortedArrayOf<GlyphID> glyphArray; /* Array of GlyphIDs--in numerical order */ public: @@ -821,10 +815,12 @@ struct CoverageFormat2 } template <typename set_t> - inline void add_coverage (set_t *glyphs) const { + inline bool add_coverage (set_t *glyphs) const { unsigned int count = rangeRecord.len; for (unsigned int i = 0; i < count; i++) - rangeRecord[i].add_coverage (glyphs); + if (unlikely (!rangeRecord[i].add_coverage (glyphs))) + return false; + return true; } public: @@ -864,7 +860,7 @@ struct CoverageFormat2 private: protected: - USHORT coverageFormat; /* Format identifier--format = 2 */ + UINT16 coverageFormat; /* Format identifier--format = 2 */ SortedArrayOf<RangeRecord> rangeRecord; /* Array of glyph ranges--ordered by * Start GlyphID. rangeCount entries @@ -931,17 +927,19 @@ struct Coverage } } + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ template <typename set_t> - inline void add_coverage (set_t *glyphs) const { + inline bool add_coverage (set_t *glyphs) const { switch (u.format) { - case 1: u.format1.add_coverage (glyphs); break; - case 2: u.format2.add_coverage (glyphs); break; - default: break; + case 1: return u.format1.add_coverage (glyphs); + case 2: return u.format2.add_coverage (glyphs); + default:return false; } } struct Iter { - Iter (void) : format (0) {}; + Iter (void) : format (0), u () {}; inline void init (const Coverage &c_) { format = c_.u.format; switch (format) { @@ -982,14 +980,14 @@ struct Coverage private: unsigned int format; union { + CoverageFormat2::Iter format2; /* Put this one first since it's larger; helps shut up compiler. */ CoverageFormat1::Iter format1; - CoverageFormat2::Iter format2; } u; }; protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ CoverageFormat1 format1; CoverageFormat2 format2; } u; @@ -1022,11 +1020,36 @@ struct ClassDefFormat1 } template <typename set_t> - inline void add_class (set_t *glyphs, unsigned int klass) const { + inline bool add_coverage (set_t *glyphs) const { + unsigned int start = 0; unsigned int count = classValue.len; for (unsigned int i = 0; i < count; i++) + { + if (classValue[i]) + continue; + + if (start != i) + if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i))) + return false; + + start = i + 1; + } + if (start != count) + if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count))) + return false; + + return true; + } + + template <typename set_t> + inline bool add_class (set_t *glyphs, unsigned int klass) const { + unsigned int count = classValue.len; + for (unsigned int i = 0; i < count; i++) + { if (classValue[i] == klass) glyphs->add (startGlyph + i); + } + return true; } inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const { @@ -1051,9 +1074,9 @@ struct ClassDefFormat1 } protected: - USHORT classFormat; /* Format identifier--format = 1 */ + UINT16 classFormat; /* Format identifier--format = 1 */ GlyphID startGlyph; /* First GlyphID of the classValueArray */ - ArrayOf<USHORT> + ArrayOf<UINT16> classValue; /* Array of Class Values--one per GlyphID */ public: DEFINE_SIZE_ARRAY (6, classValue); @@ -1079,11 +1102,25 @@ struct ClassDefFormat2 } template <typename set_t> - inline void add_class (set_t *glyphs, unsigned int klass) const { + inline bool add_coverage (set_t *glyphs) const { unsigned int count = rangeRecord.len; for (unsigned int i = 0; i < count; i++) + if (rangeRecord[i].value) + if (unlikely (!rangeRecord[i].add_coverage (glyphs))) + return false; + return true; + } + + template <typename set_t> + inline bool add_class (set_t *glyphs, unsigned int klass) const { + unsigned int count = rangeRecord.len; + for (unsigned int i = 0; i < count; i++) + { if (rangeRecord[i].value == klass) - rangeRecord[i].add_coverage (glyphs); + if (unlikely (!rangeRecord[i].add_coverage (glyphs))) + return false; + } + return true; } inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const { @@ -1111,7 +1148,7 @@ struct ClassDefFormat2 } protected: - USHORT classFormat; /* Format identifier--format = 2 */ + UINT16 classFormat; /* Format identifier--format = 2 */ SortedArrayOf<RangeRecord> rangeRecord; /* Array of glyph ranges--ordered by * Start GlyphID */ @@ -1141,11 +1178,25 @@ struct ClassDef } } - inline void add_class (hb_set_t *glyphs, unsigned int klass) const { + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template <typename set_t> + inline bool add_coverage (set_t *glyphs) const { + switch (u.format) { + case 1: return u.format1.add_coverage (glyphs); + case 2: return u.format2.add_coverage (glyphs); + default:return false; + } + } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template <typename set_t> + inline bool add_class (set_t *glyphs, unsigned int klass) const { switch (u.format) { - case 1: u.format1.add_class (glyphs, klass); return; - case 2: u.format2.add_class (glyphs, klass); return; - default:return; + case 1: return u.format1.add_class (glyphs, klass); + case 2: return u.format2.add_class (glyphs, klass); + default:return false; } } @@ -1159,7 +1210,7 @@ struct ClassDef protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ ClassDefFormat1 format1; ClassDefFormat2 format2; } u; @@ -1244,8 +1295,8 @@ struct VarRegionList } protected: - USHORT axisCount; - USHORT regionCount; + UINT16 axisCount; + UINT16 regionCount; VarRegionAxis axesZ[VAR]; public: DEFINE_SIZE_ARRAY (4, axesZ); @@ -1269,13 +1320,13 @@ struct VarData unsigned int count = regionIndices.len; unsigned int scount = shortCount; - const BYTE *bytes = &StructAfter<BYTE> (regionIndices); - const BYTE *row = bytes + inner * (scount + count); + const UINT8 *bytes = &StructAfter<UINT8> (regionIndices); + const UINT8 *row = bytes + inner * (scount + count); float delta = 0.; unsigned int i = 0; - const SHORT *scursor = reinterpret_cast<const SHORT *> (row); + const INT16 *scursor = reinterpret_cast<const INT16 *> (row); for (; i < scount; i++) { float scalar = regions.evaluate (regionIndices.array[i], coords, coord_count); @@ -1297,15 +1348,15 @@ struct VarData return_trace (c->check_struct (this) && regionIndices.sanitize(c) && shortCount <= regionIndices.len && - c->check_array (&StructAfter<BYTE> (regionIndices), + c->check_array (&StructAfter<UINT8> (regionIndices), get_row_size (), itemCount)); } protected: - USHORT itemCount; - USHORT shortCount; - ArrayOf<USHORT> regionIndices; - BYTE bytesX[VAR]; + UINT16 itemCount; + UINT16 shortCount; + ArrayOf<UINT16> regionIndices; + UINT8 bytesX[VAR]; public: DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX); }; @@ -1323,6 +1374,14 @@ struct VariationStore this+regions); } + inline float get_delta (unsigned int index, + int *coords, unsigned int coord_count) const + { + unsigned int outer = index >> 16; + unsigned int inner = index & 0xFFFF; + return get_delta (outer, inner, coords, coord_count); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1333,9 +1392,9 @@ struct VariationStore } protected: - USHORT format; - OffsetTo<VarRegionList, ULONG> regions; - OffsetArrayOf<VarData, ULONG> dataSets; + UINT16 format; + LOffsetTo<VarRegionList> regions; + OffsetArrayOf<VarData, UINT32> dataSets; public: DEFINE_SIZE_ARRAY (8, dataSets); }; @@ -1362,8 +1421,8 @@ struct ConditionFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ - USHORT axisIndex; + UINT16 format; /* Format identifier--format = 1 */ + UINT16 axisIndex; F2DOT14 filterRangeMinValue; F2DOT14 filterRangeMaxValue; public: @@ -1392,7 +1451,7 @@ struct Condition protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ ConditionFormat1 format1; } u; public: @@ -1417,7 +1476,7 @@ struct ConditionSet } protected: - OffsetArrayOf<Condition, ULONG> conditions; + OffsetArrayOf<Condition, UINT32> conditions; public: DEFINE_SIZE_ARRAY (2, conditions); }; @@ -1433,8 +1492,8 @@ struct FeatureTableSubstitutionRecord } protected: - USHORT featureIndex; - OffsetTo<Feature, ULONG> feature; + UINT16 featureIndex; + LOffsetTo<Feature> feature; public: DEFINE_SIZE_STATIC (6); }; @@ -1450,7 +1509,7 @@ struct FeatureTableSubstitution if (record.featureIndex == feature_index) return &(this+record.feature); } - return NULL; + return nullptr; } inline bool sanitize (hb_sanitize_context_t *c) const @@ -1481,9 +1540,9 @@ struct FeatureVariationRecord } protected: - OffsetTo<ConditionSet, ULONG> + LOffsetTo<ConditionSet> conditions; - OffsetTo<FeatureTableSubstitution, ULONG> + LOffsetTo<FeatureTableSubstitution> substitutions; public: DEFINE_SIZE_STATIC (8); @@ -1527,7 +1586,7 @@ struct FeatureVariations protected: FixedVersion<> version; /* Version--0x00010000u */ - ArrayOf<FeatureVariationRecord, ULONG> + LArrayOf<FeatureVariationRecord> varRecords; public: DEFINE_SIZE_ARRAY (8, varRecords); @@ -1553,8 +1612,8 @@ struct HintingDevice inline unsigned int get_size (void) const { unsigned int f = deltaFormat; - if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size; - return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f))); + if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * UINT16::static_size; + return UINT16::static_size * (4 + ((endSize - startSize) >> (4 - f))); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -1599,14 +1658,14 @@ struct HintingDevice } protected: - USHORT startSize; /* Smallest size to correct--in ppem */ - USHORT endSize; /* Largest size to correct--in ppem */ - USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3 + UINT16 startSize; /* Smallest size to correct--in ppem */ + UINT16 endSize; /* Largest size to correct--in ppem */ + UINT16 deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3 * 1 Signed 2-bit value, 8 values per uint16 * 2 Signed 4-bit value, 4 values per uint16 * 3 Signed 8-bit value, 2 values per uint16 */ - USHORT deltaValue[VAR]; /* Array of compressed data */ + UINT16 deltaValue[VAR]; /* Array of compressed data */ public: DEFINE_SIZE_ARRAY (6, deltaValue); }; @@ -1637,9 +1696,9 @@ struct VariationDevice } protected: - USHORT outerIndex; - USHORT innerIndex; - USHORT deltaFormat; /* Format identifier for this table: 0x0x8000 */ + UINT16 outerIndex; + UINT16 innerIndex; + UINT16 deltaFormat; /* Format identifier for this table: 0x0x8000 */ public: DEFINE_SIZE_STATIC (6); }; @@ -1647,10 +1706,10 @@ struct VariationDevice struct DeviceHeader { protected: - USHORT reserved1; - USHORT reserved2; + UINT16 reserved1; + UINT16 reserved2; public: - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ public: DEFINE_SIZE_STATIC (6); }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh index b70cbb7a38..eed46dd672 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gdef-table.hh @@ -41,7 +41,7 @@ namespace OT { * Attachment List Table */ -typedef ArrayOf<USHORT> AttachPoint; /* Array of contour point indices--in +typedef ArrayOf<UINT16> AttachPoint; /* Array of contour point indices--in * increasing numerical order */ struct AttachList @@ -62,7 +62,7 @@ struct AttachList const AttachPoint &points = this+attachPoint[index]; if (point_count) { - const USHORT *array = points.sub_array (start_offset, point_count); + const UINT16 *array = points.sub_array (start_offset, point_count); unsigned int count = *point_count; for (unsigned int i = 0; i < count; i++) point_array[i] = array[i]; @@ -109,8 +109,8 @@ struct CaretValueFormat1 } protected: - USHORT caretValueFormat; /* Format identifier--format = 1 */ - SHORT coordinate; /* X or Y value, in design units */ + UINT16 caretValueFormat; /* Format identifier--format = 1 */ + INT16 coordinate; /* X or Y value, in design units */ public: DEFINE_SIZE_STATIC (4); }; @@ -136,8 +136,8 @@ struct CaretValueFormat2 } protected: - USHORT caretValueFormat; /* Format identifier--format = 2 */ - USHORT caretValuePoint; /* Contour point index on glyph */ + UINT16 caretValueFormat; /* Format identifier--format = 2 */ + UINT16 caretValuePoint; /* Contour point index on glyph */ public: DEFINE_SIZE_STATIC (4); }; @@ -160,8 +160,8 @@ struct CaretValueFormat3 } protected: - USHORT caretValueFormat; /* Format identifier--format = 3 */ - SHORT coordinate; /* X or Y value, in design units */ + UINT16 caretValueFormat; /* Format identifier--format = 3 */ + INT16 coordinate; /* X or Y value, in design units */ OffsetTo<Device> deviceTable; /* Offset to Device table for X or Y * value--from beginning of CaretValue @@ -199,7 +199,7 @@ struct CaretValue protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ CaretValueFormat1 format1; CaretValueFormat2 format2; CaretValueFormat3 format3; @@ -294,8 +294,8 @@ struct MarkGlyphSetsFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ - ArrayOf<OffsetTo<Coverage, ULONG> > + UINT16 format; /* Format identifier--format = 1 */ + ArrayOf<LOffsetTo<Coverage> > coverage; /* Array of long offsets to mark set * coverage tables */ public: @@ -324,7 +324,7 @@ struct MarkGlyphSets protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ MarkGlyphSetsFormat1 format1; } u; public: @@ -404,9 +404,9 @@ struct GDEF { unsigned int klass = get_glyph_class (glyph); - ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs); - ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures); - ASSERT_STATIC ((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks); + static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), ""); + static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), ""); + static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), ""); switch (klass) { default: return 0; @@ -443,7 +443,7 @@ struct GDEF * definitions--from beginning of GDEF * header (may be NULL). Introduced * in version 0x00010002. */ - OffsetTo<VariationStore, ULONG> + LOffsetTo<VariationStore> varStore; /* Offset to the table of Item Variation * Store--from beginning of GDEF * header (may be NULL). Introduced diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh index 952fd60fec..b344d793c7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gpos-table.hh @@ -51,11 +51,11 @@ enum attach_type_t { /* Shared Tables: ValueRecord, Anchor Table, and MarkArray */ -typedef USHORT Value; +typedef UINT16 Value; typedef Value ValueRecord[VAR]; -struct ValueFormat : USHORT +struct ValueFormat : UINT16 { enum Flags { xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */ @@ -74,14 +74,14 @@ struct ValueFormat : USHORT /* All fields are options. Only those available advance the value pointer. */ #if 0 - SHORT xPlacement; /* Horizontal adjustment for + INT16 xPlacement; /* Horizontal adjustment for * placement--in design units */ - SHORT yPlacement; /* Vertical adjustment for + INT16 yPlacement; /* Vertical adjustment for * placement--in design units */ - SHORT xAdvance; /* Horizontal adjustment for + INT16 xAdvance; /* Horizontal adjustment for * advance--in design units (only used * for horizontal writing) */ - SHORT yAdvance; /* Vertical adjustment for advance--in + INT16 yAdvance; /* Vertical adjustment for advance--in * design units (only used for vertical * writing) */ Offset xPlaDevice; /* Offset to Device table for @@ -178,8 +178,8 @@ struct ValueFormat : USHORT static inline const OffsetTo<Device>& get_device (const Value* value) { return *CastP<OffsetTo<Device> > (value); } - static inline const SHORT& get_short (const Value* value) - { return *CastP<SHORT> (value); } + static inline const INT16& get_short (const Value* value) + { return *CastP<INT16> (value); } public: @@ -247,9 +247,9 @@ struct AnchorFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ - SHORT xCoordinate; /* Horizontal value--in design units */ - SHORT yCoordinate; /* Vertical value--in design units */ + UINT16 format; /* Format identifier--format = 1 */ + INT16 xCoordinate; /* Horizontal value--in design units */ + INT16 yCoordinate; /* Vertical value--in design units */ public: DEFINE_SIZE_STATIC (6); }; @@ -278,10 +278,10 @@ struct AnchorFormat2 } protected: - USHORT format; /* Format identifier--format = 2 */ - SHORT xCoordinate; /* Horizontal value--in design units */ - SHORT yCoordinate; /* Vertical value--in design units */ - USHORT anchorPoint; /* Index to glyph contour point */ + UINT16 format; /* Format identifier--format = 2 */ + INT16 xCoordinate; /* Horizontal value--in design units */ + INT16 yCoordinate; /* Vertical value--in design units */ + UINT16 anchorPoint; /* Index to glyph contour point */ public: DEFINE_SIZE_STATIC (8); }; @@ -308,9 +308,9 @@ struct AnchorFormat3 } protected: - USHORT format; /* Format identifier--format = 3 */ - SHORT xCoordinate; /* Horizontal value--in design units */ - SHORT yCoordinate; /* Vertical value--in design units */ + UINT16 format; /* Format identifier--format = 3 */ + INT16 xCoordinate; /* Horizontal value--in design units */ + INT16 yCoordinate; /* Vertical value--in design units */ OffsetTo<Device> xDeviceTable; /* Offset to Device table for X * coordinate-- from beginning of @@ -351,7 +351,7 @@ struct Anchor protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ AnchorFormat1 format1; AnchorFormat2 format2; AnchorFormat3 format3; @@ -382,7 +382,7 @@ struct AnchorMatrix return_trace (true); } - USHORT rows; /* Number of rows */ + UINT16 rows; /* Number of rows */ protected: OffsetTo<Anchor> matrixZ[VAR]; /* Matrix of offsets to Anchor tables-- @@ -403,7 +403,7 @@ struct MarkRecord } protected: - USHORT klass; /* Class defined for this mark */ + UINT16 klass; /* Class defined for this mark */ OffsetTo<Anchor> markAnchor; /* Offset to Anchor table--from * beginning of MarkArray table */ @@ -432,6 +432,7 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde hb_position_t mark_x, mark_y, base_x, base_y; + buffer->unsafe_to_break (glyph_pos, buffer->idx); mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y); glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y); @@ -461,7 +462,7 @@ struct SinglePosFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+coverage).add_coverage (c->input); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; } inline const Coverage &get_coverage (void) const @@ -491,7 +492,7 @@ struct SinglePosFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ @@ -509,7 +510,7 @@ struct SinglePosFormat2 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+coverage).add_coverage (c->input); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; } inline const Coverage &get_coverage (void) const @@ -543,13 +544,13 @@ struct SinglePosFormat2 } protected: - USHORT format; /* Format identifier--format = 2 */ + UINT16 format; /* Format identifier--format = 2 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ ValueFormat valueFormat; /* Defines the types of data in the * ValueRecord */ - USHORT valueCount; /* Number of ValueRecords */ + UINT16 valueCount; /* Number of ValueRecords */ ValueRecord values; /* Array of ValueRecords--positioning * values applied to glyphs */ public: @@ -572,7 +573,7 @@ struct SinglePos protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ SinglePosFormat1 format1; SinglePosFormat2 format2; } u; @@ -603,15 +604,10 @@ struct PairSet TRACE_COLLECT_GLYPHS (this); unsigned int len1 = valueFormats[0].get_len (); unsigned int len2 = valueFormats[1].get_len (); - unsigned int record_size = USHORT::static_size * (1 + len1 + len2); + unsigned int record_size = UINT16::static_size * (1 + len1 + len2); const PairValueRecord *record = CastP<PairValueRecord> (arrayZ); - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - { - c->input->add (record->secondGlyph); - record = &StructAtOffset<PairValueRecord> (record, record_size); - } + c->input->add_array (&record->secondGlyph, len, record_size); } inline bool apply (hb_apply_context_t *c, @@ -622,7 +618,7 @@ struct PairSet hb_buffer_t *buffer = c->buffer; unsigned int len1 = valueFormats[0].get_len (); unsigned int len2 = valueFormats[1].get_len (); - unsigned int record_size = USHORT::static_size * (1 + len1 + len2); + unsigned int record_size = UINT16::static_size * (1 + len1 + len2); const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ); unsigned int count = len; @@ -643,6 +639,7 @@ struct PairSet min = mid + 1; else { + buffer->unsafe_to_break (buffer->idx, pos + 1); valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()); valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]); if (len2) @@ -666,7 +663,7 @@ struct PairSet { TRACE_SANITIZE (this); if (!(c->check_struct (this) - && c->check_array (arrayZ, USHORT::static_size * closure->stride, len))) return_trace (false); + && c->check_array (arrayZ, UINT16::static_size * closure->stride, len))) return_trace (false); unsigned int count = len; const PairValueRecord *record = CastP<PairValueRecord> (arrayZ); @@ -675,8 +672,8 @@ struct PairSet } protected: - USHORT len; /* Number of PairValueRecords */ - USHORT arrayZ[VAR]; /* Array of PairValueRecords--ordered + UINT16 len; /* Number of PairValueRecords */ + UINT16 arrayZ[VAR]; /* Array of PairValueRecords--ordered * by GlyphID of the second glyph */ public: DEFINE_SIZE_ARRAY (2, arrayZ); @@ -687,7 +684,7 @@ struct PairPosFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+coverage).add_coverage (c->input); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count = pairSet.len; for (unsigned int i = 0; i < count; i++) (this+pairSet[i]).collect_glyphs (c, valueFormat); @@ -731,7 +728,7 @@ struct PairPosFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ @@ -753,17 +750,8 @@ struct PairPosFormat2 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+coverage).add_coverage (c->input); - - unsigned int count1 = class1Count; - const ClassDef &klass1 = this+classDef1; - for (unsigned int i = 0; i < count1; i++) - klass1.add_class (c->input, i); - - unsigned int count2 = class2Count; - const ClassDef &klass2 = this+classDef2; - for (unsigned int i = 0; i < count2; i++) - klass2.add_class (c->input, i); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; + if (unlikely (!(this+classDef2).add_coverage (c->input))) return; } inline const Coverage &get_coverage (void) const @@ -790,6 +778,7 @@ struct PairPosFormat2 unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint); if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false); + buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1); const Value *v = &values[record_len * (klass1 * class2Count + klass2)]; valueFormat1.apply_value (c, this, v, buffer->cur_pos()); valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]); @@ -820,7 +809,7 @@ struct PairPosFormat2 } protected: - USHORT format; /* Format identifier--format = 2 */ + UINT16 format; /* Format identifier--format = 2 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ @@ -838,9 +827,9 @@ struct PairPosFormat2 classDef2; /* Offset to ClassDef table--from * beginning of PairPos subtable--for * the second glyph of the pair */ - USHORT class1Count; /* Number of classes in ClassDef1 + UINT16 class1Count; /* Number of classes in ClassDef1 * table--includes Class0 */ - USHORT class2Count; /* Number of classes in ClassDef2 + UINT16 class2Count; /* Number of classes in ClassDef2 * table--includes Class0 */ ValueRecord values; /* Matrix of value pairs: * class1-major, class2-minor, @@ -865,7 +854,7 @@ struct PairPos protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ PairPosFormat1 format1; PairPosFormat2 format2; } u; @@ -903,7 +892,7 @@ struct CursivePosFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+coverage).add_coverage (c->input); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; } inline const Coverage &get_coverage (void) const @@ -929,6 +918,7 @@ struct CursivePosFormat1 unsigned int i = buffer->idx; unsigned int j = skippy_iter.idx; + buffer->unsafe_to_break (i, j); hb_position_t entry_x, entry_y, exit_x, exit_y; (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y); (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y); @@ -1018,7 +1008,7 @@ struct CursivePosFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of subtable */ @@ -1044,7 +1034,7 @@ struct CursivePos protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ CursivePosFormat1 format1; } u; }; @@ -1060,8 +1050,8 @@ struct MarkBasePosFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+markCoverage).add_coverage (c->input); - (this+baseCoverage).add_coverage (c->input); + if (unlikely (!(this+markCoverage).add_coverage (c->input))) return; + if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return; } inline const Coverage &get_coverage (void) const @@ -1083,7 +1073,9 @@ struct MarkBasePosFormat1 do { if (!skippy_iter.prev ()) return_trace (false); /* We only want to attach to the first of a MultipleSubst sequence. Reject others. */ - if (0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) break; + if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) || + 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx])) + break; skippy_iter.reject (); } while (1); @@ -1107,14 +1099,14 @@ struct MarkBasePosFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> markCoverage; /* Offset to MarkCoverage table--from * beginning of MarkBasePos subtable */ OffsetTo<Coverage> baseCoverage; /* Offset to BaseCoverage table--from * beginning of MarkBasePos subtable */ - USHORT classCount; /* Number of classes defined for marks */ + UINT16 classCount; /* Number of classes defined for marks */ OffsetTo<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkBasePos subtable */ @@ -1140,7 +1132,7 @@ struct MarkBasePos protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ MarkBasePosFormat1 format1; } u; }; @@ -1161,8 +1153,8 @@ struct MarkLigPosFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+markCoverage).add_coverage (c->input); - (this+ligatureCoverage).add_coverage (c->input); + if (unlikely (!(this+markCoverage).add_coverage (c->input))) return; + if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return; } inline const Coverage &get_coverage (void) const @@ -1224,7 +1216,7 @@ struct MarkLigPosFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> markCoverage; /* Offset to Mark Coverage table--from * beginning of MarkLigPos subtable */ @@ -1232,7 +1224,7 @@ struct MarkLigPosFormat1 ligatureCoverage; /* Offset to Ligature Coverage * table--from beginning of MarkLigPos * subtable */ - USHORT classCount; /* Number of defined mark classes */ + UINT16 classCount; /* Number of defined mark classes */ OffsetTo<MarkArray> markArray; /* Offset to MarkArray table--from * beginning of MarkLigPos subtable */ @@ -1258,7 +1250,7 @@ struct MarkLigPos protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ MarkLigPosFormat1 format1; } u; }; @@ -1274,8 +1266,8 @@ struct MarkMarkPosFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+mark1Coverage).add_coverage (c->input); - (this+mark2Coverage).add_coverage (c->input); + if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return; + if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return; } inline const Coverage &get_coverage (void) const @@ -1338,7 +1330,7 @@ struct MarkMarkPosFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> mark1Coverage; /* Offset to Combining Mark1 Coverage * table--from beginning of MarkMarkPos @@ -1347,7 +1339,7 @@ struct MarkMarkPosFormat1 mark2Coverage; /* Offset to Combining Mark2 Coverage * table--from beginning of MarkMarkPos * subtable */ - USHORT classCount; /* Number of defined mark classes */ + UINT16 classCount; /* Number of defined mark classes */ OffsetTo<MarkArray> mark1Array; /* Offset to Mark1Array table--from * beginning of MarkMarkPos subtable */ @@ -1373,7 +1365,7 @@ struct MarkMarkPos protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ MarkMarkPosFormat1 format1; } u; }; @@ -1432,7 +1424,7 @@ struct PosLookupSubTable protected: union { - USHORT sub_format; + UINT16 sub_format; SinglePos single; PairPos pair; CursivePos cursive; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh index 66fcb3f3af..0b09c4e4a1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsub-table.hh @@ -44,7 +44,7 @@ struct SingleSubstFormat1 for (iter.init (this+coverage); iter.more (); iter.next ()) { /* TODO Switch to range-based API to work around malicious fonts. - * https://github.com/behdad/harfbuzz/issues/363 */ + * https://github.com/harfbuzz/harfbuzz/issues/363 */ hb_codepoint_t glyph_id = iter.get_glyph (); if (c->glyphs->has (glyph_id)) c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); @@ -54,13 +54,13 @@ struct SingleSubstFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; Coverage::Iter iter; for (iter.init (this+coverage); iter.more (); iter.next ()) { /* TODO Switch to range-based API to work around malicious fonts. - * https://github.com/behdad/harfbuzz/issues/363 */ + * https://github.com/harfbuzz/harfbuzz/issues/363 */ hb_codepoint_t glyph_id = iter.get_glyph (); - c->input->add (glyph_id); c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu); } } @@ -110,11 +110,11 @@ struct SingleSubstFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ - SHORT deltaGlyphID; /* Add to original GlyphID to get + INT16 deltaGlyphID; /* Add to original GlyphID to get * substitute GlyphID */ public: DEFINE_SIZE_STATIC (6); @@ -130,7 +130,7 @@ struct SingleSubstFormat2 for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) c->glyphs->add (substitute[iter.get_coverage ()]); } @@ -139,13 +139,13 @@ struct SingleSubstFormat2 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; Coverage::Iter iter; unsigned int count = substitute.len; for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ - c->input->add (iter.get_glyph ()); + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ c->output->add (substitute[iter.get_coverage ()]); } } @@ -195,7 +195,7 @@ struct SingleSubstFormat2 } protected: - USHORT format; /* Format identifier--format = 2 */ + UINT16 format; /* Format identifier--format = 2 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ @@ -249,7 +249,7 @@ struct SingleSubst protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ SingleSubstFormat1 format1; SingleSubstFormat2 format2; } u; @@ -269,9 +269,7 @@ struct Sequence inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - unsigned int count = substitute.len; - for (unsigned int i = 0; i < count; i++) - c->output->add (substitute[i]); + c->output->add_array (substitute.array, substitute.len); } inline bool apply (hb_apply_context_t *c) const @@ -287,7 +285,7 @@ struct Sequence return_trace (true); } /* Spec disallows this, but Uniscribe allows it. - * https://github.com/behdad/harfbuzz/issues/253 */ + * https://github.com/harfbuzz/harfbuzz/issues/253 */ else if (unlikely (count == 0)) { c->buffer->delete_glyph (); @@ -339,7 +337,7 @@ struct MultipleSubstFormat1 for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) (this+sequence[iter.get_coverage ()]).closure (c); } @@ -348,7 +346,7 @@ struct MultipleSubstFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - (this+coverage).add_coverage (c->input); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count = sequence.len; for (unsigned int i = 0; i < count; i++) (this+sequence[i]).collect_glyphs (c); @@ -400,7 +398,7 @@ struct MultipleSubstFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ @@ -442,7 +440,7 @@ struct MultipleSubst protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ MultipleSubstFormat1 format1; } u; }; @@ -461,7 +459,7 @@ struct AlternateSubstFormat1 for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) { const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; unsigned int count = alt_set.len; @@ -474,17 +472,15 @@ struct AlternateSubstFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; Coverage::Iter iter; unsigned int count = alternateSet.len; for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ - c->input->add (iter.get_glyph ()); + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; - unsigned int count = alt_set.len; - for (unsigned int i = 0; i < count; i++) - c->output->add (alt_set[i]); + c->output->add_array (alt_set.array, alt_set.len); } } @@ -552,7 +548,7 @@ struct AlternateSubstFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ @@ -594,7 +590,7 @@ struct AlternateSubst protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ AlternateSubstFormat1 format1; } u; }; @@ -615,9 +611,7 @@ struct Ligature inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - unsigned int count = component.len; - for (unsigned int i = 1; i < count; i++) - c->input->add (component[i]); + c->input->add_array (component.array, component.len ? component.len - 1 : 0); c->output->add (ligGlyph); } @@ -658,7 +652,7 @@ struct Ligature if (likely (!match_input (c, count, &component[1], match_glyph, - NULL, + nullptr, &match_length, match_positions, &is_mark_ligature, @@ -792,7 +786,7 @@ struct LigatureSubstFormat1 for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) (this+ligatureSet[iter.get_coverage ()]).closure (c); } @@ -801,13 +795,13 @@ struct LigatureSubstFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; Coverage::Iter iter; unsigned int count = ligatureSet.len; for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ - c->input->add (iter.get_glyph ()); + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c); } } @@ -868,7 +862,7 @@ struct LigatureSubstFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of Substitution table */ @@ -918,7 +912,7 @@ struct LigatureSubst protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ LigatureSubstFormat1 format1; } u; }; @@ -961,7 +955,7 @@ struct ReverseChainSingleSubstFormat1 for (iter.init (this+coverage); iter.more (); iter.next ()) { if (unlikely (iter.get_coverage () >= count)) - break; /* Work around malicious fonts. https://github.com/behdad/harfbuzz/issues/363 */ + break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */ if (c->glyphs->has (iter.get_glyph ())) c->glyphs->add (substitute[iter.get_coverage ()]); } @@ -970,25 +964,22 @@ struct ReverseChainSingleSubstFormat1 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const { TRACE_COLLECT_GLYPHS (this); - - const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); + if (unlikely (!(this+coverage).add_coverage (c->input))) return; unsigned int count; - (this+coverage).add_coverage (c->input); - count = backtrack.len; for (unsigned int i = 0; i < count; i++) - (this+backtrack[i]).add_coverage (c->before); + if (unlikely (!(this+backtrack[i]).add_coverage (c->before))) return; + const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); count = lookahead.len; for (unsigned int i = 0; i < count; i++) - (this+lookahead[i]).add_coverage (c->after); + if (unlikely (!(this+lookahead[i]).add_coverage (c->after))) return; const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); count = substitute.len; - for (unsigned int i = 0; i < count; i++) - c->output->add (substitute[i]); + c->output->add_array (substitute.array, substitute.len); } inline const Coverage &get_coverage (void) const @@ -1014,14 +1005,17 @@ struct ReverseChainSingleSubstFormat1 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack); const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead); + unsigned int start_index = 0, end_index = 0; if (match_backtrack (c, - backtrack.len, (USHORT *) backtrack.array, - match_coverage, this) && + backtrack.len, (UINT16 *) backtrack.array, + match_coverage, this, + &start_index) && match_lookahead (c, - lookahead.len, (USHORT *) lookahead.array, + lookahead.len, (UINT16 *) lookahead.array, match_coverage, this, - 1)) + 1, &end_index)) { + c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index); c->replace_glyph_inplace (substitute[index]); /* Note: We DON'T decrease buffer->idx. The main loop does it * for us. This is useful for preventing surprises if someone @@ -1045,7 +1039,7 @@ struct ReverseChainSingleSubstFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ @@ -1079,7 +1073,7 @@ struct ReverseChainSingleSubst protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ ReverseChainSingleSubstFormat1 format1; } u; }; @@ -1125,7 +1119,7 @@ struct SubstLookupSubTable protected: union { - USHORT sub_format; + UINT16 sub_format; SingleSubst single; MultipleSubst multiple; AlternateSubst alternate; @@ -1277,9 +1271,11 @@ struct SubstLookup : Lookup if (unlikely (get_type () == SubstLookupSubTable::Extension)) { /* The spec says all subtables of an Extension lookup should - * have the same type. This is specially important if one has - * a reverse type! */ + * have the same type, which shall not be the Extension type + * itself. This is specially important if one has a reverse type! */ unsigned int type = get_subtable (0).u.extension.get_type (); + if (unlikely (type == SubstLookupSubTable::Extension)) + return_trace (false); unsigned int count = get_subtable_count (); for (unsigned int i = 1; i < count; i++) if (get_subtable (i).u.extension.get_type () != type) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh index fd75c5425a..b08a59138e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos-private.hh @@ -29,6 +29,8 @@ #ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH #define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH +#include "hb-private.hh" +#include "hb-debug.hh" #include "hb-buffer-private.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-set-private.hh" @@ -37,15 +39,6 @@ namespace OT { -#ifndef HB_DEBUG_CLOSURE -#define HB_DEBUG_CLOSURE (HB_DEBUG+0) -#endif - -#define TRACE_CLOSURE(this) \ - hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - struct hb_closure_context_t : hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE> { @@ -77,7 +70,7 @@ struct hb_closure_context_t : unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), glyphs (glyphs_), - recurse_func (NULL), + recurse_func (nullptr), nesting_level_left (nesting_level_left_), debug_depth (0) {} @@ -85,16 +78,6 @@ struct hb_closure_context_t : }; - -#ifndef HB_DEBUG_WOULD_APPLY -#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0) -#endif - -#define TRACE_WOULD_APPLY(this) \ - hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - "%d glyphs", c->len); - struct hb_would_apply_context_t : hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY> { @@ -122,16 +105,6 @@ struct hb_would_apply_context_t : }; - -#ifndef HB_DEBUG_COLLECT_GLYPHS -#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0) -#endif - -#define TRACE_COLLECT_GLYPHS(this) \ - hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - struct hb_collect_glyphs_context_t : hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS> { @@ -146,7 +119,7 @@ struct hb_collect_glyphs_context_t : if (unlikely (nesting_level_left == 0 || !recurse_func)) return default_return_value (); - /* Note that GPOS sets recurse_func to NULL already, so it doesn't get + /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get * past the previous check. For GSUB, we only want to collect the output * glyphs in the recursion. If output is not requested, we can go home now. * @@ -160,7 +133,7 @@ struct hb_collect_glyphs_context_t : return HB_VOID; /* Return if new lookup was recursed to before. */ - if (recursed_lookups.has (lookup_index)) + if (recursed_lookups->has (lookup_index)) return HB_VOID; hb_set_t *old_before = before; @@ -176,7 +149,7 @@ struct hb_collect_glyphs_context_t : input = old_input; after = old_after; - recursed_lookups.add (lookup_index); + recursed_lookups->add (lookup_index); return HB_VOID; } @@ -187,31 +160,31 @@ struct hb_collect_glyphs_context_t : hb_set_t *after; hb_set_t *output; recurse_func_t recurse_func; - hb_set_t recursed_lookups; + hb_set_t *recursed_lookups; unsigned int nesting_level_left; unsigned int debug_depth; hb_collect_glyphs_context_t (hb_face_t *face_, - hb_set_t *glyphs_before, /* OUT. May be NULL */ - hb_set_t *glyphs_input, /* OUT. May be NULL */ - hb_set_t *glyphs_after, /* OUT. May be NULL */ - hb_set_t *glyphs_output, /* OUT. May be NULL */ + hb_set_t *glyphs_before, /* OUT. May be nullptr */ + hb_set_t *glyphs_input, /* OUT. May be nullptr */ + hb_set_t *glyphs_after, /* OUT. May be nullptr */ + hb_set_t *glyphs_output, /* OUT. May be nullptr */ unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) : face (face_), before (glyphs_before ? glyphs_before : hb_set_get_empty ()), input (glyphs_input ? glyphs_input : hb_set_get_empty ()), after (glyphs_after ? glyphs_after : hb_set_get_empty ()), output (glyphs_output ? glyphs_output : hb_set_get_empty ()), - recurse_func (NULL), - recursed_lookups (), + recurse_func (nullptr), + recursed_lookups (nullptr), nesting_level_left (nesting_level_left_), debug_depth (0) { - recursed_lookups.init (); + recursed_lookups = hb_set_create (); } ~hb_collect_glyphs_context_t (void) { - recursed_lookups.fini (); + hb_set_destroy (recursed_lookups); } void set_recurse_func (recurse_func_t func) { recurse_func = func; } @@ -219,10 +192,6 @@ struct hb_collect_glyphs_context_t : -#ifndef HB_DEBUG_GET_COVERAGE -#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0) -#endif - /* XXX Can we remove this? */ template <typename set_t> @@ -249,17 +218,6 @@ struct hb_add_coverage_context_t : }; - -#ifndef HB_DEBUG_APPLY -#define HB_DEBUG_APPLY (HB_DEBUG+0) -#endif - -#define TRACE_APPLY(this) \ - hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - "idx %d gid %u lookup %d", \ - c->buffer->idx, c->buffer->cur().codepoint, (int) c->lookup_index); - struct hb_apply_context_t : hb_dispatch_context_t<hb_apply_context_t, bool, HB_DEBUG_APPLY> { @@ -273,10 +231,10 @@ struct hb_apply_context_t : #define arg1(arg) (arg) /* Remove the macro to see why it's needed! */ syllable arg1(0), #undef arg1 - match_func (NULL), - match_data (NULL) {}; + match_func (nullptr), + match_data (nullptr) {}; - typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data); + typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const UINT16 &value, const void *data); inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } @@ -294,7 +252,7 @@ struct hb_apply_context_t : }; inline may_match_t may_match (const hb_glyph_info_t &info, - const USHORT *glyph_data) const + const UINT16 *glyph_data) const { if (!(info.mask & mask) || (syllable && syllable != info.syllable ())) @@ -319,7 +277,7 @@ struct hb_apply_context_t : if (!c->check_glyph_property (&info, lookup_props)) return SKIP_YES; - if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_fvs (&info) && + if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) && (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && (ignore_zwj || !_hb_glyph_info_is_zwj (&info)))) return SKIP_MAYBE; @@ -342,13 +300,13 @@ struct hb_apply_context_t : inline void init (hb_apply_context_t *c_, bool context_match = false) { c = c_; - match_glyph_data = NULL, - matcher.set_match_func (NULL, NULL); + match_glyph_data = nullptr; + matcher.set_match_func (nullptr, nullptr); matcher.set_lookup_props (c->lookup_props); /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */ - matcher.set_ignore_zwnj (context_match || c->table_index == 1); + matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj)); /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */ - matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj); + matcher.set_ignore_zwj (c->table_index == 1 || (context_match || c->auto_zwj)); matcher.set_mask (context_match ? -1 : c->lookup_mask); } inline void set_lookup_props (unsigned int lookup_props) @@ -357,7 +315,7 @@ struct hb_apply_context_t : } inline void set_match_func (matcher_t::match_func_t match_func_, const void *match_data_, - const USHORT glyph_data[]) + const UINT16 glyph_data[]) { matcher.set_match_func (match_func_, match_data_); match_glyph_data = glyph_data; @@ -374,6 +332,13 @@ struct hb_apply_context_t : inline void reject (void) { num_items++; match_glyph_data--; } + inline matcher_t::may_skip_t + may_skip (const hb_apply_context_t *c, + const hb_glyph_info_t &info) const + { + return matcher.may_skip (c, info); + } + inline bool next (void) { assert (num_items > 0); @@ -433,7 +398,7 @@ struct hb_apply_context_t : protected: hb_apply_context_t *c; matcher_t matcher; - const USHORT *match_glyph_data; + const UINT16 *match_glyph_data; unsigned int num_items; unsigned int end; @@ -448,7 +413,7 @@ struct hb_apply_context_t : bool stop_sublookup_iteration (return_t r) const { return r; } return_t recurse (unsigned int lookup_index) { - if (unlikely (nesting_level_left == 0 || !recurse_func)) + if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0)) return default_return_value (); nesting_level_left--; @@ -457,45 +422,50 @@ struct hb_apply_context_t : return ret; } - unsigned int table_index; /* GSUB/GPOS */ + skipping_iterator_t iter_input, iter_context; + hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; - hb_direction_t direction; - hb_mask_t lookup_mask; - bool auto_zwj; recurse_func_t recurse_func; - unsigned int nesting_level_left; - unsigned int lookup_props; const GDEF &gdef; - bool has_glyph_classes; const VariationStore &var_store; - skipping_iterator_t iter_input, iter_context; + + hb_direction_t direction; + hb_mask_t lookup_mask; + unsigned int table_index; /* GSUB/GPOS */ unsigned int lookup_index; + unsigned int lookup_props; + unsigned int nesting_level_left; unsigned int debug_depth; + bool auto_zwnj; + bool auto_zwj; + bool has_glyph_classes; + hb_apply_context_t (unsigned int table_index_, hb_font_t *font_, hb_buffer_t *buffer_) : - table_index (table_index_), + iter_input (), iter_context (), font (font_), face (font->face), buffer (buffer_), - direction (buffer_->props.direction), - lookup_mask (1), - auto_zwj (true), - recurse_func (NULL), - nesting_level_left (HB_MAX_NESTING_LEVEL), - lookup_props (0), + recurse_func (nullptr), gdef (*hb_ot_layout_from_face (face)->gdef), - has_glyph_classes (gdef.has_glyph_classes ()), var_store (gdef.get_var_store ()), - iter_input (), - iter_context (), + direction (buffer_->props.direction), + lookup_mask (1), + table_index (table_index_), lookup_index ((unsigned int) -1), - debug_depth (0) {} + lookup_props (0), + nesting_level_left (HB_MAX_NESTING_LEVEL), + debug_depth (0), + auto_zwnj (true), + auto_zwj (true), + has_glyph_classes (gdef.has_glyph_classes ()) {} inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; } inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; } + inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; } inline void set_recurse_func (recurse_func_t func) { recurse_func = func; } inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; } inline void set_lookup_props (unsigned int lookup_props_) @@ -598,9 +568,9 @@ struct hb_apply_context_t : -typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data); -typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data); -typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data); +typedef bool (*intersects_func_t) (hb_set_t *glyphs, const UINT16 &value, const void *data); +typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const UINT16 &value, const void *data); +typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const UINT16 &value, const void *data); struct ContextClosureFuncs { @@ -616,16 +586,16 @@ struct ContextApplyFuncs }; -static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED) +static inline bool intersects_glyph (hb_set_t *glyphs, const UINT16 &value, const void *data HB_UNUSED) { return glyphs->has (value); } -static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data) +static inline bool intersects_class (hb_set_t *glyphs, const UINT16 &value, const void *data) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); return class_def.intersects_class (glyphs, value); } -static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data) +static inline bool intersects_coverage (hb_set_t *glyphs, const UINT16 &value, const void *data) { const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value; return (data+coverage).intersects (glyphs); @@ -633,7 +603,7 @@ static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, c static inline bool intersects_array (hb_closure_context_t *c, unsigned int count, - const USHORT values[], + const UINT16 values[], intersects_func_t intersects_func, const void *intersects_data) { @@ -644,16 +614,16 @@ static inline bool intersects_array (hb_closure_context_t *c, } -static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED) +static inline void collect_glyph (hb_set_t *glyphs, const UINT16 &value, const void *data HB_UNUSED) { glyphs->add (value); } -static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data) +static inline void collect_class (hb_set_t *glyphs, const UINT16 &value, const void *data) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); class_def.add_class (glyphs, value); } -static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data) +static inline void collect_coverage (hb_set_t *glyphs, const UINT16 &value, const void *data) { const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value; (data+coverage).add_coverage (glyphs); @@ -661,7 +631,7 @@ static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, cons static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED, hb_set_t *glyphs, unsigned int count, - const USHORT values[], + const UINT16 values[], collect_glyphs_func_t collect_func, const void *collect_data) { @@ -670,16 +640,16 @@ static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED, } -static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED) +static inline bool match_glyph (hb_codepoint_t glyph_id, const UINT16 &value, const void *data HB_UNUSED) { return glyph_id == value; } -static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data) +static inline bool match_class (hb_codepoint_t glyph_id, const UINT16 &value, const void *data) { const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); return class_def.get_class (glyph_id) == value; } -static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data) +static inline bool match_coverage (hb_codepoint_t glyph_id, const UINT16 &value, const void *data) { const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value; return (data+coverage).get_coverage (glyph_id) != NOT_COVERED; @@ -687,7 +657,7 @@ static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, static inline bool would_match_input (hb_would_apply_context_t *c, unsigned int count, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data) { @@ -702,15 +672,15 @@ static inline bool would_match_input (hb_would_apply_context_t *c, } static inline bool match_input (hb_apply_context_t *c, unsigned int count, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ match_func_t match_func, const void *match_data, unsigned int *end_offset, unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], - bool *p_is_mark_ligature = NULL, - unsigned int *p_total_component_count = NULL) + bool *p_is_mark_ligature = nullptr, + unsigned int *p_total_component_count = nullptr) { - TRACE_APPLY (NULL); + TRACE_APPLY (nullptr); if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false); @@ -731,11 +701,17 @@ static inline bool match_input (hb_apply_context_t *c, * - Ligatures cannot be formed across glyphs attached to different components * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother. - * However, it would be wrong to ligate that SHADDA,FATHA sequence.o - * There is an exception to this: If a ligature tries ligating with marks that - * belong to it itself, go ahead, assuming that the font designer knows what - * they are doing (otherwise it can break Indic stuff when a matra wants to - * ligate with a conjunct...) + * However, it would be wrong to ligate that SHADDA,FATHA sequence. + * There are a couple of exceptions to this: + * + * o If a ligature tries ligating with marks that belong to it itself, go ahead, + * assuming that the font designer knows what they are doing (otherwise it can + * break Indic stuff when a matra wants to ligate with a conjunct, + * + * o If two marks want to ligate and they belong to different components of the + * same ligature glyph, and said ligature glyph is to be ignored according to + * mark-filtering rules, then allow. + * https://github.com/harfbuzz/harfbuzz/issues/545 */ bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur()); @@ -746,6 +722,12 @@ static inline bool match_input (hb_apply_context_t *c, 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()); + enum { + LIGBASE_NOT_CHECKED, + LIGBASE_MAY_NOT_SKIP, + LIGBASE_MAY_SKIP + } ligbase = LIGBASE_NOT_CHECKED; + match_positions[0] = buffer->idx; for (unsigned int i = 1; i < count; i++) { @@ -756,13 +738,43 @@ static inline bool match_input (hb_apply_context_t *c, unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]); unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]); - if (first_lig_id && first_lig_comp) { + if (first_lig_id && first_lig_comp) + { /* If first component was attached to a previous ligature component, * all subsequent components should be attached to the same ligature - * component, otherwise we shouldn't ligate them. */ + * component, otherwise we shouldn't ligate them... */ if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp) - return_trace (false); - } else { + { + /* ...unless, we are attached to a base ligature and that base + * ligature is ignorable. */ + if (ligbase == LIGBASE_NOT_CHECKED) + { + bool found = false; + const hb_glyph_info_t *out = buffer->out_info; + unsigned int j = buffer->out_len; + while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id) + { + if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0) + { + j--; + found = true; + break; + } + j--; + } + + if (found && skippy_iter.may_skip (c, out[j]) == hb_apply_context_t::matcher_t::SKIP_YES) + ligbase = LIGBASE_MAY_SKIP; + else + ligbase = LIGBASE_MAY_NOT_SKIP; + } + + if (ligbase == LIGBASE_MAY_NOT_SKIP) + return_trace (false); + } + } + else + { /* If first component was NOT attached to a previous ligature component, * all subsequent components should also NOT be attached to any ligature * component, unless they are attached to the first component itself! */ @@ -792,7 +804,7 @@ static inline bool ligate_input (hb_apply_context_t *c, bool is_mark_ligature, unsigned int total_component_count) { - TRACE_APPLY (NULL); + TRACE_APPLY (nullptr); hb_buffer_t *buffer = c->buffer; @@ -884,11 +896,12 @@ static inline bool ligate_input (hb_apply_context_t *c, static inline bool match_backtrack (hb_apply_context_t *c, unsigned int count, - const USHORT backtrack[], + const UINT16 backtrack[], match_func_t match_func, - const void *match_data) + const void *match_data, + unsigned int *match_start) { - TRACE_APPLY (NULL); + TRACE_APPLY (nullptr); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (c->buffer->backtrack_len (), count); @@ -898,17 +911,20 @@ static inline bool match_backtrack (hb_apply_context_t *c, if (!skippy_iter.prev ()) return_trace (false); + *match_start = skippy_iter.idx; + return_trace (true); } static inline bool match_lookahead (hb_apply_context_t *c, unsigned int count, - const USHORT lookahead[], + const UINT16 lookahead[], match_func_t match_func, const void *match_data, - unsigned int offset) + unsigned int offset, + unsigned int *end_index) { - TRACE_APPLY (NULL); + TRACE_APPLY (nullptr); hb_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context; skippy_iter.reset (c->buffer->idx + offset - 1, count); @@ -918,6 +934,8 @@ static inline bool match_lookahead (hb_apply_context_t *c, if (!skippy_iter.next ()) return_trace (false); + *end_index = skippy_iter.idx + 1; + return_trace (true); } @@ -931,9 +949,9 @@ struct LookupRecord return_trace (c->check_struct (this)); } - USHORT sequenceIndex; /* Index into current glyph + UINT16 sequenceIndex; /* Index into current glyph * sequence--first glyph = 0 */ - USHORT lookupListIndex; /* Lookup to apply to that + UINT16 lookupListIndex; /* Lookup to apply to that * position--zero--based */ public: DEFINE_SIZE_STATIC (4); @@ -956,10 +974,10 @@ static inline bool apply_lookup (hb_apply_context_t *c, const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */ unsigned int match_length) { - TRACE_APPLY (NULL); + TRACE_APPLY (nullptr); hb_buffer_t *buffer = c->buffer; - unsigned int end; + int end; /* All positions are distance from beginning of *output* buffer. * Adjust. */ @@ -984,7 +1002,11 @@ static inline bool apply_lookup (hb_apply_context_t *c, if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index) continue; - buffer->move_to (match_positions[idx]); + if (unlikely (!buffer->move_to (match_positions[idx]))) + break; + + if (unlikely (buffer->max_ops <= 0)) + break; unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len (); if (!c->recurse (lookupRecord[i].lookupListIndex)) @@ -996,10 +1018,32 @@ static inline bool apply_lookup (hb_apply_context_t *c, if (!delta) continue; - /* Recursed lookup changed buffer len. Adjust. */ + /* Recursed lookup changed buffer len. Adjust. + * + * TODO: + * + * Right now, if buffer length increased by n, we assume n new glyphs + * were added right after the current position, and if buffer length + * was decreased by n, we assume n match positions after the current + * one where removed. The former (buffer length increased) case is + * fine, but the decrease case can be improved in at least two ways, + * both of which are significant: + * + * - If recursed-to lookup is MultipleSubst and buffer length + * decreased, then it's current match position that was deleted, + * NOT the one after it. + * + * - If buffer length was decreased by n, it does not necessarily + * mean that n match positions where removed, as there might + * have been marks and default-ignorables in the sequence. We + * should instead drop match positions between current-position + * and current-position + n instead. + * + * It should be possible to construct tests for both of these cases. + */ - end = int (end) + delta; - if (end <= match_positions[idx]) + end += delta; + if (end <= int (match_positions[idx])) { /* End might end up being smaller than match_positions[idx] if the recursed * lookup ended up removing many items, more than we have had matched. @@ -1068,7 +1112,7 @@ struct ContextApplyLookupContext static inline void context_closure_lookup (hb_closure_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], ContextClosureLookupContext &lookup_context) @@ -1082,7 +1126,7 @@ static inline void context_closure_lookup (hb_closure_context_t *c, static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], ContextCollectGlyphsLookupContext &lookup_context) @@ -1096,7 +1140,7 @@ static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c static inline bool context_would_apply_lookup (hb_would_apply_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookupCount HB_UNUSED, const LookupRecord lookupRecord[] HB_UNUSED, ContextApplyLookupContext &lookup_context) @@ -1107,7 +1151,7 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c, } static inline bool context_apply_lookup (hb_apply_context_t *c, unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookupCount, const LookupRecord lookupRecord[], ContextApplyLookupContext &lookup_context) @@ -1118,10 +1162,11 @@ static inline bool context_apply_lookup (hb_apply_context_t *c, inputCount, input, lookup_context.funcs.match, lookup_context.match_data, &match_length, match_positions) - && apply_lookup (c, + && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length), + apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, - match_length); + match_length)); } struct Rule @@ -1164,19 +1209,19 @@ struct Rule inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return inputCount.sanitize (c) - && lookupCount.sanitize (c) - && c->check_range (inputZ, - inputZ[0].static_size * inputCount - + lookupRecordX[0].static_size * lookupCount); + return_trace (inputCount.sanitize (c) && + lookupCount.sanitize (c) && + c->check_range (inputZ, + inputZ[0].static_size * inputCount + + lookupRecordX[0].static_size * lookupCount)); } protected: - USHORT inputCount; /* Total number of glyphs in input + UINT16 inputCount; /* Total number of glyphs in input * glyph sequence--includes the first * glyph */ - USHORT lookupCount; /* Number of LookupRecords */ - USHORT inputZ[VAR]; /* Array of match inputs--start with + UINT16 lookupCount; /* Number of LookupRecords */ + UINT16 inputZ[VAR]; /* Array of match inputs--start with * second glyph */ LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in * design order */ @@ -1251,7 +1296,7 @@ struct ContextFormat1 struct ContextClosureLookupContext lookup_context = { {intersects_glyph}, - NULL + nullptr }; unsigned int count = ruleSet.len; @@ -1269,7 +1314,7 @@ struct ContextFormat1 struct ContextCollectGlyphsLookupContext lookup_context = { {collect_glyph}, - NULL + nullptr }; unsigned int count = ruleSet.len; @@ -1284,7 +1329,7 @@ struct ContextFormat1 const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; struct ContextApplyLookupContext lookup_context = { {match_glyph}, - NULL + nullptr }; return_trace (rule_set.would_apply (c, lookup_context)); } @@ -1304,7 +1349,7 @@ struct ContextFormat1 const RuleSet &rule_set = this+ruleSet[index]; struct ContextApplyLookupContext lookup_context = { {match_glyph}, - NULL + nullptr }; return_trace (rule_set.apply (c, lookup_context)); } @@ -1316,7 +1361,7 @@ struct ContextFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ @@ -1409,7 +1454,7 @@ struct ContextFormat2 } protected: - USHORT format; /* Format identifier--format = 2 */ + UINT16 format; /* Format identifier--format = 2 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ @@ -1438,7 +1483,7 @@ struct ContextFormat3 this }; context_closure_lookup (c, - glyphCount, (const USHORT *) (coverageZ + 1), + glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context); } @@ -1455,7 +1500,7 @@ struct ContextFormat3 }; context_collect_glyphs_lookup (c, - glyphCount, (const USHORT *) (coverageZ + 1), + glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context); } @@ -1469,7 +1514,7 @@ struct ContextFormat3 {match_coverage}, this }; - return_trace (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); + return_trace (context_would_apply_lookup (c, glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); } inline const Coverage &get_coverage (void) const @@ -1488,7 +1533,7 @@ struct ContextFormat3 {match_coverage}, this }; - return_trace (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); + return_trace (context_apply_lookup (c, glyphCount, (const UINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context)); } inline bool sanitize (hb_sanitize_context_t *c) const @@ -1505,10 +1550,10 @@ struct ContextFormat3 } protected: - USHORT format; /* Format identifier--format = 3 */ - USHORT glyphCount; /* Number of glyphs in the input glyph + UINT16 format; /* Format identifier--format = 3 */ + UINT16 glyphCount; /* Number of glyphs in the input glyph * sequence */ - USHORT lookupCount; /* Number of LookupRecords */ + UINT16 lookupCount; /* Number of LookupRecords */ OffsetTo<Coverage> coverageZ[VAR]; /* Array of offsets to Coverage * table in glyph sequence order */ @@ -1535,7 +1580,7 @@ struct Context protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ ContextFormat1 format1; ContextFormat2 format2; ContextFormat3 format3; @@ -1565,11 +1610,11 @@ struct ChainContextApplyLookupContext static inline void chain_context_closure_lookup (hb_closure_context_t *c, unsigned int backtrackCount, - const USHORT backtrack[], + const UINT16 backtrack[], unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const USHORT lookahead[], + const UINT16 lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], ChainContextClosureLookupContext &lookup_context) @@ -1589,11 +1634,11 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c, static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c, unsigned int backtrackCount, - const USHORT backtrack[], + const UINT16 backtrack[], unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const USHORT lookahead[], + const UINT16 lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], ChainContextCollectGlyphsLookupContext &lookup_context) @@ -1613,11 +1658,11 @@ static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_contex static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c, unsigned int backtrackCount, - const USHORT backtrack[] HB_UNUSED, + const UINT16 backtrack[] HB_UNUSED, unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const USHORT lookahead[] HB_UNUSED, + const UINT16 lookahead[] HB_UNUSED, unsigned int lookupCount HB_UNUSED, const LookupRecord lookupRecord[] HB_UNUSED, ChainContextApplyLookupContext &lookup_context) @@ -1630,16 +1675,16 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c static inline bool chain_context_apply_lookup (hb_apply_context_t *c, unsigned int backtrackCount, - const USHORT backtrack[], + const UINT16 backtrack[], unsigned int inputCount, /* Including the first glyph (not matched) */ - const USHORT input[], /* Array of input values--start with second glyph */ + const UINT16 input[], /* Array of input values--start with second glyph */ unsigned int lookaheadCount, - const USHORT lookahead[], + const UINT16 lookahead[], unsigned int lookupCount, const LookupRecord lookupRecord[], ChainContextApplyLookupContext &lookup_context) { - unsigned int match_length = 0; + unsigned int start_index = 0, match_length = 0, end_index = 0; unsigned int match_positions[HB_MAX_CONTEXT_LENGTH]; return match_input (c, inputCount, input, @@ -1647,15 +1692,17 @@ static inline bool chain_context_apply_lookup (hb_apply_context_t *c, &match_length, match_positions) && match_backtrack (c, backtrackCount, backtrack, - lookup_context.funcs.match, lookup_context.match_data[0]) + lookup_context.funcs.match, lookup_context.match_data[0], + &start_index) && match_lookahead (c, lookaheadCount, lookahead, lookup_context.funcs.match, lookup_context.match_data[2], - match_length) - && apply_lookup (c, + match_length, &end_index) + && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index), + apply_lookup (c, inputCount, match_positions, lookupCount, lookupRecord, - match_length); + match_length)); } struct ChainRule @@ -1663,8 +1710,8 @@ struct ChainRule inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const { TRACE_CLOSURE (this); - const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); - const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack); + const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); chain_context_closure_lookup (c, backtrack.len, backtrack.array, @@ -1677,8 +1724,8 @@ struct ChainRule inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const { TRACE_COLLECT_GLYPHS (this); - const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); - const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack); + const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); chain_context_collect_glyphs_lookup (c, backtrack.len, backtrack.array, @@ -1691,8 +1738,8 @@ struct ChainRule inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const { TRACE_WOULD_APPLY (this); - const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); - const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack); + const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); return_trace (chain_context_would_apply_lookup (c, backtrack.len, backtrack.array, @@ -1704,8 +1751,8 @@ struct ChainRule inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const { TRACE_APPLY (this); - const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); - const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack); + const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); return_trace (chain_context_apply_lookup (c, backtrack.len, backtrack.array, @@ -1718,23 +1765,23 @@ struct ChainRule { TRACE_SANITIZE (this); if (!backtrack.sanitize (c)) return_trace (false); - const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack); + const HeadlessArrayOf<UINT16> &input = StructAfter<HeadlessArrayOf<UINT16> > (backtrack); if (!input.sanitize (c)) return_trace (false); - const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input); + const ArrayOf<UINT16> &lookahead = StructAfter<ArrayOf<UINT16> > (input); if (!lookahead.sanitize (c)) return_trace (false); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); return_trace (lookup.sanitize (c)); } protected: - ArrayOf<USHORT> + ArrayOf<UINT16> backtrack; /* Array of backtracking values * (to be matched before the input * sequence) */ - HeadlessArrayOf<USHORT> + HeadlessArrayOf<UINT16> inputX; /* Array of input values (start with * second glyph) */ - ArrayOf<USHORT> + ArrayOf<UINT16> lookaheadX; /* Array of lookahead values's (to be * matched after the input sequence) */ ArrayOf<LookupRecord> @@ -1807,7 +1854,7 @@ struct ChainContextFormat1 struct ChainContextClosureLookupContext lookup_context = { {intersects_glyph}, - {NULL, NULL, NULL} + {nullptr, nullptr, nullptr} }; unsigned int count = ruleSet.len; @@ -1825,7 +1872,7 @@ struct ChainContextFormat1 struct ChainContextCollectGlyphsLookupContext lookup_context = { {collect_glyph}, - {NULL, NULL, NULL} + {nullptr, nullptr, nullptr} }; unsigned int count = ruleSet.len; @@ -1840,7 +1887,7 @@ struct ChainContextFormat1 const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])]; struct ChainContextApplyLookupContext lookup_context = { {match_glyph}, - {NULL, NULL, NULL} + {nullptr, nullptr, nullptr} }; return_trace (rule_set.would_apply (c, lookup_context)); } @@ -1859,7 +1906,7 @@ struct ChainContextFormat1 const ChainRuleSet &rule_set = this+ruleSet[index]; struct ChainContextApplyLookupContext lookup_context = { {match_glyph}, - {NULL, NULL, NULL} + {nullptr, nullptr, nullptr} }; return_trace (rule_set.apply (c, lookup_context)); } @@ -1871,7 +1918,7 @@ struct ChainContextFormat1 } protected: - USHORT format; /* Format identifier--format = 1 */ + UINT16 format; /* Format identifier--format = 1 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ @@ -1986,7 +2033,7 @@ struct ChainContextFormat2 } protected: - USHORT format; /* Format identifier--format = 2 */ + UINT16 format; /* Format identifier--format = 2 */ OffsetTo<Coverage> coverage; /* Offset to Coverage table--from * beginning of table */ @@ -2026,9 +2073,9 @@ struct ChainContextFormat3 {this, this, this} }; chain_context_closure_lookup (c, - backtrack.len, (const USHORT *) backtrack.array, - input.len, (const USHORT *) input.array + 1, - lookahead.len, (const USHORT *) lookahead.array, + backtrack.len, (const UINT16 *) backtrack.array, + input.len, (const UINT16 *) input.array + 1, + lookahead.len, (const UINT16 *) lookahead.array, lookup.len, lookup.array, lookup_context); } @@ -2047,9 +2094,9 @@ struct ChainContextFormat3 {this, this, this} }; chain_context_collect_glyphs_lookup (c, - backtrack.len, (const USHORT *) backtrack.array, - input.len, (const USHORT *) input.array + 1, - lookahead.len, (const USHORT *) lookahead.array, + backtrack.len, (const UINT16 *) backtrack.array, + input.len, (const UINT16 *) input.array + 1, + lookahead.len, (const UINT16 *) lookahead.array, lookup.len, lookup.array, lookup_context); } @@ -2066,9 +2113,9 @@ struct ChainContextFormat3 {this, this, this} }; return_trace (chain_context_would_apply_lookup (c, - backtrack.len, (const USHORT *) backtrack.array, - input.len, (const USHORT *) input.array + 1, - lookahead.len, (const USHORT *) lookahead.array, + backtrack.len, (const UINT16 *) backtrack.array, + input.len, (const UINT16 *) input.array + 1, + lookahead.len, (const UINT16 *) lookahead.array, lookup.len, lookup.array, lookup_context)); } @@ -2093,9 +2140,9 @@ struct ChainContextFormat3 {this, this, this} }; return_trace (chain_context_apply_lookup (c, - backtrack.len, (const USHORT *) backtrack.array, - input.len, (const USHORT *) input.array + 1, - lookahead.len, (const USHORT *) lookahead.array, + backtrack.len, (const UINT16 *) backtrack.array, + input.len, (const UINT16 *) input.array + 1, + lookahead.len, (const UINT16 *) lookahead.array, lookup.len, lookup.array, lookup_context)); } @@ -2113,7 +2160,7 @@ struct ChainContextFormat3 } protected: - USHORT format; /* Format identifier--format = 3 */ + UINT16 format; /* Format identifier--format = 3 */ OffsetArrayOf<Coverage> backtrack; /* Array of coverage tables * in backtracking sequence, in glyph @@ -2150,7 +2197,7 @@ struct ChainContext protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ ChainContextFormat1 format1; ChainContextFormat2 format2; ChainContextFormat3 format3; @@ -2187,11 +2234,11 @@ struct ExtensionFormat1 } protected: - USHORT format; /* Format identifier. Set to 1. */ - USHORT extensionLookupType; /* Lookup type of subtable referenced + UINT16 format; /* Format identifier. Set to 1. */ + UINT16 extensionLookupType; /* Lookup type of subtable referenced * by ExtensionOffset (i.e. the * extension subtable). */ - ULONG extensionOffset; /* Offset to the extension subtable, + UINT32 extensionOffset; /* Offset to the extension subtable, * of lookup type subtable. */ public: DEFINE_SIZE_STATIC (8); @@ -2229,7 +2276,7 @@ struct Extension protected: union { - USHORT format; /* Format identifier */ + UINT16 format; /* Format identifier */ ExtensionFormat1<T> format1; } u; }; @@ -2241,9 +2288,6 @@ struct Extension struct GSUBGPOS { - static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB; - static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS; - inline unsigned int get_script_count (void) const { return (this+scriptList).len; } inline const Tag& get_script_tag (unsigned int i) const @@ -2313,7 +2357,7 @@ struct GSUBGPOS featureList; /* FeatureList table */ OffsetTo<LookupList> lookupList; /* LookupList table */ - OffsetTo<FeatureVariations, ULONG> + LOffsetTo<FeatureVariations> featureVars; /* Offset to Feature Variations table--from beginning of table * (may be NULL). Introduced diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh index c3068491be..adbaad64f3 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-jstf-table.hh @@ -124,7 +124,7 @@ struct JstfPriority struct JstfLangSys : OffsetListOf<JstfPriority> { inline bool sanitize (hb_sanitize_context_t *c, - const Record<JstfLangSys>::sanitize_closure_t * = NULL) const + const Record<JstfLangSys>::sanitize_closure_t * = nullptr) const { TRACE_SANITIZE (this); return_trace (OffsetListOf<JstfPriority>::sanitize (c)); @@ -165,7 +165,7 @@ struct JstfScript inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } inline bool sanitize (hb_sanitize_context_t *c, - const Record<JstfScript>::sanitize_closure_t * = NULL) const + const Record<JstfScript>::sanitize_closure_t * = nullptr) const { TRACE_SANITIZE (this); return_trace (extenderGlyphs.sanitize (c, this) && diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh index a4272de631..0f0926f890 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-private.hh @@ -33,7 +33,8 @@ #include "hb-font-private.hh" #include "hb-buffer-private.hh" -#include "hb-set-private.hh" +#include "hb-set-digest-private.hh" +#include "hb-open-type-private.hh" /* Private API corresponding to hb-ot-layout.h: */ @@ -125,6 +126,8 @@ namespace OT { struct GSUB; struct GPOS; struct MATH; + struct fvar; + struct avar; } struct hb_ot_layout_lookup_accelerator_t @@ -153,12 +156,15 @@ struct hb_ot_layout_t hb_blob_t *gdef_blob; hb_blob_t *gsub_blob; hb_blob_t *gpos_blob; - hb_blob_t *math_blob; const struct OT::GDEF *gdef; const struct OT::GSUB *gsub; const struct OT::GPOS *gpos; - const struct OT::MATH *math; + + /* TODO Move the following out of this struct. */ + OT::hb_lazy_table_loader_t<struct OT::MATH> math; + OT::hb_lazy_table_loader_t<struct OT::fvar> fvar; + OT::hb_lazy_table_loader_t<struct OT::avar> avar; unsigned int gsub_lookup_count; unsigned int gpos_lookup_count; @@ -191,8 +197,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout); #define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */ -/* loop over syllables */ - +/* Loop over syllables. Based on foreach_cluster(). */ #define foreach_syllable(buffer, start, end) \ for (unsigned int \ _count = buffer->len, \ @@ -221,7 +226,9 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start) * - General_Category: 5 bits. * - A bit each for: * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). - * * Whether it's one of the three Mongolian Free Variation Selectors. + * * Whether it's one of the three Mongolian Free Variation Selectors, + * CGJ, or other characters that are hidden but should not be ignored + * like most other Default_Ignorable()s do during matching. * * One free bit right now. * * The high-byte has different meanings, switched by the Gen-Cat: @@ -234,7 +241,8 @@ _next_syllable (hb_buffer_t *buffer, unsigned int start) enum hb_unicode_props_flags_t { UPROPS_MASK_GEN_CAT = 0x001Fu, UPROPS_MASK_IGNORABLE = 0x0020u, - UPROPS_MASK_FVS = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3 */ + UPROPS_MASK_HIDDEN = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, + * or TAG characters */ /* If GEN_CAT=FORMAT, top byte masks: */ UPROPS_MASK_Cf_ZWJ = 0x0100u, @@ -258,16 +266,21 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer) buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES; props |= UPROPS_MASK_IGNORABLE; if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ; - if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ; + else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ; /* Mongolian Free Variation Selectors need to be remembered * because although we need to hide them like default-ignorables, * they need to non-ignorable during shaping. This is similar to * what we do for joiners in Indic-like shapers, but since the * FVSes are GC=Mn, we have use a separate bit to remember them. * Fixes: - * https://github.com/behdad/harfbuzz/issues/234 - */ - if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_FVS; + * https://github.com/harfbuzz/harfbuzz/issues/234 */ + else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN; + /* TAG characters need similar treatment. Fixes: + * https://github.com/harfbuzz/harfbuzz/issues/463 */ + else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN; + /* COMBINING GRAPHEME JOINER should not be skipped; at least some times. + * https://github.com/harfbuzz/harfbuzz/issues/554 */ + else if (unlikely (u == 0x034Fu)) props |= UPROPS_MASK_HIDDEN; } else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat))) { @@ -292,7 +305,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer) /* Recategorize emoji skin-tone modifiers as Unicode mark, so they * behave correctly in non-native directionality. They originally * are MODIFIER_SYMBOL. Fixes: - * https://github.com/behdad/harfbuzz/issues/169 + * https://github.com/harfbuzz/harfbuzz/issues/169 */ if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu))) { @@ -337,6 +350,8 @@ _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info) return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0; } +#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info))) + static inline bool _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info) { @@ -367,9 +382,9 @@ _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) !_hb_glyph_info_ligated (info); } static inline hb_bool_t -_hb_glyph_info_is_default_ignorable_and_not_fvs (const hb_glyph_info_t *info) +_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) { - return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_FVS)) + return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN)) == UPROPS_MASK_IGNORABLE) && !_hb_glyph_info_ligated (info); } @@ -617,5 +632,4 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer) #undef lig_props #undef glyph_props - #endif /* HB_OT_LAYOUT_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc index 145ec76389..8845889827 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc @@ -34,22 +34,21 @@ #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" -#include "hb-ot-layout-jstf-table.hh" +#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise. +#include "hb-ot-name-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-map-private.hh" -#include <stdlib.h> -#include <string.h> +const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; -HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) hb_ot_layout_t * _hb_ot_layout_create (hb_face_t *face) { hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)); if (unlikely (!layout)) - return NULL; + return nullptr; layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF)); layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob); @@ -60,9 +59,9 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob); - /* The MATH table is rarely used, so only try and load it in _get_math. */ - layout->math_blob = NULL; - layout->math = NULL; + layout->math.init (face); + layout->fvar.init (face); + layout->avar.init (face); { /* @@ -106,14 +105,28 @@ _hb_ot_layout_create (hb_face_t *face) || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len) /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len) + /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len) + /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len) /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len) /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len) + /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len) + /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */ + || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len) + /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5 tahoma.ttf from Windows 10 AU */ + || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len) + /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2 tahomabd.ttf from Windows 10 AU */ + || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len) /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len) + /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc himalaya.ttf from Windows 7 */ + || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len) /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len) /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ @@ -124,6 +137,14 @@ _hb_ot_layout_create (hb_face_t *face) /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len) + /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */ + || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len) + /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/ + || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len) + /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */ + || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len) + /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */ + || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len) /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len) /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ @@ -132,6 +153,9 @@ _hb_ot_layout_create (hb_face_t *face) || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len) /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len) + /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85 Padauk.ttf + * "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */ + || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len) ) { /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks @@ -156,7 +180,7 @@ _hb_ot_layout_create (hb_face_t *face) (layout->gpos_lookup_count && !layout->gpos_accels))) { _hb_ot_layout_destroy (layout); - return NULL; + return nullptr; } for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) @@ -181,7 +205,10 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gdef_blob); hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); - hb_blob_destroy (layout->math_blob); + + layout->math.fini (); + layout->fvar.fini (); + layout->avar.fini (); free (layout); } @@ -256,7 +283,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, hb_codepoint_t glyph, unsigned int start_offset, unsigned int *caret_count /* IN/OUT */, - int *caret_array /* OUT */) + hb_position_t *caret_array /* OUT */) { return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); } @@ -298,7 +325,7 @@ hb_ot_layout_table_find_script (hb_face_t *face, hb_tag_t script_tag, unsigned int *script_index) { - ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); + static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), ""); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); if (g.find_script_index (script_tag, script_index)) @@ -329,7 +356,7 @@ hb_ot_layout_table_choose_script (hb_face_t *face, unsigned int *script_index, hb_tag_t *chosen_script) { - ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); + static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), ""); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); while (*script_tags) @@ -388,7 +415,7 @@ hb_ot_layout_table_find_feature (hb_face_t *face, hb_tag_t feature_tag, unsigned int *feature_index) { - ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); + static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX), ""); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); unsigned int num_features = g.get_feature_count (); @@ -425,7 +452,7 @@ hb_ot_layout_script_find_language (hb_face_t *face, hb_tag_t language_tag, unsigned int *language_index) { - ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX); + static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX), ""); const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); if (s.find_lang_sys_index (language_tag, language_index)) @@ -451,7 +478,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, script_index, language_index, feature_index, - NULL); + nullptr); } /** @@ -504,7 +531,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face, const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); - ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t)); + static_assert ((sizeof (unsigned int) == sizeof (hb_tag_t)), ""); unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags); if (feature_tags) { @@ -525,7 +552,7 @@ hb_ot_layout_language_find_feature (hb_face_t *face, hb_tag_t feature_tag, unsigned int *feature_index) { - ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); + static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX), ""); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); @@ -574,6 +601,7 @@ unsigned int hb_ot_layout_table_get_lookup_count (hb_face_t *face, hb_tag_t table_tag) { + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0; switch (table_tag) { case HB_OT_TAG_GSUB: @@ -629,7 +657,7 @@ _hb_ot_layout_collect_lookups_features (hb_face_t *face, script_index, language_index, &required_feature_index, - NULL)) + nullptr)) _hb_ot_layout_collect_lookups_lookups (face, table_tag, required_feature_index, @@ -698,7 +726,7 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face, unsigned int count = hb_ot_layout_script_get_language_tags (face, table_tag, script_index, - 0, NULL, NULL); + 0, nullptr, nullptr); for (unsigned int language_index = 0; language_index < count; language_index++) _hb_ot_layout_collect_lookups_features (face, table_tag, @@ -745,7 +773,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face, /* All scripts */ unsigned int count = hb_ot_layout_table_get_script_tags (face, table_tag, - 0, NULL, NULL); + 0, nullptr, nullptr); for (unsigned int script_index = 0; script_index < count; script_index++) _hb_ot_layout_collect_lookups_languages (face, table_tag, @@ -782,10 +810,10 @@ void hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, hb_tag_t table_tag, unsigned int lookup_index, - hb_set_t *glyphs_before, /* OUT. May be NULL */ - hb_set_t *glyphs_input, /* OUT. May be NULL */ - hb_set_t *glyphs_after, /* OUT. May be NULL */ - hb_set_t *glyphs_output /* OUT. May be NULL */) + hb_set_t *glyphs_before, /* OUT. May be nullptr */ + hb_set_t *glyphs_input, /* OUT. May be nullptr */ + hb_set_t *glyphs_after, /* OUT. May be nullptr */ + hb_set_t *glyphs_output /* OUT. May be nullptr */) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return; @@ -836,7 +864,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */) { - ASSERT_STATIC (OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX); + static_assert ((OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX), ""); const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const OT::Feature &f = g.get_feature_variation (feature_index, variations_index); @@ -944,11 +972,11 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) **/ hb_bool_t hb_ot_layout_get_size_params (hb_face_t *face, - unsigned int *design_size, /* OUT. May be NULL */ - unsigned int *subfamily_id, /* OUT. May be NULL */ - unsigned int *subfamily_name_id, /* OUT. May be NULL */ - unsigned int *range_start, /* OUT. May be NULL */ - unsigned int *range_end /* OUT. May be NULL */) + unsigned int *design_size, /* OUT. May be nullptr */ + unsigned int *subfamily_id, /* OUT. May be nullptr */ + unsigned int *subfamily_name_id, /* OUT. May be nullptr */ + unsigned int *range_start, /* OUT. May be nullptr */ + unsigned int *range_end /* OUT. May be nullptr */) { const OT::GPOS &gpos = _get_gpos (face); const hb_tag_t tag = HB_TAG ('s','i','z','e'); @@ -1196,6 +1224,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, c.set_lookup_index (lookup_index); c.set_lookup_mask (lookups[table_index][i].mask); c.set_auto_zwj (lookups[table_index][i].auto_zwj); + c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); apply_string<Proxy> (&c, proxy.table.get_lookup (lookup_index), proxy.accels[lookup_index]); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh index 0395c9c22f..97b92cc9a8 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map-private.hh @@ -50,19 +50,25 @@ struct hb_ot_map_t hb_mask_t mask; hb_mask_t _1_mask; /* mask for value=1, for quick access */ unsigned int needs_fallback : 1; + unsigned int auto_zwnj : 1; unsigned int auto_zwj : 1; - static int cmp (const feature_map_t *a, const feature_map_t *b) - { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; } + inline int cmp (const hb_tag_t *tag_) const + { return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; } }; struct lookup_map_t { unsigned short index; + unsigned short auto_zwnj : 1; unsigned short auto_zwj : 1; hb_mask_t mask; - static int cmp (const lookup_map_t *a, const lookup_map_t *b) - { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; } + static int cmp (const void *pa, const void *pb) + { + const lookup_map_t *a = (const lookup_map_t *) pa; + const lookup_map_t *b = (const lookup_map_t *) pb; + return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; + } }; typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); @@ -77,7 +83,7 @@ struct hb_ot_map_t inline hb_mask_t get_global_mask (void) const { return global_mask; } - inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = NULL) const { + inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const { const feature_map_t *map = features.bsearch (&feature_tag); if (shift) *shift = map ? map->shift : 0; return map ? map->mask : 0; @@ -106,14 +112,14 @@ struct hb_ot_map_t inline void get_stage_lookups (unsigned int table_index, unsigned int stage, const struct lookup_map_t **plookups, unsigned int *lookup_count) const { if (unlikely (stage == (unsigned int) -1)) { - *plookups = NULL; + *plookups = nullptr; *lookup_count = 0; return; } assert (stage <= stages[table_index].len); unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0; unsigned int end = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len; - *plookups = &lookups[table_index][start]; + *plookups = end == start ? nullptr : &lookups[table_index][start]; *lookup_count = end - start; } @@ -150,8 +156,9 @@ enum hb_ot_map_feature_flags_t { F_NONE = 0x0000u, F_GLOBAL = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */ F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */ - F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */ - F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */ + F_MANUAL_ZWNJ = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */ + F_MANUAL_ZWJ = 0x0008u, /* Don't skip over ZWJ when matching **input**. */ + F_GLOBAL_SEARCH = 0x0010u /* If feature not found in LangSys, look for it in global feature list and pick one. */ }; HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t); /* Macro version for where const is desired. */ @@ -196,7 +203,8 @@ struct hb_ot_map_builder_t unsigned int feature_index, unsigned int variations_index, hb_mask_t mask, - bool auto_zwj); + bool auto_zwnj = true, + bool auto_zwj = true); struct feature_info_t { hb_tag_t tag; @@ -206,9 +214,13 @@ struct hb_ot_map_builder_t unsigned int default_value; /* for non-global features, what should the unset glyphs take */ unsigned int stage[2]; /* GSUB/GPOS */ - static int cmp (const feature_info_t *a, const feature_info_t *b) - { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : - (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); } + static int cmp (const void *pa, const void *pb) + { + const feature_info_t *a = (const feature_info_t *) pa; + const feature_info_t *b = (const feature_info_t *) pb; + return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : + (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); + } }; struct stage_info_t { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc index 9b331d5210..ea9bde9a66 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-map.cc @@ -85,6 +85,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, unsigned int feature_index, unsigned int variations_index, hb_mask_t mask, + bool auto_zwnj, bool auto_zwj) { unsigned int lookup_indices[32]; @@ -112,6 +113,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, return; lookup->mask = mask; lookup->index = lookup_indices[i]; + lookup->auto_zwnj = auto_zwnj; lookup->auto_zwj = auto_zwj; } @@ -136,7 +138,11 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, const int *coords, unsigned int num_coords) { - m.global_mask = 1; + static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), ""); + unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1; + unsigned int global_bit_shift = _hb_popcount32 (HB_GLYPH_FLAG_DEFINED); + + m.global_mask = global_bit_mask; unsigned int required_feature_index[2]; hb_tag_t required_feature_tag[2]; @@ -188,7 +194,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, /* Allocate bits now */ - unsigned int next_bit = 1; + unsigned int next_bit = global_bit_shift + 1; + for (unsigned int i = 0; i < feature_infos.len; i++) { const feature_info_t *info = &feature_infos[i]; @@ -243,11 +250,12 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, map->index[1] = feature_index[1]; map->stage[0] = info->stage[0]; map->stage[1] = info->stage[1]; + map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ); map->auto_zwj = !(info->flags & F_MANUAL_ZWJ); if ((info->flags & F_GLOBAL) && info->max_value == 1) { /* Uses the global bit */ - map->shift = 0; - map->mask = 1; + map->shift = global_bit_shift; + map->mask = global_bit_mask; } else { map->shift = next_bit; map->mask = (1u << (next_bit + bits_needed)) - (1u << next_bit); @@ -261,8 +269,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, feature_infos.shrink (0); /* Done with these */ - add_gsub_pause (NULL); - add_gpos_pause (NULL); + add_gsub_pause (nullptr); + add_gpos_pause (nullptr); for (unsigned int table_index = 0; table_index < 2; table_index++) { @@ -284,8 +292,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, add_lookups (m, face, table_index, required_feature_index[table_index], variations_index, - 1 /* mask */, - true /* auto_zwj */); + global_bit_mask); for (unsigned i = 0; i < m.features.len; i++) if (m.features[i].stage[table_index] == stage) @@ -293,6 +300,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, m.features[i].index[table_index], variations_index, m.features[i].mask, + m.features[i].auto_zwnj, m.features[i].auto_zwj); /* Sort lookups and merge duplicates */ @@ -307,6 +315,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, else { m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; + m.lookups[table_index][j].auto_zwnj &= m.lookups[table_index][i].auto_zwnj; m.lookups[table_index][j].auto_zwj &= m.lookups[table_index][i].auto_zwj; } m.lookups[table_index].shrink (j + 1); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh new file mode 100644 index 0000000000..7dc3283a28 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math-table.hh @@ -0,0 +1,722 @@ +/* + * Copyright © 2016 Igalia S.L. + * + * 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. + * + * Igalia Author(s): Frédéric Wang + */ + +#ifndef HB_OT_MATH_TABLE_HH +#define HB_OT_MATH_TABLE_HH + +#include "hb-open-type-private.hh" +#include "hb-ot-layout-common-private.hh" +#include "hb-ot-math.h" + +namespace OT { + + +struct MathValueRecord +{ + inline hb_position_t get_x_value (hb_font_t *font, const void *base) const + { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); } + inline hb_position_t get_y_value (hb_font_t *font, const void *base) const + { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); } + + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && deviceTable.sanitize (c, base)); + } + + protected: + INT16 value; /* The X or Y value in design units */ + OffsetTo<Device> deviceTable; /* Offset to the device table - from the + * beginning of parent table. May be nullptr. + * Suggested format for device table is 1. */ + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct MathConstants +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + + unsigned int count = ARRAY_LENGTH (mathValueRecords); + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) + return_trace (false); + + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && sanitize_math_value_records(c)); + } + + inline hb_position_t get_value (hb_ot_math_constant_t constant, + hb_font_t *font) const + { + switch (constant) { + + case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: + case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: + return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN]; + + case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: + case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: + return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]); + + case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: + case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: + case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value(font, this); + + case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_AXIS_HEIGHT: + case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: + case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: + case HB_OT_MATH_CONSTANT_MATH_LEADING: + case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: + case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_GAP_MIN: + case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: + case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: + case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: + case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: + case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: + case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: + case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: + case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: + case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: + return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value(font, this); + + case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: + return radicalDegreeBottomRaisePercent; + + default: + return 0; + } + } + + protected: + INT16 percentScaleDown[2]; + UINT16 minHeight[2]; + MathValueRecord mathValueRecords[51]; + INT16 radicalDegreeBottomRaisePercent; + + public: + DEFINE_SIZE_STATIC (214); +}; + +struct MathItalicsCorrectionInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + coverage.sanitize (c, this) && + italicsCorrection.sanitize (c, this)); + } + + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const + { + unsigned int index = (this+coverage).get_coverage (glyph); + return italicsCorrection[index].get_x_value (font, this); + } + + protected: + OffsetTo<Coverage> coverage; /* Offset to Coverage table - + * from the beginning of + * MathItalicsCorrectionInfo + * table. */ + ArrayOf<MathValueRecord> italicsCorrection; /* Array of MathValueRecords + * defining italics correction + * values for each + * covered glyph. */ + + public: + DEFINE_SIZE_ARRAY (4, italicsCorrection); +}; + +struct MathTopAccentAttachment +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + topAccentCoverage.sanitize (c, this) && + topAccentAttachment.sanitize (c, this)); + } + + inline hb_position_t get_value (hb_codepoint_t glyph, + hb_font_t *font) const + { + unsigned int index = (this+topAccentCoverage).get_coverage (glyph); + if (index == NOT_COVERED) + return font->get_glyph_h_advance (glyph) / 2; + return topAccentAttachment[index].get_x_value(font, this); + } + + protected: + OffsetTo<Coverage> topAccentCoverage; /* Offset to Coverage table - + * from the beginning of + * MathTopAccentAttachment + * table. */ + ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords + * defining top accent + * attachment points for each + * covered glyph. */ + + public: + DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment); +}; + +struct MathKern +{ + inline bool sanitize_math_value_records (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = 2 * heightCount + 1; + for (unsigned int i = 0; i < count; i++) + if (!mathValueRecords[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (mathValueRecords, + mathValueRecords[0].static_size, + 2 * heightCount + 1) && + sanitize_math_value_records (c)); + } + + inline hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const + { + const MathValueRecord* correctionHeight = mathValueRecords; + const MathValueRecord* kernValue = mathValueRecords + heightCount; + int sign = font->y_scale < 0 ? -1 : +1; + + /* The description of the MathKern table is a ambiguous, but interpreting + * "between the two heights found at those indexes" for 0 < i < len as + * + * correctionHeight[i-1] < correction_height <= correctionHeight[i] + * + * makes the result consistent with the limit cases and we can just use the + * binary search algorithm of std::upper_bound: + */ + unsigned int i = 0; + unsigned int count = heightCount; + while (count > 0) + { + unsigned int half = count / 2; + hb_position_t height = correctionHeight[i + half].get_y_value(font, this); + if (sign * height < sign * correction_height) + { + i += half + 1; + count -= half + 1; + } else + count = half; + } + return kernValue[i].get_x_value(font, this); + } + + protected: + UINT16 heightCount; + MathValueRecord mathValueRecords[VAR]; /* Array of correction heights at + * which the kern value changes. + * Sorted by the height value in + * design units (heightCount entries), + * Followed by: + * Array of kern values corresponding + * to heights. (heightCount+1 entries). + */ + + public: + DEFINE_SIZE_ARRAY (2, mathValueRecords); +}; + +struct MathKernInfoRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + + unsigned int count = ARRAY_LENGTH (mathKern); + for (unsigned int i = 0; i < count; i++) + if (unlikely (!mathKern[i].sanitize (c, base))) + return_trace (false); + + return_trace (true); + } + + inline hb_position_t get_kerning (hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font, + const void *base) const + { + unsigned int idx = kern; + if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0; + return (base+mathKern[idx]).get_value (correction_height, font); + } + + protected: + /* Offset to MathKern table for each corner - + * from the beginning of MathKernInfo table. May be nullptr. */ + OffsetTo<MathKern> mathKern[4]; + + public: + DEFINE_SIZE_STATIC (8); +}; + +struct MathKernInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathKernCoverage.sanitize (c, this) && + mathKernInfoRecords.sanitize (c, this)); + } + + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const + { + unsigned int index = (this+mathKernCoverage).get_coverage (glyph); + return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this); + } + + protected: + OffsetTo<Coverage> mathKernCoverage; /* Offset to Coverage table - + * from the beginning of the + * MathKernInfo table. */ + ArrayOf<MathKernInfoRecord> mathKernInfoRecords; /* Array of + * MathKernInfoRecords, + * per-glyph information for + * mathematical positioning + * of subscripts and + * superscripts. */ + + public: + DEFINE_SIZE_ARRAY (4, mathKernInfoRecords); +}; + +struct MathGlyphInfo +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + mathItalicsCorrectionInfo.sanitize (c, this) && + mathTopAccentAttachment.sanitize (c, this) && + extendedShapeCoverage.sanitize (c, this) && + mathKernInfo.sanitize(c, this)); + } + + inline hb_position_t + get_italics_correction (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); } + + inline hb_position_t + get_top_accent_attachment (hb_codepoint_t glyph, hb_font_t *font) const + { return (this+mathTopAccentAttachment).get_value (glyph, font); } + + inline bool is_extended_shape (hb_codepoint_t glyph) const + { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; } + + inline hb_position_t get_kerning (hb_codepoint_t glyph, + hb_ot_math_kern_t kern, + hb_position_t correction_height, + hb_font_t *font) const + { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); } + + protected: + /* Offset to MathItalicsCorrectionInfo table - + * from the beginning of MathGlyphInfo table. */ + OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo; + + /* Offset to MathTopAccentAttachment table - + * from the beginning of MathGlyphInfo table. */ + OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment; + + /* Offset to coverage table for Extended Shape glyphs - + * from the beginning of MathGlyphInfo table. When the left or right glyph of + * a box is an extended shape variant, the (ink) box (and not the default + * position defined by values in MathConstants table) should be used for + * vertical positioning purposes. May be nullptr.. */ + OffsetTo<Coverage> extendedShapeCoverage; + + /* Offset to MathKernInfo table - + * from the beginning of MathGlyphInfo table. */ + OffsetTo<MathKernInfo> mathKernInfo; + + public: + DEFINE_SIZE_STATIC (8); +}; + +struct MathGlyphVariantRecord +{ + friend struct MathGlyphConstruction; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + GlyphID variantGlyph; /* Glyph ID for the variant. */ + UINT16 advanceMeasurement; /* Advance width/height, in design units, of the + * variant, in the direction of requested + * glyph extension. */ + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct PartFlags : UINT16 +{ + enum Flags { + Extender = 0x0001u, /* If set, the part can be skipped or repeated. */ + + Defined = 0x0001u, /* All defined flags. */ + }; + + public: + DEFINE_SIZE_STATIC (2); +}; + +struct MathGlyphPartRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + inline void extract (hb_ot_math_glyph_part_t &out, + int scale, + hb_font_t *font) const + { + out.glyph = glyph; + + out.start_connector_length = font->em_scale (startConnectorLength, scale); + out.end_connector_length = font->em_scale (endConnectorLength, scale); + out.full_advance = font->em_scale (fullAdvance, scale); + + static_assert ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER == + (unsigned int) PartFlags::Extender, ""); + + out.flags = (hb_ot_math_glyph_part_flags_t) + (unsigned int) + (partFlags & PartFlags::Defined); + } + + protected: + GlyphID glyph; /* Glyph ID for the part. */ + UINT16 startConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the beginning of the glyph, in the + * direction of the extension. */ + UINT16 endConnectorLength; /* Advance width/ height of the straight bar + * connector material, in design units, is at + * the end of the glyph, in the direction of + * the extension. */ + UINT16 fullAdvance; /* Full advance width/height for this part, + * in the direction of the extension. + * In design units. */ + PartFlags partFlags; /* Part qualifiers. */ + + public: + DEFINE_SIZE_STATIC (10); +}; + +struct MathGlyphAssembly +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + italicsCorrection.sanitize(c, this) && + partRecords.sanitize(c)); + } + + inline unsigned int get_parts (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_ot_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { + if (parts_count) + { + int scale = font->dir_scale (direction); + const MathGlyphPartRecord *arr = + partRecords.sub_array (start_offset, parts_count); + unsigned int count = *parts_count; + for (unsigned int i = 0; i < count; i++) + arr[i].extract (parts[i], scale, font); + } + + if (italics_correction) + *italics_correction = italicsCorrection.get_x_value (font, this); + + return partRecords.len; + } + + protected: + MathValueRecord italicsCorrection; /* Italics correction of this + * MathGlyphAssembly. Should not + * depend on the assembly size. */ + ArrayOf<MathGlyphPartRecord> partRecords; /* Array of part records, from + * left to right and bottom to + * top. */ + + public: + DEFINE_SIZE_ARRAY (6, partRecords); +}; + +struct MathGlyphConstruction +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + glyphAssembly.sanitize(c, this) && + mathGlyphVariantRecord.sanitize(c)); + } + + inline const MathGlyphAssembly &get_assembly (void) const + { return this+glyphAssembly; } + + inline unsigned int get_variants (hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_ot_math_glyph_variant_t *variants /* OUT */) const + { + if (variants_count) + { + int scale = font->dir_scale (direction); + const MathGlyphVariantRecord *arr = + mathGlyphVariantRecord.sub_array (start_offset, variants_count); + unsigned int count = *variants_count; + for (unsigned int i = 0; i < count; i++) + { + variants[i].glyph = arr[i].variantGlyph; + variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale); + } + } + return mathGlyphVariantRecord.len; + } + + protected: + /* Offset to MathGlyphAssembly table for this shape - from the beginning of + MathGlyphConstruction table. May be nullptr. */ + OffsetTo<MathGlyphAssembly> glyphAssembly; + + /* MathGlyphVariantRecords for alternative variants of the glyphs. */ + ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord; + + public: + DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord); +}; + +struct MathVariants +{ + inline bool sanitize_offsets (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + unsigned int count = vertGlyphCount + horizGlyphCount; + for (unsigned int i = 0; i < count; i++) + if (!glyphConstruction[i].sanitize (c, this)) return_trace (false); + return_trace (true); + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + vertGlyphCoverage.sanitize (c, this) && + horizGlyphCoverage.sanitize (c, this) && + c->check_array (glyphConstruction, + glyphConstruction[0].static_size, + vertGlyphCount + horizGlyphCount) && + sanitize_offsets (c)); + } + + inline hb_position_t get_min_connector_overlap (hb_direction_t direction, + hb_font_t *font) const + { return font->em_scale_dir (minConnectorOverlap, direction); } + + inline unsigned int get_glyph_variants (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *variants_count, /* IN/OUT */ + hb_ot_math_glyph_variant_t *variants /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_variants (direction, font, start_offset, variants_count, variants); } + + inline unsigned int get_glyph_parts (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font, + unsigned int start_offset, + unsigned int *parts_count, /* IN/OUT */ + hb_ot_math_glyph_part_t *parts /* OUT */, + hb_position_t *italics_correction /* OUT */) const + { return get_glyph_construction (glyph, direction, font) + .get_assembly () + .get_parts (direction, font, + start_offset, parts_count, parts, + italics_correction); } + + private: + inline const MathGlyphConstruction & + get_glyph_construction (hb_codepoint_t glyph, + hb_direction_t direction, + hb_font_t *font) const + { + bool vertical = HB_DIRECTION_IS_VERTICAL (direction); + unsigned int count = vertical ? vertGlyphCount : horizGlyphCount; + const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage + : horizGlyphCoverage; + + unsigned int index = (this+coverage).get_coverage (glyph); + if (unlikely (index >= count)) return Null(MathGlyphConstruction); + + if (!vertical) + index += vertGlyphCount; + + return this+glyphConstruction[index]; + } + + protected: + UINT16 minConnectorOverlap; /* Minimum overlap of connecting + * glyphs during glyph construction, + * in design units. */ + OffsetTo<Coverage> vertGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + OffsetTo<Coverage> horizGlyphCoverage; /* Offset to Coverage table - + * from the beginning of MathVariants + * table. */ + UINT16 vertGlyphCount; /* Number of glyphs for which + * information is provided for + * vertically growing variants. */ + UINT16 horizGlyphCount; /* Number of glyphs for which + * information is provided for + * horizontally growing variants. */ + + /* Array of offsets to MathGlyphConstruction tables - from the beginning of + the MathVariants table, for shapes growing in vertical/horizontal + direction. */ + OffsetTo<MathGlyphConstruction> glyphConstruction[VAR]; + + public: + DEFINE_SIZE_ARRAY (10, glyphConstruction); +}; + + +/* + * MATH -- The MATH Table + */ + +struct MATH +{ + static const hb_tag_t tableTag = HB_OT_TAG_MATH; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + mathConstants.sanitize (c, this) && + mathGlyphInfo.sanitize (c, this) && + mathVariants.sanitize (c, this)); + } + + inline hb_position_t get_constant (hb_ot_math_constant_t constant, + hb_font_t *font) const + { return (this+mathConstants).get_value (constant, font); } + + inline const MathGlyphInfo &get_math_glyph_info (void) const + { return this+mathGlyphInfo; } + + inline const MathVariants &get_math_variants (void) const + { return this+mathVariants; } + + protected: + FixedVersion<>version; /* Version of the MATH table + * initially set to 0x00010000u */ + OffsetTo<MathConstants> mathConstants;/* MathConstants table */ + OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */ + OffsetTo<MathVariants> mathVariants; /* MathVariants table */ + + public: + DEFINE_SIZE_STATIC (10); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_MATH_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc index 9ef21d2995..f82a07353c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-math.cc @@ -26,33 +26,15 @@ #include "hb-open-type-private.hh" -#include "hb-ot-layout-math-table.hh" - -HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) +#include "hb-ot-layout-private.hh" +#include "hb-ot-math-table.hh" static inline const OT::MATH& _get_math (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::MATH); - hb_ot_layout_t * layout = hb_ot_layout_from_face (face); - -retry: - const OT::MATH *math = (const OT::MATH *) hb_atomic_ptr_get (&layout->math); - - if (unlikely (!math)) - { - hb_blob_t *blob = OT::Sanitizer<OT::MATH>::sanitize (face->reference_table (HB_OT_TAG_MATH)); - math = OT::Sanitizer<OT::MATH>::lock_instance (blob); - if (!hb_atomic_ptr_cmpexch (&layout->math, NULL, math)) - { - hb_blob_destroy (blob); - goto retry; - } - layout->math_blob = blob; - } - - return *math; + return *(layout->math.get ()); } /* @@ -64,10 +46,9 @@ retry: * @face: #hb_face_t to test * * This function allows to verify the presence of an OpenType MATH table on the - * face. If so, such a table will be loaded into memory and sanitized. You can - * then safely call other functions for math layout and shaping. + * face. * - * Return value: #TRUE if face has a MATH table and #FALSE otherwise + * Return value: true if face has a MATH table, false otherwise * * Since: 1.3.3 **/ @@ -136,10 +117,10 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, /** * hb_ot_math_is_glyph_extended_shape: - * @font: a #hb_font_t to test + * @face: a #hb_face_t to test * @glyph: a glyph index to test * - * Return value: #TRUE if the glyph is an extended shape and #FALSE otherwise + * Return value: true if the glyph is an extended shape, false otherwise * * Since: 1.3.3 **/ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh index 943e3908c7..f6d283eb14 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-maxp-table.hh @@ -60,7 +60,7 @@ struct maxp protected: FixedVersion<>version; /* Version of the maxp table (0.5 or 1.0), * 0x00005000u or 0x00010000u. */ - USHORT numGlyphs; /* The number of glyphs in the font. */ + UINT16 numGlyphs; /* The number of glyphs in the font. */ public: DEFINE_SIZE_STATIC (6); }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh index 870f123325..4c5b3c0f98 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-name-table.hh @@ -42,8 +42,10 @@ namespace OT { struct NameRecord { - static int cmp (const NameRecord *a, const NameRecord *b) + static int cmp (const void *pa, const void *pb) { + const NameRecord *a = (const NameRecord *) pa; + const NameRecord *b = (const NameRecord *) pb; int ret; ret = b->platformID.cmp (a->platformID); if (ret) return ret; @@ -63,12 +65,12 @@ struct NameRecord return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset)); } - USHORT platformID; /* Platform ID. */ - USHORT encodingID; /* Platform-specific encoding ID. */ - USHORT languageID; /* Language ID. */ - USHORT nameID; /* Name ID. */ - USHORT length; /* String length (in bytes). */ - USHORT offset; /* String offset from start of storage area (in bytes). */ + UINT16 platformID; /* Platform ID. */ + UINT16 encodingID; /* Platform-specific encoding ID. */ + UINT16 languageID; /* Language ID. */ + UINT16 nameID; /* Name ID. */ + UINT16 length; /* String length (in bytes). */ + UINT16 offset; /* String offset from start of storage area (in bytes). */ public: DEFINE_SIZE_STATIC (12); }; @@ -89,7 +91,7 @@ struct name key.encodingID.set (encoding_id); key.languageID.set (language_id); key.nameID.set (name_id); - NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), (hb_compare_func_t) NameRecord::cmp); + NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp); if (!match) return 0; @@ -121,9 +123,9 @@ struct name } /* We only implement format 0 for now. */ - USHORT format; /* Format selector (=0/1). */ - USHORT count; /* Number of name records. */ - Offset<> stringOffset; /* Offset to start of string storage (from start of table). */ + UINT16 format; /* Format selector (=0/1). */ + UINT16 count; /* Number of name records. */ + Offset16 stringOffset; /* Offset to start of string storage (from start of table). */ NameRecord nameRecord[VAR]; /* The name records where count is the number of records. */ public: DEFINE_SIZE_ARRAY (6, nameRecord); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh index 4709cd6e87..aa78f1e0a6 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-os2-table.hh @@ -50,50 +50,50 @@ struct os2 } public: - USHORT version; + UINT16 version; /* Version 0 */ - SHORT xAvgCharWidth; - USHORT usWeightClass; - USHORT usWidthClass; - USHORT fsType; - SHORT ySubscriptXSize; - SHORT ySubscriptYSize; - SHORT ySubscriptXOffset; - SHORT ySubscriptYOffset; - SHORT ySuperscriptXSize; - SHORT ySuperscriptYSize; - SHORT ySuperscriptXOffset; - SHORT ySuperscriptYOffset; - SHORT yStrikeoutSize; - SHORT yStrikeoutPosition; - SHORT sFamilyClass; - BYTE panose[10]; - ULONG ulUnicodeRange[4]; + INT16 xAvgCharWidth; + UINT16 usWeightClass; + UINT16 usWidthClass; + UINT16 fsType; + INT16 ySubscriptXSize; + INT16 ySubscriptYSize; + INT16 ySubscriptXOffset; + INT16 ySubscriptYOffset; + INT16 ySuperscriptXSize; + INT16 ySuperscriptYSize; + INT16 ySuperscriptXOffset; + INT16 ySuperscriptYOffset; + INT16 yStrikeoutSize; + INT16 yStrikeoutPosition; + INT16 sFamilyClass; + UINT8 panose[10]; + UINT32 ulUnicodeRange[4]; Tag achVendID; - USHORT fsSelection; - USHORT usFirstCharIndex; - USHORT usLastCharIndex; - SHORT sTypoAscender; - SHORT sTypoDescender; - SHORT sTypoLineGap; - USHORT usWinAscent; - USHORT usWinDescent; + UINT16 fsSelection; + UINT16 usFirstCharIndex; + UINT16 usLastCharIndex; + INT16 sTypoAscender; + INT16 sTypoDescender; + INT16 sTypoLineGap; + UINT16 usWinAscent; + UINT16 usWinDescent; /* Version 1 */ - //ULONG ulCodePageRange1; - //ULONG ulCodePageRange2; + //UINT32 ulCodePageRange1; + //UINT32 ulCodePageRange2; /* Version 2 */ - //SHORT sxHeight; - //SHORT sCapHeight; - //USHORT usDefaultChar; - //USHORT usBreakChar; - //USHORT usMaxContext; + //INT16 sxHeight; + //INT16 sCapHeight; + //UINT16 usDefaultChar; + //UINT16 usBreakChar; + //UINT16 usMaxContext; /* Version 5 */ - //USHORT usLowerOpticalPointSize; - //USHORT usUpperOpticalPointSize; + //UINT16 usLowerOpticalPointSize; + //UINT16 usUpperOpticalPointSize; public: DEFINE_SIZE_STATIC (78); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-macroman.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-macroman.hh new file mode 100644 index 0000000000..dbbb97e5a9 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-macroman.hh @@ -0,0 +1,294 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_OT_POST_MACROMAN_HH +#if 0 /* Make checks happy. */ +#define HB_OT_POST_MACROMAN_HH +#include "hb-private.hh" +#endif + + +_S(".notdef") +_S(".null") +_S("nonmarkingreturn") +_S("space") +_S("exclam") +_S("quotedbl") +_S("numbersign") +_S("dollar") +_S("percent") +_S("ampersand") +_S("quotesingle") +_S("parenleft") +_S("parenright") +_S("asterisk") +_S("plus") +_S("comma") +_S("hyphen") +_S("period") +_S("slash") +_S("zero") +_S("one") +_S("two") +_S("three") +_S("four") +_S("five") +_S("six") +_S("seven") +_S("eight") +_S("nine") +_S("colon") +_S("semicolon") +_S("less") +_S("equal") +_S("greater") +_S("question") +_S("at") +_S("A") +_S("B") +_S("C") +_S("D") +_S("E") +_S("F") +_S("G") +_S("H") +_S("I") +_S("J") +_S("K") +_S("L") +_S("M") +_S("N") +_S("O") +_S("P") +_S("Q") +_S("R") +_S("S") +_S("T") +_S("U") +_S("V") +_S("W") +_S("X") +_S("Y") +_S("Z") +_S("bracketleft") +_S("backslash") +_S("bracketright") +_S("asciicircum") +_S("underscore") +_S("grave") +_S("a") +_S("b") +_S("c") +_S("d") +_S("e") +_S("f") +_S("g") +_S("h") +_S("i") +_S("j") +_S("k") +_S("l") +_S("m") +_S("n") +_S("o") +_S("p") +_S("q") +_S("r") +_S("s") +_S("t") +_S("u") +_S("v") +_S("w") +_S("x") +_S("y") +_S("z") +_S("braceleft") +_S("bar") +_S("braceright") +_S("asciitilde") +_S("Adieresis") +_S("Aring") +_S("Ccedilla") +_S("Eacute") +_S("Ntilde") +_S("Odieresis") +_S("Udieresis") +_S("aacute") +_S("agrave") +_S("acircumflex") +_S("adieresis") +_S("atilde") +_S("aring") +_S("ccedilla") +_S("eacute") +_S("egrave") +_S("ecircumflex") +_S("edieresis") +_S("iacute") +_S("igrave") +_S("icircumflex") +_S("idieresis") +_S("ntilde") +_S("oacute") +_S("ograve") +_S("ocircumflex") +_S("odieresis") +_S("otilde") +_S("uacute") +_S("ugrave") +_S("ucircumflex") +_S("udieresis") +_S("dagger") +_S("degree") +_S("cent") +_S("sterling") +_S("section") +_S("bullet") +_S("paragraph") +_S("germandbls") +_S("registered") +_S("copyright") +_S("trademark") +_S("acute") +_S("dieresis") +_S("notequal") +_S("AE") +_S("Oslash") +_S("infinity") +_S("plusminus") +_S("lessequal") +_S("greaterequal") +_S("yen") +_S("mu") +_S("partialdiff") +_S("summation") +_S("product") +_S("pi") +_S("integral") +_S("ordfeminine") +_S("ordmasculine") +_S("Omega") +_S("ae") +_S("oslash") +_S("questiondown") +_S("exclamdown") +_S("logicalnot") +_S("radical") +_S("florin") +_S("approxequal") +_S("Delta") +_S("guillemotleft") +_S("guillemotright") +_S("ellipsis") +_S("nonbreakingspace") +_S("Agrave") +_S("Atilde") +_S("Otilde") +_S("OE") +_S("oe") +_S("endash") +_S("emdash") +_S("quotedblleft") +_S("quotedblright") +_S("quoteleft") +_S("quoteright") +_S("divide") +_S("lozenge") +_S("ydieresis") +_S("Ydieresis") +_S("fraction") +_S("currency") +_S("guilsinglleft") +_S("guilsinglright") +_S("fi") +_S("fl") +_S("daggerdbl") +_S("periodcentered") +_S("quotesinglbase") +_S("quotedblbase") +_S("perthousand") +_S("Acircumflex") +_S("Ecircumflex") +_S("Aacute") +_S("Edieresis") +_S("Egrave") +_S("Iacute") +_S("Icircumflex") +_S("Idieresis") +_S("Igrave") +_S("Oacute") +_S("Ocircumflex") +_S("apple") +_S("Ograve") +_S("Uacute") +_S("Ucircumflex") +_S("Ugrave") +_S("dotlessi") +_S("circumflex") +_S("tilde") +_S("macron") +_S("breve") +_S("dotaccent") +_S("ring") +_S("cedilla") +_S("hungarumlaut") +_S("ogonek") +_S("caron") +_S("Lslash") +_S("lslash") +_S("Scaron") +_S("scaron") +_S("Zcaron") +_S("zcaron") +_S("brokenbar") +_S("Eth") +_S("eth") +_S("Yacute") +_S("yacute") +_S("Thorn") +_S("thorn") +_S("minus") +_S("multiply") +_S("onesuperior") +_S("twosuperior") +_S("threesuperior") +_S("onehalf") +_S("onequarter") +_S("threequarters") +_S("franc") +_S("Gbreve") +_S("gbreve") +_S("Idotaccent") +_S("Scedilla") +_S("scedilla") +_S("Cacute") +_S("cacute") +_S("Ccaron") +_S("ccaron") +_S("dcroat") + + +#endif /* HB_OT_POST_MACROMAN_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh index 82ab3882a8..7f1c2c420f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-table.hh @@ -28,7 +28,15 @@ #define HB_OT_POST_TABLE_HH #include "hb-open-type-private.hh" +#include "hb-dsalgs.hh" +#define HB_STRING_ARRAY_NAME format1_names +#define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh" +#include "hb-string-array.hh" +#undef HB_STRING_ARRAY_LIST +#undef HB_STRING_ARRAY_NAME + +#define NUM_FORMAT1_NAMES 258 namespace OT { @@ -45,16 +53,13 @@ struct postV2Tail inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (numberOfGlyphs.sanitize (c) && - c->check_array (glyphNameIndex, sizeof (USHORT), numberOfGlyphs)); + return_trace (glyphNameIndex.sanitize (c)); } - USHORT numberOfGlyphs; /* Number of glyphs (this should be the - * same as numGlyphs in 'maxp' table). */ - USHORT glyphNameIndex[VAR]; /* This is not an offset, but is the + ArrayOf<UINT16>glyphNameIndex; /* This is not an offset, but is the * ordinal number of the glyph in 'post' * string tables. */ - BYTE namesX[VAR]; /* Glyph names with length bytes [variable] + UINT8 namesX[VAR]; /* Glyph names with length bytes [variable] * (a Pascal string). */ DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX); @@ -71,12 +76,170 @@ struct post return_trace (false); if (version.to_int () == 0x00020000) { - const postV2Tail &v2 = StructAfter<postV2Tail>(*this); + const postV2Tail &v2 = StructAfter<postV2Tail> (*this); return_trace (v2.sanitize (c)); } return_trace (true); } + struct accelerator_t + { + inline void init (hb_face_t *face) + { + blob = Sanitizer<post>::sanitize (face->reference_table (HB_OT_TAG_post)); + const post *table = Sanitizer<post>::lock_instance (blob); + unsigned int table_length = hb_blob_get_length (blob); + + version = table->version.to_int (); + index_to_offset.init (); + if (version != 0x00020000) + return; + + const postV2Tail &v2 = StructAfter<postV2Tail> (*table); + + glyphNameIndex = &v2.glyphNameIndex; + pool = &StructAfter<uint8_t> (v2.glyphNameIndex); + + const uint8_t *end = (uint8_t *) table + table_length; + for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data) + { + uint32_t *offset = index_to_offset.push (); + if (unlikely (!offset)) + break; + *offset = data - pool; + } + } + inline void fini (void) + { + index_to_offset.finish (); + free (gids_sorted_by_name); + } + + inline bool get_glyph_name (hb_codepoint_t glyph, + char *buf, unsigned int buf_len) const + { + hb_string_t s = find_glyph_name (glyph); + if (!s.len) + return false; + if (!buf_len) + return true; + if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */ + return false; + strncpy (buf, s.bytes, s.len); + buf[s.len] = '\0'; + return true; + } + + inline bool get_glyph_from_name (const char *name, int len, + hb_codepoint_t *glyph) const + { + unsigned int count = get_glyph_count (); + if (unlikely (!count)) + return false; + + if (len < 0) + len = strlen (name); + + if (unlikely (!len)) + return false; + + retry: + uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name); + + if (unlikely (!gids)) + { + gids = (uint16_t *) malloc (count * sizeof (gids[0])); + if (unlikely (!gids)) + return false; /* Anything better?! */ + + for (unsigned int i = 0; i < count; i++) + gids[i] = i; + hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this); + + if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) { + free (gids); + goto retry; + } + } + + hb_string_t st (name, len); + const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this); + if (gid) + { + *glyph = *gid; + return true; + } + + return false; + } + + protected: + + inline unsigned int get_glyph_count (void) const + { + if (version == 0x00010000) + return NUM_FORMAT1_NAMES; + + if (version == 0x00020000) + return glyphNameIndex->len; + + return 0; + } + + static inline int cmp_gids (const void *pa, const void *pb, void *arg) + { + const accelerator_t *thiz = (const accelerator_t *) arg; + uint16_t a = * (const uint16_t *) pa; + uint16_t b = * (const uint16_t *) pb; + return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a)); + } + + static inline int cmp_key (const void *pk, const void *po, void *arg) + { + const accelerator_t *thiz = (const accelerator_t *) arg; + const hb_string_t *key = (const hb_string_t *) pk; + uint16_t o = * (const uint16_t *) po; + return thiz->find_glyph_name (o).cmp (*key); + } + + inline hb_string_t find_glyph_name (hb_codepoint_t glyph) const + { + if (version == 0x00010000) + { + if (glyph >= NUM_FORMAT1_NAMES) + return hb_string_t (); + + return format1_names (glyph); + } + + if (version != 0x00020000 || glyph >= glyphNameIndex->len) + return hb_string_t (); + + unsigned int index = glyphNameIndex->array[glyph]; + if (index < NUM_FORMAT1_NAMES) + return format1_names (index); + index -= NUM_FORMAT1_NAMES; + + if (index >= index_to_offset.len) + return hb_string_t (); + unsigned int offset = index_to_offset.array[index]; + + const uint8_t *data = pool + offset; + unsigned int name_length = *data; + data++; + + return hb_string_t ((const char *) data, name_length); + } + + private: + hb_blob_t *blob; + uint32_t version; + const ArrayOf<UINT16> *glyphNameIndex; + hb_prealloced_array_t<uint32_t, 1> index_to_offset; + const uint8_t *pool; + mutable uint16_t *gids_sorted_by_name; + }; + public: FixedVersion<>version; /* 0x00010000 for version 1.0 * 0x00020000 for version 2.0 @@ -98,16 +261,16 @@ struct post * from the value of this field. */ FWORD underlineThickness; /* Suggested values for the underline thickness. */ - ULONG isFixedPitch; /* Set to 0 if the font is proportionally + UINT32 isFixedPitch; /* Set to 0 if the font is proportionally * spaced, non-zero if the font is not * proportionally spaced (i.e. monospaced). */ - ULONG minMemType42; /* Minimum memory usage when an OpenType font + UINT32 minMemType42; /* Minimum memory usage when an OpenType font * is downloaded. */ - ULONG maxMemType42; /* Maximum memory usage when an OpenType font + UINT32 maxMemType42; /* Maximum memory usage when an OpenType font * is downloaded. */ - ULONG minMemType1; /* Minimum memory usage when an OpenType font + UINT32 minMemType1; /* Minimum memory usage when an OpenType font * is downloaded as a Type 1 font. */ - ULONG maxMemType1; /* Maximum memory usage when an OpenType font + UINT32 maxMemType1; /* Maximum memory usage when an OpenType font * is downloaded as a Type 1 font. */ /*postV2Tail v2[VAR];*/ DEFINE_SIZE_STATIC (32); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh index d97d285210..d98cde121c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-fallback.hh @@ -73,11 +73,11 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS } if (!num_glyphs) - return NULL; + return nullptr; /* Bubble-sort or something equally good! * May not be good-enough for presidential candidate interviews, but good-enough for us... */ - hb_stable_sort (&glyphs[0], num_glyphs, OT::GlyphID::cmp, &substitutes[0]); + hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]); OT::Supplier<OT::GlyphID> glyphs_supplier (glyphs, num_glyphs); OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs); @@ -94,7 +94,7 @@ arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUS c.end_serialize (); /* TODO sanitize the results? */ - return ret ? c.copy<OT::SubstLookup> () : NULL; + return ret ? c.copy<OT::SubstLookup> () : nullptr; } static OT::SubstLookup * @@ -126,7 +126,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN first_glyphs_indirection[num_first_glyphs] = first_glyph_idx; num_first_glyphs++; } - hb_stable_sort (&first_glyphs[0], num_first_glyphs, OT::GlyphID::cmp, &first_glyphs_indirection[0]); + hb_stable_sort (&first_glyphs[0], num_first_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &first_glyphs_indirection[0]); /* Now that the first-glyphs are sorted, walk again, populate ligatures. */ for (unsigned int i = 0; i < num_first_glyphs; i++) @@ -153,7 +153,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN } if (!num_ligatures) - return NULL; + return nullptr; OT::Supplier<OT::GlyphID> first_glyphs_supplier (first_glyphs, num_first_glyphs); OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier (ligature_per_first_glyph_count_list, num_first_glyphs); @@ -177,7 +177,7 @@ arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UN c.end_serialize (); /* TODO sanitize the results? */ - return ret ? c.copy<OT::SubstLookup> () : NULL; + return ret ? c.copy<OT::SubstLookup> () : nullptr; } static OT::SubstLookup * @@ -237,8 +237,8 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan, return false; const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest); - ASSERT_STATIC (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup) - <= ARABIC_FALLBACK_MAX_LOOKUPS); + static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) / sizeof (ManifestLookup) + <= ARABIC_FALLBACK_MAX_LOOKUPS, ""); /* TODO sanitize the table? */ unsigned j = 0; @@ -271,7 +271,7 @@ arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan, const hb_ot_shape_plan_t *plan, hb_font_t *font) { - ASSERT_STATIC (ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS); + static_assert ((ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), ""); unsigned int j = 0; for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh index 736c7f76b3..cd6e4058b5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-table.hh @@ -6,10 +6,10 @@ * * on files with these headers: * - * # ArabicShaping-9.0.0.txt - * # Date: 2016-02-24, 22:25:00 GMT [RP] - * # Blocks-9.0.0.txt - * # Date: 2016-02-05, 23:48:00 GMT [KW] + * # ArabicShaping-10.0.0.txt + * # Date: 2017-02-16, 00:00:00 GMT [RP, KW] + * # Blocks-10.0.0.txt + * # Date: 2017-04-12, 17:30:00 GMT [KW] * UnicodeData.txt does not have a header. */ @@ -72,7 +72,10 @@ static const uint8_t joining_table[] = /* Mandaic */ /* 0840 */ R,D,D,D,D,D,R,R,D,R,D,D,D,D,D,D,D,D,D,D,R,D,U,U,U,X,X,X,X,X,X,X, - /* 0860 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + + /* Syriac Supplement */ + + /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, /* 0880 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, /* Arabic Extended-A */ @@ -130,7 +133,7 @@ static const uint8_t joining_table[] = /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D, /* 1E940 */ D,D,D,D, -}; /* Table items: 1214; occupancy: 54% */ +}; /* Table items: 1214; occupancy: 55% */ static unsigned int @@ -139,28 +142,28 @@ joining_type (hb_codepoint_t u) switch (u >> 12) { case 0x0u: - if (hb_in_range (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u]; + if (hb_in_range<hb_codepoint_t> (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u]; break; case 0x1u: - if (hb_in_range (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u]; break; case 0x2u: - if (hb_in_range (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu]; + if (hb_in_range<hb_codepoint_t> (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu]; break; case 0xAu: - if (hb_in_range (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u]; + if (hb_in_range<hb_codepoint_t> (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u]; break; case 0x10u: - if (hb_in_range (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u]; - if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u]; + if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u]; break; case 0x1Eu: - if (hb_in_range (u, 0x1E900u, 0x1E943u)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E943u)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u]; break; default: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh index e70c48f427..54c6cdc24f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic-win1256.hh @@ -43,16 +43,16 @@ #define OT_TABLE_END } #define OT_LABEL_START(Name) unsigned char Name[ #define OT_LABEL_END ]; -#define OT_BYTE(u8) +1/*byte*/ -#define OT_USHORT(u16) +2/*bytes*/ +#define OT_UINT8(u8) +1/*byte*/ +#define OT_UINT16(u16) +2/*bytes*/ #else #undef OT_MEASURE #define OT_TABLE_START TABLE_NAME = { #define OT_TABLE_END }; #define OT_LABEL_START(Name) { #define OT_LABEL_END }, -#define OT_BYTE(u8) (u8), -#define OT_USHORT(u16) (unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu), +#define OT_UINT8(u8) (u8), +#define OT_UINT16(u16) (unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu), #define OT_COUNT(Name, ItemSize) ((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \ / (unsigned int)(ItemSize) \ /* OT_ASSERT it's divisible (and positive). */) @@ -80,24 +80,24 @@ */ #define OT_TAG(a,b,c,d) \ - OT_BYTE(a) OT_BYTE(b) OT_BYTE(c) OT_BYTE(d) + OT_UINT8(a) OT_UINT8(b) OT_UINT8(c) OT_UINT8(d) #define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \ - OT_USHORT(OT_DISTANCE(From, To)) + OT_UINT16(OT_DISTANCE(From, To)) #define OT_GLYPHID /* GlyphID */ \ - OT_USHORT + OT_UINT16 #define OT_UARRAY(Name, Items) \ OT_LABEL_START(Name) \ - OT_USHORT(OT_COUNT(Name##Data, 2)) \ + OT_UINT16(OT_COUNT(Name##Data, 2)) \ OT_LABEL(Name##Data) \ Items \ OT_LABEL_END #define OT_UHEADLESSARRAY(Name, Items) \ OT_LABEL_START(Name) \ - OT_USHORT(OT_COUNT(Name##Data, 2) + 1) \ + OT_UINT16(OT_COUNT(Name##Data, 2) + 1) \ OT_LABEL(Name##Data) \ Items \ OT_LABEL_END @@ -111,19 +111,19 @@ #define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \ OT_LABEL_START(Name) \ - OT_USHORT(LookupType) \ - OT_USHORT(LookupFlag) \ + OT_UINT16(LookupType) \ + OT_UINT16(LookupFlag) \ OT_LABEL_END \ OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets)) #define OT_SUBLOOKUP(Name, SubFormat, Items) \ OT_LABEL_START(Name) \ - OT_USHORT(SubFormat) \ + OT_UINT16(SubFormat) \ Items #define OT_COVERAGE1(Name, Items) \ OT_LABEL_START(Name) \ - OT_USHORT(1) \ + OT_UINT16(1) \ OT_LABEL_END \ OT_UARRAY(Name##Glyphs, OT_LIST(Items)) @@ -174,7 +174,7 @@ /* Table manifest. */ #define MANIFEST(Items) \ OT_LABEL_START(manifest) \ - OT_USHORT(OT_COUNT(manifestData, 6)) \ + OT_UINT16(OT_COUNT(manifestData, 6)) \ OT_LABEL(manifestData) \ Items \ OT_LABEL_END @@ -304,8 +304,8 @@ OT_TABLE_END #undef OT_TABLE_END #undef OT_LABEL_START #undef OT_LABEL_END -#undef OT_BYTE -#undef OT_USHORT +#undef OT_UINT8 +#undef OT_UINT16 #undef OT_DISTANCE #undef OT_COUNT diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc index 56ec5cd65c..eb9d36ff1d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc @@ -24,24 +24,21 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb-private.hh" +#include "hb-debug.hh" #include "hb-ot-shape-complex-arabic-private.hh" #include "hb-ot-shape-private.hh" -#ifndef HB_DEBUG_ARABIC -#define HB_DEBUG_ARABIC (HB_DEBUG+0) -#endif - - /* buffer var allocations */ #define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */ #define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0 /* See: - * https://github.com/behdad/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */ + * https://github.com/harfbuzz/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */ #define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \ - (FLAG_SAFE (gen_cat) & \ + (FLAG_UNSAFE (gen_cat) & \ (FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \ /*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \ @@ -90,7 +87,7 @@ static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_categ if (likely (j_type != JOINING_TYPE_X)) return j_type; - return (FLAG_SAFE(gen_cat) & + return (FLAG_UNSAFE(gen_cat) & (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT)) @@ -199,6 +196,9 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * work. However, testing shows that rlig and calt are applied * together for Mongolian in Uniscribe. As such, we only add a * pause for Arabic, not other scripts. + * + * A pause after calt is required to make KFGQPC Uthmanic Script HAFS + * work correctly. See https://github.com/harfbuzz/harfbuzz/issues/505 */ map->add_gsub_pause (nuke_joiners); @@ -209,20 +209,23 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) map->add_global_bool_feature (HB_TAG('c','c','m','p')); map->add_global_bool_feature (HB_TAG('l','o','c','l')); - map->add_gsub_pause (NULL); + map->add_gsub_pause (nullptr); for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) { bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]); map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE); - map->add_gsub_pause (NULL); + map->add_gsub_pause (nullptr); } map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK); if (plan->props.script == HB_SCRIPT_ARABIC) map->add_gsub_pause (arabic_fallback_shape); + /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */ + map->add_global_bool_feature (HB_TAG('r','c','l','t')); map->add_global_bool_feature (HB_TAG('c','a','l','t')); + map->add_gsub_pause (nullptr); /* The spec includes 'cswh'. Earlier versions of Windows * used to enable this by default, but testing suggests @@ -232,7 +235,6 @@ collect_features_arabic (hb_ot_shape_planner_t *plan) * Note that IranNastaliq uses this feature extensively * to fixup broken glyph sequences. Oh well... * Test case: U+0643,U+0640,U+0631. */ - //map->add_gsub_pause (NULL); //map->add_global_bool_feature (HB_TAG('c','s','w','h')); map->add_global_bool_feature (HB_TAG('m','s','e','t')); } @@ -260,7 +262,7 @@ data_create_arabic (const hb_ot_shape_plan_t *plan) { arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t)); if (unlikely (!arabic_plan)) - return NULL; + return nullptr; arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC; arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h')); @@ -316,7 +318,10 @@ arabic_joining (hb_buffer_t *buffer) const arabic_state_table_entry *entry = &arabic_state_table[state][this_type]; if (entry->prev_action != NONE && prev != (unsigned int) -1) + { info[prev].arabic_shaping_action() = entry->prev_action; + buffer->unsafe_to_break (prev, i + 1); + } info[i].arabic_shaping_action() = entry->curr_action; @@ -345,7 +350,7 @@ mongolian_variation_selectors (hb_buffer_t *buffer) unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 1; i < count; i++) - if (unlikely (hb_in_range (info[i].codepoint, 0x180Bu, 0x180Du))) + if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du))) info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action(); } @@ -404,7 +409,7 @@ retry: { /* This sucks. We need a font to build the fallback plan... */ fallback_plan = arabic_fallback_plan_create (plan, font); - if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast<arabic_shape_plan_t *> (arabic_plan))->fallback_plan, NULL, fallback_plan))) { + if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast<arabic_shape_plan_t *> (arabic_plan))->fallback_plan, nullptr, fallback_plan))) { arabic_fallback_plan_destroy (fallback_plan); goto retry; } @@ -524,11 +529,11 @@ apply_stch (const hb_ot_shape_plan_t *plan, } i++; // Don't touch i again. - DEBUG_MSG (ARABIC, NULL, "%s stretch at (%d,%d,%d)", + DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%d,%d,%d)", step == MEASURE ? "measuring" : "cutting", context, start, end); - DEBUG_MSG (ARABIC, NULL, "rest of word: count=%d width %d", start - context, w_total); - DEBUG_MSG (ARABIC, NULL, "fixed tiles: count=%d width=%d", n_fixed, w_fixed); - DEBUG_MSG (ARABIC, NULL, "repeating tiles: count=%d width=%d", n_repeating, w_repeating); + DEBUG_MSG (ARABIC, nullptr, "rest of word: count=%d width %d", start - context, w_total); + DEBUG_MSG (ARABIC, nullptr, "fixed tiles: count=%d width=%d", n_fixed, w_fixed); + DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating); /* Number of additional times to repeat each repeating tile. */ int n_copies = 0; @@ -540,7 +545,7 @@ apply_stch (const hb_ot_shape_plan_t *plan, /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */ hb_position_t extra_repeat_overlap = 0; hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1); - if (shortfall > 0) + if (shortfall > 0 && n_repeating > 0) { ++n_copies; hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining; @@ -551,10 +556,11 @@ apply_stch (const hb_ot_shape_plan_t *plan, if (step == MEASURE) { extra_glyphs_needed += n_copies * n_repeating; - DEBUG_MSG (ARABIC, NULL, "will add extra %d copies of repeating tiles", n_copies); + DEBUG_MSG (ARABIC, nullptr, "will add extra %d copies of repeating tiles", n_copies); } else { + buffer->unsafe_to_break (context, end); hb_position_t x_offset = 0; for (unsigned int k = end; k > start; k--) { @@ -564,7 +570,7 @@ apply_stch (const hb_ot_shape_plan_t *plan, if (info[k - 1].arabic_shaping_action() == STCH_REPEATING) repeat += n_copies; - DEBUG_MSG (ARABIC, NULL, "appending %d copies of glyph %d; j=%d", + DEBUG_MSG (ARABIC, nullptr, "appending %d copies of glyph %d; j=%d", repeat, info[k - 1].codepoint, j); for (unsigned int n = 0; n < repeat; n++) { @@ -605,20 +611,94 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan, HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action); } +/* http://www.unicode.org/reports/tr53/tr53-1.pdf */ + +static hb_codepoint_t +modifier_combining_marks[] = +{ + 0x0654u, /* ARABIC HAMZA ABOVE */ + 0x0655u, /* ARABIC HAMZA BELOW */ + 0x0658u, /* ARABIC MARK NOON GHUNNA */ + 0x06DCu, /* ARABIC SMALL HIGH SEEN */ + 0x06E3u, /* ARABIC SMALL LOW SEEN */ + 0x06E7u, /* ARABIC SMALL HIGH YEH */ + 0x06E8u, /* ARABIC SMALL HIGH NOON */ + 0x08F3u, /* ARABIC SMALL HIGH WAW */ +}; + +static inline bool +info_is_mcm (const hb_glyph_info_t &info) +{ + hb_codepoint_t u = info.codepoint; + for (unsigned int i = 0; i < ARRAY_LENGTH (modifier_combining_marks); i++) + if (u == modifier_combining_marks[i]) + return true; + return false; +} + +static void +reorder_marks_arabic (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + unsigned int start, + unsigned int end) +{ + hb_glyph_info_t *info = buffer->info; + + unsigned int i = start; + for (unsigned int cc = 220; cc <= 230; cc += 10) + { + DEBUG_MSG (ARABIC, buffer, "Looking for %d's starting at %d\n", cc, i); + while (i < end && info_cc(info[i]) < cc) + i++; + DEBUG_MSG (ARABIC, buffer, "Looking for %d's stopped at %d\n", cc, i); + + if (i == end) + break; + + if (info_cc(info[i]) > cc) + continue; + + /* Technically we should also check "info_cc(info[j]) == cc" + * in the following loop. But not doing it is safe; we might + * end up moving all the 220 MCMs and 230 MCMs together in one + * move and be done. */ + unsigned int j = i; + while (j < end && info_is_mcm (info[j])) + j++; + DEBUG_MSG (ARABIC, buffer, "Found %d's from %d to %d\n", cc, i, j); + + if (i == j) + continue; + + /* Shift it! */ + DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d\n", cc, i, j); + hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS]; + assert (j - i <= ARRAY_LENGTH (temp)); + buffer->merge_clusters (start, j); + memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t)); + memmove (&info[start + j - i], &info[start], (i - start) * sizeof (hb_glyph_info_t)); + memmove (&info[start], temp, (j - i) * sizeof (hb_glyph_info_t)); + + start += j - i; + + i = j; + } +} + const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic = { - "arabic", collect_features_arabic, - NULL, /* override_features */ + nullptr, /* override_features */ data_create_arabic, data_destroy_arabic, - NULL, /* preprocess_text */ + nullptr, /* preprocess_text */ postprocess_glyphs_arabic, HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, - NULL, /* decompose */ - NULL, /* compose */ + nullptr, /* decompose */ + nullptr, /* compose */ setup_masks_arabic, - NULL, /* disable_otl */ + nullptr, /* disable_otl */ + reorder_marks_arabic, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc index 42830ab618..68a62a10d4 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-default.cc @@ -29,18 +29,18 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default = { - "default", - NULL, /* collect_features */ - NULL, /* override_features */ - NULL, /* data_create */ - NULL, /* data_destroy */ - NULL, /* preprocess_text */ - NULL, /* postprocess_glyphs */ + nullptr, /* collect_features */ + nullptr, /* override_features */ + nullptr, /* data_create */ + nullptr, /* data_destroy */ + nullptr, /* preprocess_text */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, - NULL, /* decompose */ - NULL, /* compose */ - NULL, /* setup_masks */ - NULL, /* disable_otl */ + nullptr, /* decompose */ + nullptr, /* compose */ + nullptr, /* setup_masks */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc index eb95a28c09..7508c223c4 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc @@ -32,7 +32,7 @@ /* Same order as the feature array below */ enum { - NONE, + _JMO, LJMO, VJMO, @@ -80,7 +80,7 @@ data_create_hangul (const hb_ot_shape_plan_t *plan) { hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) calloc (1, sizeof (hangul_shape_plan_t)); if (unlikely (!hangul_plan)) - return NULL; + return nullptr; for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++) hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]); @@ -105,16 +105,16 @@ data_destroy_hangul (void *data) #define NCount (VCount * TCount) #define SCount (LCount * NCount) -#define isCombiningL(u) (hb_in_range ((u), LBase, LBase+LCount-1)) -#define isCombiningV(u) (hb_in_range ((u), VBase, VBase+VCount-1)) -#define isCombiningT(u) (hb_in_range ((u), TBase+1, TBase+TCount-1)) -#define isCombinedS(u) (hb_in_range ((u), SBase, SBase+SCount-1)) +#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1)) +#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1)) +#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1)) +#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1)) -#define isL(u) (hb_in_ranges ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu)) -#define isV(u) (hb_in_ranges ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u)) -#define isT(u) (hb_in_ranges ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu)) +#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu)) +#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u)) +#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu)) -#define isHangulTone(u) (hb_in_range ((u), 0x302Eu, 0x302Fu)) +#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu)) /* buffer var allocations */ #define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ @@ -202,6 +202,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, if (start < end && end == buffer->out_len) { /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ + buffer->unsafe_to_break_from_outbuffer (start, buffer->idx); buffer->next_glyph (); if (!is_zero_width_char (font, u)) { @@ -258,6 +259,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, else t = 0; /* The next character was not a trailing jamo. */ } + buffer->unsafe_to_break (buffer->idx, buffer->idx + (t ? 3 : 2)); /* We've got a syllable <L,V,T?>; see if it can potentially be composed. */ if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t))) @@ -322,6 +324,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, end = start + 1; continue; } + else + buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */ } /* Otherwise, decompose if font doesn't support <LV> or <LVT>, @@ -368,6 +372,8 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan, buffer->merge_out_clusters (start, end); continue; } + else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint))) + buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */ } if (has_glyph) @@ -408,18 +414,18 @@ setup_masks_hangul (const hb_ot_shape_plan_t *plan, const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul = { - "hangul", collect_features_hangul, override_features_hangul, data_create_hangul, data_destroy_hangul, preprocess_text_hangul, - NULL, /* postprocess_glyphs */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_NONE, - NULL, /* decompose */ - NULL, /* compose */ + nullptr, /* decompose */ + nullptr, /* compose */ setup_masks_hangul, - NULL, /* disable_otl */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc index 96f2494616..34cf28b8e2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc @@ -161,7 +161,7 @@ disable_otl_hebrew (const hb_ot_shape_plan_t *plan) * script. This matches Uniscribe better, and makes fonts like * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work. * See: - * https://github.com/behdad/harfbuzz/issues/347#issuecomment-267838368 + * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */ return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r'); } @@ -169,18 +169,18 @@ disable_otl_hebrew (const hb_ot_shape_plan_t *plan) const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = { - "hebrew", - NULL, /* collect_features */ - NULL, /* override_features */ - NULL, /* data_create */ - NULL, /* data_destroy */ - NULL, /* preprocess_text */ - NULL, /* postprocess_glyphs */ + nullptr, /* collect_features */ + nullptr, /* override_features */ + nullptr, /* data_create */ + nullptr, /* data_destroy */ + nullptr, /* preprocess_text */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, - NULL, /* decompose */ + nullptr, /* decompose */ compose_hebrew, - NULL, /* setup_masks */ + nullptr, /* setup_masks */ disable_otl_hebrew, + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh index 5a7a265c87..7eaba4e4e7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-machine.hh @@ -56,7 +56,7 @@ static const unsigned char _indic_syllable_machine_trans_keys[] = { 5u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 8u, 8u, 1u, 16u, 8u, 13u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, - 16u, 16u, 8u, 8u, 1u, 18u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, + 16u, 16u, 8u, 8u, 1u, 19u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 14u, 5u, 14u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, 9u, 10u, 9u, 9u, 5u, 10u, 3u, 13u, @@ -101,7 +101,7 @@ static const unsigned char _indic_syllable_machine_trans_keys[] = { 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 14u, 4u, 14u, 5u, 14u, 3u, 13u, 3u, 10u, 5u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 3u, 10u, 5u, 10u, 5u, 10u, 9u, 10u, 9u, 9u, 9u, 10u, - 9u, 10u, 9u, 9u, 5u, 10u, 0 + 9u, 10u, 9u, 9u, 5u, 10u, 1u, 16u, 0 }; static const char _indic_syllable_machine_key_spans[] = { @@ -127,7 +127,7 @@ static const char _indic_syllable_machine_key_spans[] = { 3, 4, 3, 1, 4, 3, 1, 4, 3, 1, 1, 16, 6, 5, 1, 1, 5, 1, 1, 5, 1, 1, 5, 1, - 1, 1, 18, 15, 15, 14, 16, 15, + 1, 1, 19, 15, 15, 14, 16, 15, 15, 14, 16, 15, 15, 14, 16, 15, 15, 14, 16, 15, 15, 14, 10, 10, 6, 2, 1, 2, 2, 1, 6, 11, @@ -172,7 +172,7 @@ static const char _indic_syllable_machine_key_spans[] = { 12, 11, 10, 12, 11, 10, 12, 11, 10, 12, 11, 10, 11, 8, 6, 8, 11, 16, 8, 6, 6, 2, 1, 2, - 2, 1, 6 + 2, 1, 6, 16 }; static const short _indic_syllable_machine_index_offsets[] = { @@ -198,52 +198,52 @@ static const short _indic_syllable_machine_index_offsets[] = { 954, 958, 963, 967, 969, 974, 978, 980, 985, 989, 991, 993, 1010, 1017, 1023, 1025, 1027, 1033, 1035, 1037, 1043, 1045, 1047, 1053, - 1055, 1057, 1059, 1078, 1094, 1110, 1125, 1142, - 1158, 1174, 1189, 1206, 1222, 1238, 1253, 1270, - 1286, 1302, 1317, 1334, 1350, 1366, 1381, 1392, - 1403, 1410, 1413, 1415, 1418, 1421, 1423, 1430, - 1442, 1451, 1458, 1467, 1479, 1492, 1505, 1517, - 1528, 1541, 1553, 1564, 1577, 1589, 1600, 1613, - 1625, 1636, 1649, 1666, 1678, 1694, 1710, 1727, - 1744, 1761, 1778, 1795, 1811, 1827, 1844, 1861, - 1878, 1895, 1912, 1928, 1944, 1961, 1978, 1995, - 2012, 2029, 2045, 2061, 2078, 2095, 2112, 2129, - 2146, 2162, 2178, 2194, 2210, 2225, 2242, 2258, - 2274, 2289, 2306, 2322, 2338, 2353, 2370, 2386, - 2402, 2417, 2434, 2450, 2466, 2481, 2492, 2503, - 2510, 2513, 2515, 2518, 2521, 2523, 2530, 2542, - 2551, 2558, 2567, 2579, 2592, 2605, 2617, 2628, - 2641, 2653, 2664, 2677, 2689, 2700, 2713, 2725, - 2736, 2749, 2766, 2778, 2794, 2810, 2827, 2844, - 2861, 2878, 2895, 2911, 2927, 2944, 2961, 2978, - 2995, 3012, 3028, 3044, 3061, 3078, 3095, 3112, - 3129, 3145, 3161, 3178, 3195, 3212, 3229, 3241, - 3258, 3274, 3290, 3305, 3322, 3338, 3354, 3369, - 3386, 3402, 3418, 3433, 3450, 3466, 3482, 3497, - 3514, 3530, 3546, 3561, 3572, 3583, 3590, 3593, - 3595, 3598, 3601, 3603, 3610, 3622, 3631, 3638, - 3647, 3659, 3672, 3685, 3697, 3708, 3721, 3733, - 3744, 3757, 3769, 3780, 3793, 3805, 3816, 3829, - 3846, 3858, 3874, 3890, 3907, 3924, 3941, 3958, - 3975, 3991, 4007, 4024, 4041, 4058, 4075, 4092, - 4108, 4124, 4141, 4158, 4175, 4192, 4209, 4225, - 4241, 4258, 4275, 4292, 4309, 4326, 4338, 4354, - 4366, 4382, 4398, 4413, 4430, 4446, 4462, 4477, - 4494, 4510, 4526, 4541, 4558, 4574, 4590, 4605, - 4622, 4638, 4654, 4669, 4680, 4691, 4698, 4701, - 4703, 4706, 4709, 4711, 4718, 4730, 4739, 4746, - 4755, 4767, 4780, 4793, 4805, 4816, 4829, 4841, - 4852, 4865, 4877, 4888, 4901, 4913, 4924, 4937, - 4954, 4966, 4982, 4998, 5015, 5032, 5049, 5066, - 5083, 5099, 5115, 5132, 5149, 5166, 5183, 5200, - 5216, 5232, 5249, 5266, 5283, 5300, 5317, 5333, - 5349, 5366, 5383, 5400, 5417, 5434, 5450, 5468, - 5484, 5502, 5514, 5521, 5524, 5526, 5529, 5532, - 5534, 5541, 5558, 5574, 5590, 5605, 5621, 5637, - 5654, 5667, 5679, 5690, 5703, 5715, 5726, 5739, - 5751, 5762, 5775, 5787, 5798, 5810, 5819, 5826, - 5835, 5847, 5864, 5873, 5880, 5887, 5890, 5892, - 5895, 5898, 5900 + 1055, 1057, 1059, 1079, 1095, 1111, 1126, 1143, + 1159, 1175, 1190, 1207, 1223, 1239, 1254, 1271, + 1287, 1303, 1318, 1335, 1351, 1367, 1382, 1393, + 1404, 1411, 1414, 1416, 1419, 1422, 1424, 1431, + 1443, 1452, 1459, 1468, 1480, 1493, 1506, 1518, + 1529, 1542, 1554, 1565, 1578, 1590, 1601, 1614, + 1626, 1637, 1650, 1667, 1679, 1695, 1711, 1728, + 1745, 1762, 1779, 1796, 1812, 1828, 1845, 1862, + 1879, 1896, 1913, 1929, 1945, 1962, 1979, 1996, + 2013, 2030, 2046, 2062, 2079, 2096, 2113, 2130, + 2147, 2163, 2179, 2195, 2211, 2226, 2243, 2259, + 2275, 2290, 2307, 2323, 2339, 2354, 2371, 2387, + 2403, 2418, 2435, 2451, 2467, 2482, 2493, 2504, + 2511, 2514, 2516, 2519, 2522, 2524, 2531, 2543, + 2552, 2559, 2568, 2580, 2593, 2606, 2618, 2629, + 2642, 2654, 2665, 2678, 2690, 2701, 2714, 2726, + 2737, 2750, 2767, 2779, 2795, 2811, 2828, 2845, + 2862, 2879, 2896, 2912, 2928, 2945, 2962, 2979, + 2996, 3013, 3029, 3045, 3062, 3079, 3096, 3113, + 3130, 3146, 3162, 3179, 3196, 3213, 3230, 3242, + 3259, 3275, 3291, 3306, 3323, 3339, 3355, 3370, + 3387, 3403, 3419, 3434, 3451, 3467, 3483, 3498, + 3515, 3531, 3547, 3562, 3573, 3584, 3591, 3594, + 3596, 3599, 3602, 3604, 3611, 3623, 3632, 3639, + 3648, 3660, 3673, 3686, 3698, 3709, 3722, 3734, + 3745, 3758, 3770, 3781, 3794, 3806, 3817, 3830, + 3847, 3859, 3875, 3891, 3908, 3925, 3942, 3959, + 3976, 3992, 4008, 4025, 4042, 4059, 4076, 4093, + 4109, 4125, 4142, 4159, 4176, 4193, 4210, 4226, + 4242, 4259, 4276, 4293, 4310, 4327, 4339, 4355, + 4367, 4383, 4399, 4414, 4431, 4447, 4463, 4478, + 4495, 4511, 4527, 4542, 4559, 4575, 4591, 4606, + 4623, 4639, 4655, 4670, 4681, 4692, 4699, 4702, + 4704, 4707, 4710, 4712, 4719, 4731, 4740, 4747, + 4756, 4768, 4781, 4794, 4806, 4817, 4830, 4842, + 4853, 4866, 4878, 4889, 4902, 4914, 4925, 4938, + 4955, 4967, 4983, 4999, 5016, 5033, 5050, 5067, + 5084, 5100, 5116, 5133, 5150, 5167, 5184, 5201, + 5217, 5233, 5250, 5267, 5284, 5301, 5318, 5334, + 5350, 5367, 5384, 5401, 5418, 5435, 5451, 5469, + 5485, 5503, 5515, 5522, 5525, 5527, 5530, 5533, + 5535, 5542, 5559, 5575, 5591, 5606, 5622, 5638, + 5655, 5668, 5680, 5691, 5704, 5716, 5727, 5740, + 5752, 5763, 5776, 5788, 5799, 5811, 5820, 5827, + 5836, 5848, 5865, 5874, 5881, 5888, 5891, 5893, + 5896, 5899, 5901, 5908 }; static const short _indic_syllable_machine_indicies[] = { @@ -381,611 +381,613 @@ static const short _indic_syllable_machine_indicies[] = { 161, 161, 162, 157, 0, 183, 0, 184, 0, 186, 185, 188, 189, 190, 191, 192, 193, 84, 79, 194, 195, 196, 196, 156, - 197, 198, 199, 200, 201, 187, 203, 204, - 205, 206, 6, 1, 207, 208, 202, 202, - 38, 209, 202, 202, 210, 202, 211, 204, - 212, 212, 6, 1, 207, 208, 202, 202, - 202, 209, 202, 202, 210, 202, 204, 212, - 212, 6, 1, 207, 208, 202, 202, 202, - 209, 202, 202, 210, 202, 213, 202, 202, - 202, 19, 214, 202, 1, 207, 208, 202, - 202, 202, 215, 202, 213, 202, 216, 217, - 218, 219, 6, 1, 207, 208, 202, 202, - 36, 220, 202, 202, 210, 202, 221, 217, - 222, 222, 6, 1, 207, 208, 202, 202, - 202, 220, 202, 202, 210, 202, 217, 222, - 222, 6, 1, 207, 208, 202, 202, 202, - 220, 202, 202, 210, 202, 223, 202, 202, - 202, 19, 224, 202, 1, 207, 208, 202, - 202, 202, 215, 202, 223, 202, 225, 226, - 227, 228, 6, 1, 207, 208, 202, 202, - 34, 229, 202, 202, 210, 202, 230, 226, - 231, 231, 6, 1, 207, 208, 202, 202, - 202, 229, 202, 202, 210, 202, 226, 231, - 231, 6, 1, 207, 208, 202, 202, 202, - 229, 202, 202, 210, 202, 232, 202, 202, - 202, 19, 233, 202, 1, 207, 208, 202, - 202, 202, 215, 202, 232, 202, 234, 235, - 236, 237, 6, 1, 207, 208, 202, 202, - 32, 238, 202, 202, 210, 202, 239, 235, - 240, 240, 6, 1, 207, 208, 202, 202, - 202, 238, 202, 202, 210, 202, 235, 240, - 240, 6, 1, 207, 208, 202, 202, 202, - 238, 202, 202, 210, 202, 241, 202, 202, - 202, 19, 242, 202, 1, 207, 208, 202, - 202, 202, 215, 202, 241, 202, 243, 244, - 245, 246, 6, 1, 207, 208, 202, 202, - 30, 247, 202, 202, 210, 202, 248, 244, - 249, 249, 6, 1, 207, 208, 202, 202, - 202, 247, 202, 202, 210, 202, 244, 249, - 249, 6, 1, 207, 208, 202, 202, 202, - 247, 202, 202, 210, 202, 19, 250, 202, - 1, 207, 208, 202, 202, 202, 215, 202, - 251, 251, 202, 1, 207, 208, 202, 202, - 202, 215, 202, 252, 202, 202, 253, 207, - 208, 202, 207, 208, 202, 254, 202, 207, - 255, 202, 207, 256, 202, 207, 202, 252, - 202, 202, 202, 207, 208, 202, 257, 202, - 258, 259, 202, 1, 207, 208, 202, 202, - 4, 202, 3, 202, 251, 251, 202, 1, - 207, 208, 202, 251, 251, 202, 1, 207, - 208, 202, 257, 202, 251, 251, 202, 1, - 207, 208, 202, 257, 202, 258, 251, 202, - 1, 207, 208, 202, 202, 4, 202, 19, - 202, 260, 260, 6, 1, 207, 208, 202, - 202, 202, 215, 202, 261, 28, 262, 263, - 9, 1, 207, 208, 202, 202, 202, 215, - 202, 28, 262, 263, 9, 1, 207, 208, - 202, 202, 202, 215, 202, 262, 262, 9, - 1, 207, 208, 202, 202, 202, 215, 202, - 264, 25, 265, 266, 12, 1, 207, 208, - 202, 202, 202, 215, 202, 25, 265, 266, - 12, 1, 207, 208, 202, 202, 202, 215, - 202, 265, 265, 12, 1, 207, 208, 202, - 202, 202, 215, 202, 267, 22, 268, 269, - 15, 1, 207, 208, 202, 202, 202, 215, - 202, 22, 268, 269, 15, 1, 207, 208, - 202, 202, 202, 215, 202, 268, 268, 15, - 1, 207, 208, 202, 202, 202, 215, 202, - 270, 19, 251, 271, 202, 1, 207, 208, - 202, 202, 202, 215, 202, 19, 251, 271, - 202, 1, 207, 208, 202, 202, 202, 215, - 202, 251, 272, 202, 1, 207, 208, 202, - 202, 202, 215, 202, 19, 202, 251, 251, - 202, 1, 207, 208, 202, 202, 202, 215, - 202, 2, 3, 202, 202, 19, 250, 202, - 1, 207, 208, 202, 202, 202, 215, 202, - 2, 202, 244, 249, 249, 6, 1, 207, - 208, 202, 202, 202, 247, 202, 243, 244, - 249, 249, 6, 1, 207, 208, 202, 202, - 202, 247, 202, 202, 210, 202, 243, 244, - 245, 249, 6, 1, 207, 208, 202, 202, - 30, 247, 202, 202, 210, 202, 241, 202, - 273, 202, 260, 260, 6, 1, 207, 208, - 202, 202, 202, 215, 202, 241, 202, 241, - 202, 202, 202, 251, 251, 202, 1, 207, - 208, 202, 202, 202, 215, 202, 241, 202, - 241, 202, 202, 202, 251, 274, 202, 1, - 207, 208, 202, 202, 202, 215, 202, 241, - 202, 241, 202, 273, 202, 251, 251, 202, - 1, 207, 208, 202, 202, 202, 215, 202, - 241, 202, 241, 3, 202, 202, 19, 242, - 202, 1, 207, 208, 202, 202, 202, 215, - 202, 241, 202, 234, 235, 240, 240, 6, - 1, 207, 208, 202, 202, 202, 238, 202, - 202, 210, 202, 234, 235, 236, 240, 6, - 1, 207, 208, 202, 202, 32, 238, 202, - 202, 210, 202, 232, 202, 275, 202, 260, - 260, 6, 1, 207, 208, 202, 202, 202, - 215, 202, 232, 202, 232, 202, 202, 202, - 251, 251, 202, 1, 207, 208, 202, 202, - 202, 215, 202, 232, 202, 232, 202, 202, - 202, 251, 276, 202, 1, 207, 208, 202, - 202, 202, 215, 202, 232, 202, 232, 202, - 275, 202, 251, 251, 202, 1, 207, 208, - 202, 202, 202, 215, 202, 232, 202, 232, - 3, 202, 202, 19, 233, 202, 1, 207, - 208, 202, 202, 202, 215, 202, 232, 202, - 225, 226, 231, 231, 6, 1, 207, 208, - 202, 202, 202, 229, 202, 202, 210, 202, - 225, 226, 227, 231, 6, 1, 207, 208, - 202, 202, 34, 229, 202, 202, 210, 202, - 223, 202, 277, 202, 260, 260, 6, 1, - 207, 208, 202, 202, 202, 215, 202, 223, - 202, 223, 202, 202, 202, 251, 251, 202, - 1, 207, 208, 202, 202, 202, 215, 202, - 223, 202, 223, 202, 202, 202, 251, 278, - 202, 1, 207, 208, 202, 202, 202, 215, - 202, 223, 202, 223, 202, 277, 202, 251, - 251, 202, 1, 207, 208, 202, 202, 202, - 215, 202, 223, 202, 223, 3, 202, 202, - 19, 224, 202, 1, 207, 208, 202, 202, - 202, 215, 202, 223, 202, 216, 217, 222, - 222, 6, 1, 207, 208, 202, 202, 202, - 220, 202, 202, 210, 202, 216, 217, 218, - 222, 6, 1, 207, 208, 202, 202, 36, - 220, 202, 202, 210, 202, 213, 202, 279, - 202, 260, 260, 6, 1, 207, 208, 202, - 202, 202, 215, 202, 213, 202, 213, 202, - 202, 202, 251, 251, 202, 1, 207, 208, - 202, 202, 202, 215, 202, 213, 202, 213, - 202, 202, 202, 251, 280, 202, 1, 207, - 208, 202, 202, 202, 215, 202, 213, 202, - 213, 202, 279, 202, 251, 251, 202, 1, - 207, 208, 202, 202, 202, 215, 202, 213, - 202, 213, 3, 202, 202, 19, 214, 202, - 1, 207, 208, 202, 202, 202, 215, 202, - 213, 202, 203, 204, 212, 212, 6, 1, - 207, 208, 202, 202, 202, 209, 202, 202, - 210, 202, 203, 204, 205, 212, 6, 1, - 207, 208, 202, 202, 38, 209, 202, 202, - 210, 202, 282, 283, 284, 285, 45, 40, - 286, 287, 281, 281, 77, 288, 281, 281, - 289, 281, 290, 283, 291, 285, 45, 40, - 286, 287, 281, 281, 281, 288, 281, 281, - 289, 281, 283, 291, 285, 45, 40, 286, - 287, 281, 281, 281, 288, 281, 281, 289, - 281, 292, 281, 281, 281, 58, 293, 281, - 40, 286, 287, 281, 281, 281, 294, 281, - 292, 281, 295, 296, 297, 298, 45, 40, - 286, 287, 281, 281, 75, 299, 281, 281, - 289, 281, 300, 296, 301, 301, 45, 40, - 286, 287, 281, 281, 281, 299, 281, 281, - 289, 281, 296, 301, 301, 45, 40, 286, - 287, 281, 281, 281, 299, 281, 281, 289, - 281, 302, 281, 281, 281, 58, 303, 281, - 40, 286, 287, 281, 281, 281, 294, 281, - 302, 281, 304, 305, 306, 307, 45, 40, - 286, 287, 281, 281, 73, 308, 281, 281, - 289, 281, 309, 305, 310, 310, 45, 40, - 286, 287, 281, 281, 281, 308, 281, 281, - 289, 281, 305, 310, 310, 45, 40, 286, - 287, 281, 281, 281, 308, 281, 281, 289, - 281, 311, 281, 281, 281, 58, 312, 281, - 40, 286, 287, 281, 281, 281, 294, 281, - 311, 281, 313, 314, 315, 316, 45, 40, - 286, 287, 281, 281, 71, 317, 281, 281, - 289, 281, 318, 314, 319, 319, 45, 40, - 286, 287, 281, 281, 281, 317, 281, 281, - 289, 281, 314, 319, 319, 45, 40, 286, - 287, 281, 281, 281, 317, 281, 281, 289, - 281, 320, 281, 281, 281, 58, 321, 281, - 40, 286, 287, 281, 281, 281, 294, 281, - 320, 281, 322, 323, 324, 325, 45, 40, - 286, 287, 281, 281, 69, 326, 281, 281, - 289, 281, 327, 323, 328, 328, 45, 40, - 286, 287, 281, 281, 281, 326, 281, 281, - 289, 281, 323, 328, 328, 45, 40, 286, - 287, 281, 281, 281, 326, 281, 281, 289, - 281, 58, 329, 281, 40, 286, 287, 281, - 281, 281, 294, 281, 330, 330, 281, 40, - 286, 287, 281, 281, 281, 294, 281, 331, - 281, 281, 332, 286, 287, 281, 286, 287, - 281, 333, 281, 286, 334, 281, 286, 335, - 281, 286, 281, 331, 281, 281, 281, 286, - 287, 281, 336, 281, 337, 338, 281, 40, - 286, 287, 281, 281, 43, 281, 42, 281, - 330, 330, 281, 40, 286, 287, 281, 330, - 330, 281, 40, 286, 287, 281, 336, 281, - 330, 330, 281, 40, 286, 287, 281, 336, - 281, 337, 330, 281, 40, 286, 287, 281, - 281, 43, 281, 58, 281, 339, 339, 45, - 40, 286, 287, 281, 281, 281, 294, 281, - 340, 67, 341, 342, 48, 40, 286, 287, - 281, 281, 281, 294, 281, 67, 341, 342, - 48, 40, 286, 287, 281, 281, 281, 294, - 281, 341, 341, 48, 40, 286, 287, 281, - 281, 281, 294, 281, 343, 64, 344, 345, - 51, 40, 286, 287, 281, 281, 281, 294, - 281, 64, 344, 345, 51, 40, 286, 287, - 281, 281, 281, 294, 281, 344, 344, 51, - 40, 286, 287, 281, 281, 281, 294, 281, - 346, 61, 347, 348, 54, 40, 286, 287, - 281, 281, 281, 294, 281, 61, 347, 348, - 54, 40, 286, 287, 281, 281, 281, 294, - 281, 347, 347, 54, 40, 286, 287, 281, - 281, 281, 294, 281, 349, 58, 330, 350, - 281, 40, 286, 287, 281, 281, 281, 294, - 281, 58, 330, 350, 281, 40, 286, 287, - 281, 281, 281, 294, 281, 330, 351, 281, - 40, 286, 287, 281, 281, 281, 294, 281, - 58, 281, 330, 330, 281, 40, 286, 287, - 281, 281, 281, 294, 281, 41, 42, 281, - 281, 58, 329, 281, 40, 286, 287, 281, - 281, 281, 294, 281, 41, 281, 323, 328, - 328, 45, 40, 286, 287, 281, 281, 281, - 326, 281, 322, 323, 328, 328, 45, 40, - 286, 287, 281, 281, 281, 326, 281, 281, - 289, 281, 322, 323, 324, 328, 45, 40, - 286, 287, 281, 281, 69, 326, 281, 281, - 289, 281, 320, 281, 352, 281, 339, 339, - 45, 40, 286, 287, 281, 281, 281, 294, - 281, 320, 281, 320, 281, 281, 281, 330, - 330, 281, 40, 286, 287, 281, 281, 281, - 294, 281, 320, 281, 320, 281, 281, 281, - 330, 353, 281, 40, 286, 287, 281, 281, - 281, 294, 281, 320, 281, 320, 281, 352, - 281, 330, 330, 281, 40, 286, 287, 281, - 281, 281, 294, 281, 320, 281, 320, 42, - 281, 281, 58, 321, 281, 40, 286, 287, - 281, 281, 281, 294, 281, 320, 281, 313, - 314, 319, 319, 45, 40, 286, 287, 281, - 281, 281, 317, 281, 281, 289, 281, 313, - 314, 315, 319, 45, 40, 286, 287, 281, - 281, 71, 317, 281, 281, 289, 281, 311, - 281, 354, 281, 339, 339, 45, 40, 286, - 287, 281, 281, 281, 294, 281, 311, 281, - 311, 281, 281, 281, 330, 330, 281, 40, - 286, 287, 281, 281, 281, 294, 281, 311, - 281, 311, 281, 281, 281, 330, 355, 281, - 40, 286, 287, 281, 281, 281, 294, 281, - 311, 281, 311, 281, 354, 281, 330, 330, - 281, 40, 286, 287, 281, 281, 281, 294, - 281, 311, 281, 311, 42, 281, 281, 58, - 312, 281, 40, 286, 287, 281, 281, 281, - 294, 281, 311, 281, 304, 305, 310, 310, - 45, 40, 286, 287, 281, 281, 281, 308, - 281, 281, 289, 281, 304, 305, 306, 310, - 45, 40, 286, 287, 281, 281, 73, 308, - 281, 281, 289, 281, 302, 281, 356, 281, - 339, 339, 45, 40, 286, 287, 281, 281, - 281, 294, 281, 302, 281, 302, 281, 281, - 281, 330, 330, 281, 40, 286, 287, 281, - 281, 281, 294, 281, 302, 281, 302, 281, - 281, 281, 330, 357, 281, 40, 286, 287, - 281, 281, 281, 294, 281, 302, 281, 302, - 281, 356, 281, 330, 330, 281, 40, 286, - 287, 281, 281, 281, 294, 281, 302, 281, - 302, 42, 281, 281, 58, 303, 281, 40, - 286, 287, 281, 281, 281, 294, 281, 302, - 281, 295, 296, 301, 301, 45, 40, 286, - 287, 281, 281, 281, 299, 281, 281, 289, - 281, 295, 296, 297, 301, 45, 40, 286, - 287, 281, 281, 75, 299, 281, 281, 289, - 281, 292, 281, 358, 281, 339, 339, 45, - 40, 286, 287, 281, 281, 281, 294, 281, - 292, 281, 292, 281, 281, 281, 330, 330, - 281, 40, 286, 287, 281, 281, 281, 294, - 281, 292, 281, 292, 281, 281, 281, 330, - 359, 281, 40, 286, 287, 281, 281, 281, - 294, 281, 292, 281, 292, 281, 358, 281, - 330, 330, 281, 40, 286, 287, 281, 281, - 281, 294, 281, 292, 281, 76, 44, 44, - 45, 40, 281, 281, 281, 281, 281, 76, - 281, 292, 42, 281, 281, 58, 293, 281, - 40, 286, 287, 281, 281, 281, 294, 281, - 292, 281, 282, 283, 291, 285, 45, 40, - 286, 287, 281, 281, 281, 288, 281, 281, - 289, 281, 361, 191, 362, 362, 84, 79, - 194, 195, 360, 360, 360, 197, 360, 360, - 200, 360, 191, 362, 362, 84, 79, 194, - 195, 360, 360, 360, 197, 360, 360, 200, - 360, 363, 360, 360, 360, 98, 364, 360, - 79, 194, 195, 360, 360, 360, 365, 360, - 363, 360, 366, 367, 368, 369, 84, 79, - 194, 195, 360, 360, 115, 370, 360, 360, - 200, 360, 371, 367, 372, 372, 84, 79, - 194, 195, 360, 360, 360, 370, 360, 360, - 200, 360, 367, 372, 372, 84, 79, 194, - 195, 360, 360, 360, 370, 360, 360, 200, - 360, 373, 360, 360, 360, 98, 374, 360, - 79, 194, 195, 360, 360, 360, 365, 360, - 373, 360, 375, 376, 377, 378, 84, 79, - 194, 195, 360, 360, 113, 379, 360, 360, - 200, 360, 380, 376, 381, 381, 84, 79, - 194, 195, 360, 360, 360, 379, 360, 360, - 200, 360, 376, 381, 381, 84, 79, 194, - 195, 360, 360, 360, 379, 360, 360, 200, - 360, 382, 360, 360, 360, 98, 383, 360, - 79, 194, 195, 360, 360, 360, 365, 360, - 382, 360, 384, 385, 386, 387, 84, 79, - 194, 195, 360, 360, 111, 388, 360, 360, - 200, 360, 389, 385, 390, 390, 84, 79, - 194, 195, 360, 360, 360, 388, 360, 360, - 200, 360, 385, 390, 390, 84, 79, 194, - 195, 360, 360, 360, 388, 360, 360, 200, - 360, 391, 360, 360, 360, 98, 392, 360, - 79, 194, 195, 360, 360, 360, 365, 360, - 391, 360, 393, 394, 395, 396, 84, 79, - 194, 195, 360, 360, 109, 397, 360, 360, - 200, 360, 398, 394, 399, 399, 84, 79, - 194, 195, 360, 360, 360, 397, 360, 360, - 200, 360, 394, 399, 399, 84, 79, 194, - 195, 360, 360, 360, 397, 360, 360, 200, - 360, 98, 400, 360, 79, 194, 195, 360, - 360, 360, 365, 360, 401, 401, 360, 79, - 194, 195, 360, 360, 360, 365, 360, 402, - 360, 360, 403, 194, 195, 360, 194, 195, - 360, 404, 360, 194, 405, 360, 194, 406, - 360, 194, 360, 402, 360, 360, 360, 194, - 195, 360, 407, 360, 408, 409, 360, 79, - 194, 195, 360, 360, 82, 360, 81, 360, - 401, 401, 360, 79, 194, 195, 360, 401, - 401, 360, 79, 194, 195, 360, 407, 360, - 401, 401, 360, 79, 194, 195, 360, 407, - 360, 408, 401, 360, 79, 194, 195, 360, - 360, 82, 360, 98, 360, 410, 410, 84, - 79, 194, 195, 360, 360, 360, 365, 360, - 411, 107, 412, 413, 88, 79, 194, 195, - 360, 360, 360, 365, 360, 107, 412, 413, - 88, 79, 194, 195, 360, 360, 360, 365, - 360, 412, 412, 88, 79, 194, 195, 360, - 360, 360, 365, 360, 414, 104, 415, 416, - 91, 79, 194, 195, 360, 360, 360, 365, - 360, 104, 415, 416, 91, 79, 194, 195, - 360, 360, 360, 365, 360, 415, 415, 91, - 79, 194, 195, 360, 360, 360, 365, 360, - 417, 101, 418, 419, 94, 79, 194, 195, - 360, 360, 360, 365, 360, 101, 418, 419, - 94, 79, 194, 195, 360, 360, 360, 365, - 360, 418, 418, 94, 79, 194, 195, 360, - 360, 360, 365, 360, 420, 98, 401, 421, - 360, 79, 194, 195, 360, 360, 360, 365, - 360, 98, 401, 421, 360, 79, 194, 195, - 360, 360, 360, 365, 360, 401, 422, 360, - 79, 194, 195, 360, 360, 360, 365, 360, - 98, 360, 401, 401, 360, 79, 194, 195, - 360, 360, 360, 365, 360, 80, 81, 360, - 360, 98, 400, 360, 79, 194, 195, 360, - 360, 360, 365, 360, 80, 360, 394, 399, - 399, 84, 79, 194, 195, 360, 360, 360, - 397, 360, 393, 394, 399, 399, 84, 79, - 194, 195, 360, 360, 360, 397, 360, 360, - 200, 360, 393, 394, 395, 399, 84, 79, - 194, 195, 360, 360, 109, 397, 360, 360, - 200, 360, 391, 360, 423, 360, 410, 410, - 84, 79, 194, 195, 360, 360, 360, 365, - 360, 391, 360, 391, 360, 360, 360, 401, - 401, 360, 79, 194, 195, 360, 360, 360, - 365, 360, 391, 360, 391, 360, 360, 360, - 401, 424, 360, 79, 194, 195, 360, 360, - 360, 365, 360, 391, 360, 391, 360, 423, - 360, 401, 401, 360, 79, 194, 195, 360, - 360, 360, 365, 360, 391, 360, 391, 81, - 360, 360, 98, 392, 360, 79, 194, 195, - 360, 360, 360, 365, 360, 391, 360, 384, - 385, 390, 390, 84, 79, 194, 195, 360, - 360, 360, 388, 360, 360, 200, 360, 384, - 385, 386, 390, 84, 79, 194, 195, 360, - 360, 111, 388, 360, 360, 200, 360, 382, - 360, 425, 360, 410, 410, 84, 79, 194, - 195, 360, 360, 360, 365, 360, 382, 360, - 382, 360, 360, 360, 401, 401, 360, 79, - 194, 195, 360, 360, 360, 365, 360, 382, - 360, 382, 360, 360, 360, 401, 426, 360, - 79, 194, 195, 360, 360, 360, 365, 360, - 382, 360, 382, 360, 425, 360, 401, 401, - 360, 79, 194, 195, 360, 360, 360, 365, - 360, 382, 360, 382, 81, 360, 360, 98, - 383, 360, 79, 194, 195, 360, 360, 360, - 365, 360, 382, 360, 375, 376, 381, 381, - 84, 79, 194, 195, 360, 360, 360, 379, - 360, 360, 200, 360, 375, 376, 377, 381, - 84, 79, 194, 195, 360, 360, 113, 379, - 360, 360, 200, 360, 373, 360, 427, 360, - 410, 410, 84, 79, 194, 195, 360, 360, - 360, 365, 360, 373, 360, 373, 360, 360, - 360, 401, 401, 360, 79, 194, 195, 360, - 360, 360, 365, 360, 373, 360, 373, 360, - 360, 360, 401, 428, 360, 79, 194, 195, - 360, 360, 360, 365, 360, 373, 360, 373, - 360, 427, 360, 401, 401, 360, 79, 194, - 195, 360, 360, 360, 365, 360, 373, 360, - 373, 81, 360, 360, 98, 374, 360, 79, - 194, 195, 360, 360, 360, 365, 360, 373, - 360, 366, 367, 372, 372, 84, 79, 194, - 195, 360, 360, 360, 370, 360, 360, 200, - 360, 366, 367, 368, 372, 84, 79, 194, - 195, 360, 360, 115, 370, 360, 360, 200, - 360, 363, 360, 429, 360, 410, 410, 84, - 79, 194, 195, 360, 360, 360, 365, 360, - 363, 360, 363, 360, 360, 360, 401, 401, - 360, 79, 194, 195, 360, 360, 360, 365, - 360, 363, 360, 363, 360, 360, 360, 401, - 430, 360, 79, 194, 195, 360, 360, 360, - 365, 360, 363, 360, 363, 360, 429, 360, - 401, 401, 360, 79, 194, 195, 360, 360, - 360, 365, 360, 363, 360, 363, 81, 360, - 360, 98, 364, 360, 79, 194, 195, 360, - 360, 360, 365, 360, 363, 360, 116, 83, - 83, 84, 79, 431, 431, 431, 431, 156, - 116, 431, 190, 191, 362, 362, 84, 79, - 194, 195, 360, 360, 360, 197, 360, 360, - 200, 360, 116, 83, 83, 84, 79, 431, - 431, 431, 431, 431, 116, 431, 433, 434, - 435, 436, 123, 118, 437, 438, 432, 432, - 155, 439, 432, 432, 440, 432, 441, 434, - 436, 436, 123, 118, 437, 438, 432, 432, - 432, 439, 432, 432, 440, 432, 434, 436, - 436, 123, 118, 437, 438, 432, 432, 432, - 439, 432, 432, 440, 432, 442, 432, 432, - 432, 136, 443, 432, 118, 437, 438, 432, - 432, 432, 444, 432, 442, 432, 445, 446, - 447, 448, 123, 118, 437, 438, 432, 432, - 153, 449, 432, 432, 440, 432, 450, 446, - 451, 451, 123, 118, 437, 438, 432, 432, - 432, 449, 432, 432, 440, 432, 446, 451, - 451, 123, 118, 437, 438, 432, 432, 432, - 449, 432, 432, 440, 432, 452, 432, 432, - 432, 136, 453, 432, 118, 437, 438, 432, - 432, 432, 444, 432, 452, 432, 454, 455, - 456, 457, 123, 118, 437, 438, 432, 432, - 151, 458, 432, 432, 440, 432, 459, 455, - 460, 460, 123, 118, 437, 438, 432, 432, - 432, 458, 432, 432, 440, 432, 455, 460, - 460, 123, 118, 437, 438, 432, 432, 432, - 458, 432, 432, 440, 432, 461, 432, 432, - 432, 136, 462, 432, 118, 437, 438, 432, - 432, 432, 444, 432, 461, 432, 463, 464, - 465, 466, 123, 118, 437, 438, 432, 432, - 149, 467, 432, 432, 440, 432, 468, 464, - 469, 469, 123, 118, 437, 438, 432, 432, - 432, 467, 432, 432, 440, 432, 464, 469, - 469, 123, 118, 437, 438, 432, 432, 432, - 467, 432, 432, 440, 432, 470, 432, 432, - 432, 136, 471, 432, 118, 437, 438, 432, - 432, 432, 444, 432, 470, 432, 472, 473, - 474, 475, 123, 118, 437, 438, 432, 432, - 147, 476, 432, 432, 440, 432, 477, 473, - 478, 478, 123, 118, 437, 438, 432, 432, - 432, 476, 432, 432, 440, 432, 473, 478, - 478, 123, 118, 437, 438, 432, 432, 432, - 476, 432, 432, 440, 432, 136, 479, 432, - 118, 437, 438, 432, 432, 432, 444, 432, - 480, 480, 432, 118, 437, 438, 432, 432, - 432, 444, 432, 481, 432, 432, 482, 437, - 438, 432, 437, 438, 432, 483, 432, 437, - 484, 432, 437, 485, 432, 437, 432, 481, - 432, 432, 432, 437, 438, 432, 486, 432, - 487, 488, 432, 118, 437, 438, 432, 432, - 121, 432, 120, 432, 480, 480, 432, 118, - 437, 438, 432, 480, 480, 432, 118, 437, - 438, 432, 486, 432, 480, 480, 432, 118, - 437, 438, 432, 486, 432, 487, 480, 432, - 118, 437, 438, 432, 432, 121, 432, 136, - 432, 489, 489, 123, 118, 437, 438, 432, - 432, 432, 444, 432, 490, 145, 491, 492, - 126, 118, 437, 438, 432, 432, 432, 444, - 432, 145, 491, 492, 126, 118, 437, 438, - 432, 432, 432, 444, 432, 491, 491, 126, - 118, 437, 438, 432, 432, 432, 444, 432, - 493, 142, 494, 495, 129, 118, 437, 438, - 432, 432, 432, 444, 432, 142, 494, 495, - 129, 118, 437, 438, 432, 432, 432, 444, - 432, 494, 494, 129, 118, 437, 438, 432, - 432, 432, 444, 432, 496, 139, 497, 498, - 132, 118, 437, 438, 432, 432, 432, 444, - 432, 139, 497, 498, 132, 118, 437, 438, - 432, 432, 432, 444, 432, 497, 497, 132, - 118, 437, 438, 432, 432, 432, 444, 432, - 499, 136, 480, 500, 432, 118, 437, 438, - 432, 432, 432, 444, 432, 136, 480, 500, - 432, 118, 437, 438, 432, 432, 432, 444, - 432, 480, 501, 432, 118, 437, 438, 432, - 432, 432, 444, 432, 136, 432, 480, 480, - 432, 118, 437, 438, 432, 432, 432, 444, - 432, 119, 120, 432, 432, 136, 479, 432, - 118, 437, 438, 432, 432, 432, 444, 432, - 119, 432, 473, 478, 478, 123, 118, 437, - 438, 432, 432, 432, 476, 432, 472, 473, - 478, 478, 123, 118, 437, 438, 432, 432, - 432, 476, 432, 432, 440, 432, 472, 473, - 474, 478, 123, 118, 437, 438, 432, 432, - 147, 476, 432, 432, 440, 432, 470, 432, - 502, 432, 489, 489, 123, 118, 437, 438, - 432, 432, 432, 444, 432, 470, 432, 470, - 432, 432, 432, 480, 480, 432, 118, 437, - 438, 432, 432, 432, 444, 432, 470, 432, - 470, 432, 432, 432, 480, 503, 432, 118, - 437, 438, 432, 432, 432, 444, 432, 470, - 432, 470, 432, 502, 432, 480, 480, 432, - 118, 437, 438, 432, 432, 432, 444, 432, - 470, 432, 470, 120, 432, 432, 136, 471, - 432, 118, 437, 438, 432, 432, 432, 444, - 432, 470, 432, 463, 464, 469, 469, 123, - 118, 437, 438, 432, 432, 432, 467, 432, - 432, 440, 432, 463, 464, 465, 469, 123, - 118, 437, 438, 432, 432, 149, 467, 432, - 432, 440, 432, 461, 432, 504, 432, 489, - 489, 123, 118, 437, 438, 432, 432, 432, - 444, 432, 461, 432, 461, 432, 432, 432, - 480, 480, 432, 118, 437, 438, 432, 432, - 432, 444, 432, 461, 432, 461, 432, 432, - 432, 480, 505, 432, 118, 437, 438, 432, - 432, 432, 444, 432, 461, 432, 461, 432, - 504, 432, 480, 480, 432, 118, 437, 438, - 432, 432, 432, 444, 432, 461, 432, 461, - 120, 432, 432, 136, 462, 432, 118, 437, - 438, 432, 432, 432, 444, 432, 461, 432, - 454, 455, 460, 460, 123, 118, 437, 438, - 432, 432, 432, 458, 432, 432, 440, 432, - 454, 455, 456, 460, 123, 118, 437, 438, - 432, 432, 151, 458, 432, 432, 440, 432, - 452, 432, 506, 432, 489, 489, 123, 118, - 437, 438, 432, 432, 432, 444, 432, 452, - 432, 452, 432, 432, 432, 480, 480, 432, - 118, 437, 438, 432, 432, 432, 444, 432, - 452, 432, 452, 432, 432, 432, 480, 507, - 432, 118, 437, 438, 432, 432, 432, 444, - 432, 452, 432, 452, 432, 506, 432, 480, - 480, 432, 118, 437, 438, 432, 432, 432, - 444, 432, 452, 432, 452, 120, 432, 432, - 136, 453, 432, 118, 437, 438, 432, 432, - 432, 444, 432, 452, 432, 445, 446, 451, - 451, 123, 118, 437, 438, 432, 432, 432, - 449, 432, 432, 440, 432, 445, 446, 447, - 451, 123, 118, 437, 438, 432, 432, 153, - 449, 432, 432, 440, 432, 442, 432, 508, - 432, 489, 489, 123, 118, 437, 438, 432, - 432, 432, 444, 432, 442, 432, 442, 432, - 432, 432, 480, 480, 432, 118, 437, 438, - 432, 432, 432, 444, 432, 442, 432, 442, - 432, 432, 432, 480, 509, 432, 118, 437, - 438, 432, 432, 432, 444, 432, 442, 432, - 442, 432, 508, 432, 480, 480, 432, 118, - 437, 438, 432, 432, 432, 444, 432, 442, - 432, 442, 120, 432, 432, 136, 443, 432, - 118, 437, 438, 432, 432, 432, 444, 432, - 442, 432, 433, 434, 436, 436, 123, 118, - 437, 438, 432, 432, 432, 439, 432, 432, - 440, 432, 188, 189, 190, 191, 510, 362, - 84, 79, 194, 195, 196, 196, 156, 197, - 360, 188, 200, 360, 203, 511, 205, 206, - 6, 1, 207, 208, 202, 202, 38, 209, - 202, 202, 210, 202, 213, 189, 190, 191, - 512, 513, 84, 157, 514, 515, 202, 196, - 156, 516, 202, 213, 200, 202, 116, 517, - 517, 84, 157, 207, 208, 202, 202, 156, - 518, 202, 519, 202, 202, 520, 514, 515, - 202, 514, 515, 202, 254, 202, 514, 521, - 202, 514, 522, 202, 514, 202, 519, 202, - 202, 202, 514, 515, 202, 523, 3, 360, - 360, 401, 430, 360, 79, 194, 195, 360, - 360, 360, 365, 360, 523, 360, 524, 367, - 525, 526, 84, 157, 514, 515, 202, 202, - 158, 370, 202, 202, 200, 202, 527, 367, - 528, 528, 84, 157, 514, 515, 202, 202, - 202, 370, 202, 202, 200, 202, 367, 528, - 528, 84, 157, 514, 515, 202, 202, 202, - 370, 202, 202, 200, 202, 524, 367, 528, - 528, 84, 157, 514, 515, 202, 202, 202, - 370, 202, 202, 200, 202, 524, 367, 525, - 528, 84, 157, 514, 515, 202, 202, 158, - 370, 202, 202, 200, 202, 213, 202, 279, - 116, 529, 529, 160, 157, 207, 208, 202, - 202, 202, 518, 202, 213, 202, 530, 184, - 531, 532, 162, 157, 514, 515, 202, 202, - 202, 533, 202, 184, 531, 532, 162, 157, - 514, 515, 202, 202, 202, 533, 202, 531, - 531, 162, 157, 514, 515, 202, 202, 202, - 533, 202, 534, 181, 535, 536, 165, 157, - 514, 515, 202, 202, 202, 533, 202, 181, - 535, 536, 165, 157, 514, 515, 202, 202, - 202, 533, 202, 535, 535, 165, 157, 514, - 515, 202, 202, 202, 533, 202, 537, 178, - 538, 539, 168, 157, 514, 515, 202, 202, - 202, 533, 202, 178, 538, 539, 168, 157, - 514, 515, 202, 202, 202, 533, 202, 538, - 538, 168, 157, 514, 515, 202, 202, 202, - 533, 202, 540, 175, 541, 542, 202, 157, - 514, 515, 202, 202, 202, 533, 202, 175, - 541, 542, 202, 157, 514, 515, 202, 202, - 202, 533, 202, 541, 541, 202, 157, 514, - 515, 202, 202, 202, 533, 202, 543, 202, - 544, 545, 202, 157, 514, 515, 202, 202, - 172, 202, 171, 202, 541, 541, 202, 157, - 514, 515, 202, 541, 541, 202, 157, 514, - 515, 202, 543, 202, 541, 541, 202, 157, - 514, 515, 202, 543, 202, 544, 541, 202, - 157, 514, 515, 202, 202, 172, 202, 523, - 171, 360, 360, 98, 364, 360, 79, 194, - 195, 360, 360, 360, 365, 360, 523, 360, - 547, 546, 548, 548, 546, 186, 549, 550, - 546, 548, 548, 546, 186, 549, 550, 546, - 551, 546, 546, 552, 549, 550, 546, 549, - 550, 546, 553, 546, 549, 554, 546, 549, - 555, 546, 549, 546, 551, 546, 546, 546, - 549, 550, 546, 0 + 197, 198, 199, 200, 201, 202, 187, 204, + 205, 206, 207, 6, 1, 208, 209, 203, + 203, 38, 210, 203, 203, 211, 203, 212, + 205, 213, 213, 6, 1, 208, 209, 203, + 203, 203, 210, 203, 203, 211, 203, 205, + 213, 213, 6, 1, 208, 209, 203, 203, + 203, 210, 203, 203, 211, 203, 214, 203, + 203, 203, 19, 215, 203, 1, 208, 209, + 203, 203, 203, 216, 203, 214, 203, 217, + 218, 219, 220, 6, 1, 208, 209, 203, + 203, 36, 221, 203, 203, 211, 203, 222, + 218, 223, 223, 6, 1, 208, 209, 203, + 203, 203, 221, 203, 203, 211, 203, 218, + 223, 223, 6, 1, 208, 209, 203, 203, + 203, 221, 203, 203, 211, 203, 224, 203, + 203, 203, 19, 225, 203, 1, 208, 209, + 203, 203, 203, 216, 203, 224, 203, 226, + 227, 228, 229, 6, 1, 208, 209, 203, + 203, 34, 230, 203, 203, 211, 203, 231, + 227, 232, 232, 6, 1, 208, 209, 203, + 203, 203, 230, 203, 203, 211, 203, 227, + 232, 232, 6, 1, 208, 209, 203, 203, + 203, 230, 203, 203, 211, 203, 233, 203, + 203, 203, 19, 234, 203, 1, 208, 209, + 203, 203, 203, 216, 203, 233, 203, 235, + 236, 237, 238, 6, 1, 208, 209, 203, + 203, 32, 239, 203, 203, 211, 203, 240, + 236, 241, 241, 6, 1, 208, 209, 203, + 203, 203, 239, 203, 203, 211, 203, 236, + 241, 241, 6, 1, 208, 209, 203, 203, + 203, 239, 203, 203, 211, 203, 242, 203, + 203, 203, 19, 243, 203, 1, 208, 209, + 203, 203, 203, 216, 203, 242, 203, 244, + 245, 246, 247, 6, 1, 208, 209, 203, + 203, 30, 248, 203, 203, 211, 203, 249, + 245, 250, 250, 6, 1, 208, 209, 203, + 203, 203, 248, 203, 203, 211, 203, 245, + 250, 250, 6, 1, 208, 209, 203, 203, + 203, 248, 203, 203, 211, 203, 19, 251, + 203, 1, 208, 209, 203, 203, 203, 216, + 203, 252, 252, 203, 1, 208, 209, 203, + 203, 203, 216, 203, 253, 203, 203, 254, + 208, 209, 203, 208, 209, 203, 255, 203, + 208, 256, 203, 208, 257, 203, 208, 203, + 253, 203, 203, 203, 208, 209, 203, 258, + 203, 259, 260, 203, 1, 208, 209, 203, + 203, 4, 203, 3, 203, 252, 252, 203, + 1, 208, 209, 203, 252, 252, 203, 1, + 208, 209, 203, 258, 203, 252, 252, 203, + 1, 208, 209, 203, 258, 203, 259, 252, + 203, 1, 208, 209, 203, 203, 4, 203, + 19, 203, 261, 261, 6, 1, 208, 209, + 203, 203, 203, 216, 203, 262, 28, 263, + 264, 9, 1, 208, 209, 203, 203, 203, + 216, 203, 28, 263, 264, 9, 1, 208, + 209, 203, 203, 203, 216, 203, 263, 263, + 9, 1, 208, 209, 203, 203, 203, 216, + 203, 265, 25, 266, 267, 12, 1, 208, + 209, 203, 203, 203, 216, 203, 25, 266, + 267, 12, 1, 208, 209, 203, 203, 203, + 216, 203, 266, 266, 12, 1, 208, 209, + 203, 203, 203, 216, 203, 268, 22, 269, + 270, 15, 1, 208, 209, 203, 203, 203, + 216, 203, 22, 269, 270, 15, 1, 208, + 209, 203, 203, 203, 216, 203, 269, 269, + 15, 1, 208, 209, 203, 203, 203, 216, + 203, 271, 19, 252, 272, 203, 1, 208, + 209, 203, 203, 203, 216, 203, 19, 252, + 272, 203, 1, 208, 209, 203, 203, 203, + 216, 203, 252, 273, 203, 1, 208, 209, + 203, 203, 203, 216, 203, 19, 203, 252, + 252, 203, 1, 208, 209, 203, 203, 203, + 216, 203, 2, 3, 203, 203, 19, 251, + 203, 1, 208, 209, 203, 203, 203, 216, + 203, 2, 203, 245, 250, 250, 6, 1, + 208, 209, 203, 203, 203, 248, 203, 244, + 245, 250, 250, 6, 1, 208, 209, 203, + 203, 203, 248, 203, 203, 211, 203, 244, + 245, 246, 250, 6, 1, 208, 209, 203, + 203, 30, 248, 203, 203, 211, 203, 242, + 203, 274, 203, 261, 261, 6, 1, 208, + 209, 203, 203, 203, 216, 203, 242, 203, + 242, 203, 203, 203, 252, 252, 203, 1, + 208, 209, 203, 203, 203, 216, 203, 242, + 203, 242, 203, 203, 203, 252, 275, 203, + 1, 208, 209, 203, 203, 203, 216, 203, + 242, 203, 242, 203, 274, 203, 252, 252, + 203, 1, 208, 209, 203, 203, 203, 216, + 203, 242, 203, 242, 3, 203, 203, 19, + 243, 203, 1, 208, 209, 203, 203, 203, + 216, 203, 242, 203, 235, 236, 241, 241, + 6, 1, 208, 209, 203, 203, 203, 239, + 203, 203, 211, 203, 235, 236, 237, 241, + 6, 1, 208, 209, 203, 203, 32, 239, + 203, 203, 211, 203, 233, 203, 276, 203, + 261, 261, 6, 1, 208, 209, 203, 203, + 203, 216, 203, 233, 203, 233, 203, 203, + 203, 252, 252, 203, 1, 208, 209, 203, + 203, 203, 216, 203, 233, 203, 233, 203, + 203, 203, 252, 277, 203, 1, 208, 209, + 203, 203, 203, 216, 203, 233, 203, 233, + 203, 276, 203, 252, 252, 203, 1, 208, + 209, 203, 203, 203, 216, 203, 233, 203, + 233, 3, 203, 203, 19, 234, 203, 1, + 208, 209, 203, 203, 203, 216, 203, 233, + 203, 226, 227, 232, 232, 6, 1, 208, + 209, 203, 203, 203, 230, 203, 203, 211, + 203, 226, 227, 228, 232, 6, 1, 208, + 209, 203, 203, 34, 230, 203, 203, 211, + 203, 224, 203, 278, 203, 261, 261, 6, + 1, 208, 209, 203, 203, 203, 216, 203, + 224, 203, 224, 203, 203, 203, 252, 252, + 203, 1, 208, 209, 203, 203, 203, 216, + 203, 224, 203, 224, 203, 203, 203, 252, + 279, 203, 1, 208, 209, 203, 203, 203, + 216, 203, 224, 203, 224, 203, 278, 203, + 252, 252, 203, 1, 208, 209, 203, 203, + 203, 216, 203, 224, 203, 224, 3, 203, + 203, 19, 225, 203, 1, 208, 209, 203, + 203, 203, 216, 203, 224, 203, 217, 218, + 223, 223, 6, 1, 208, 209, 203, 203, + 203, 221, 203, 203, 211, 203, 217, 218, + 219, 223, 6, 1, 208, 209, 203, 203, + 36, 221, 203, 203, 211, 203, 214, 203, + 280, 203, 261, 261, 6, 1, 208, 209, + 203, 203, 203, 216, 203, 214, 203, 214, + 203, 203, 203, 252, 252, 203, 1, 208, + 209, 203, 203, 203, 216, 203, 214, 203, + 214, 203, 203, 203, 252, 281, 203, 1, + 208, 209, 203, 203, 203, 216, 203, 214, + 203, 214, 203, 280, 203, 252, 252, 203, + 1, 208, 209, 203, 203, 203, 216, 203, + 214, 203, 214, 3, 203, 203, 19, 215, + 203, 1, 208, 209, 203, 203, 203, 216, + 203, 214, 203, 204, 205, 213, 213, 6, + 1, 208, 209, 203, 203, 203, 210, 203, + 203, 211, 203, 204, 205, 206, 213, 6, + 1, 208, 209, 203, 203, 38, 210, 203, + 203, 211, 203, 283, 284, 285, 286, 45, + 40, 287, 288, 282, 282, 77, 289, 282, + 282, 290, 282, 291, 284, 292, 286, 45, + 40, 287, 288, 282, 282, 282, 289, 282, + 282, 290, 282, 284, 292, 286, 45, 40, + 287, 288, 282, 282, 282, 289, 282, 282, + 290, 282, 293, 282, 282, 282, 58, 294, + 282, 40, 287, 288, 282, 282, 282, 295, + 282, 293, 282, 296, 297, 298, 299, 45, + 40, 287, 288, 282, 282, 75, 300, 282, + 282, 290, 282, 301, 297, 302, 302, 45, + 40, 287, 288, 282, 282, 282, 300, 282, + 282, 290, 282, 297, 302, 302, 45, 40, + 287, 288, 282, 282, 282, 300, 282, 282, + 290, 282, 303, 282, 282, 282, 58, 304, + 282, 40, 287, 288, 282, 282, 282, 295, + 282, 303, 282, 305, 306, 307, 308, 45, + 40, 287, 288, 282, 282, 73, 309, 282, + 282, 290, 282, 310, 306, 311, 311, 45, + 40, 287, 288, 282, 282, 282, 309, 282, + 282, 290, 282, 306, 311, 311, 45, 40, + 287, 288, 282, 282, 282, 309, 282, 282, + 290, 282, 312, 282, 282, 282, 58, 313, + 282, 40, 287, 288, 282, 282, 282, 295, + 282, 312, 282, 314, 315, 316, 317, 45, + 40, 287, 288, 282, 282, 71, 318, 282, + 282, 290, 282, 319, 315, 320, 320, 45, + 40, 287, 288, 282, 282, 282, 318, 282, + 282, 290, 282, 315, 320, 320, 45, 40, + 287, 288, 282, 282, 282, 318, 282, 282, + 290, 282, 321, 282, 282, 282, 58, 322, + 282, 40, 287, 288, 282, 282, 282, 295, + 282, 321, 282, 323, 324, 325, 326, 45, + 40, 287, 288, 282, 282, 69, 327, 282, + 282, 290, 282, 328, 324, 329, 329, 45, + 40, 287, 288, 282, 282, 282, 327, 282, + 282, 290, 282, 324, 329, 329, 45, 40, + 287, 288, 282, 282, 282, 327, 282, 282, + 290, 282, 58, 330, 282, 40, 287, 288, + 282, 282, 282, 295, 282, 331, 331, 282, + 40, 287, 288, 282, 282, 282, 295, 282, + 332, 282, 282, 333, 287, 288, 282, 287, + 288, 282, 334, 282, 287, 335, 282, 287, + 336, 282, 287, 282, 332, 282, 282, 282, + 287, 288, 282, 337, 282, 338, 339, 282, + 40, 287, 288, 282, 282, 43, 282, 42, + 282, 331, 331, 282, 40, 287, 288, 282, + 331, 331, 282, 40, 287, 288, 282, 337, + 282, 331, 331, 282, 40, 287, 288, 282, + 337, 282, 338, 331, 282, 40, 287, 288, + 282, 282, 43, 282, 58, 282, 340, 340, + 45, 40, 287, 288, 282, 282, 282, 295, + 282, 341, 67, 342, 343, 48, 40, 287, + 288, 282, 282, 282, 295, 282, 67, 342, + 343, 48, 40, 287, 288, 282, 282, 282, + 295, 282, 342, 342, 48, 40, 287, 288, + 282, 282, 282, 295, 282, 344, 64, 345, + 346, 51, 40, 287, 288, 282, 282, 282, + 295, 282, 64, 345, 346, 51, 40, 287, + 288, 282, 282, 282, 295, 282, 345, 345, + 51, 40, 287, 288, 282, 282, 282, 295, + 282, 347, 61, 348, 349, 54, 40, 287, + 288, 282, 282, 282, 295, 282, 61, 348, + 349, 54, 40, 287, 288, 282, 282, 282, + 295, 282, 348, 348, 54, 40, 287, 288, + 282, 282, 282, 295, 282, 350, 58, 331, + 351, 282, 40, 287, 288, 282, 282, 282, + 295, 282, 58, 331, 351, 282, 40, 287, + 288, 282, 282, 282, 295, 282, 331, 352, + 282, 40, 287, 288, 282, 282, 282, 295, + 282, 58, 282, 331, 331, 282, 40, 287, + 288, 282, 282, 282, 295, 282, 41, 42, + 282, 282, 58, 330, 282, 40, 287, 288, + 282, 282, 282, 295, 282, 41, 282, 324, + 329, 329, 45, 40, 287, 288, 282, 282, + 282, 327, 282, 323, 324, 329, 329, 45, + 40, 287, 288, 282, 282, 282, 327, 282, + 282, 290, 282, 323, 324, 325, 329, 45, + 40, 287, 288, 282, 282, 69, 327, 282, + 282, 290, 282, 321, 282, 353, 282, 340, + 340, 45, 40, 287, 288, 282, 282, 282, + 295, 282, 321, 282, 321, 282, 282, 282, + 331, 331, 282, 40, 287, 288, 282, 282, + 282, 295, 282, 321, 282, 321, 282, 282, + 282, 331, 354, 282, 40, 287, 288, 282, + 282, 282, 295, 282, 321, 282, 321, 282, + 353, 282, 331, 331, 282, 40, 287, 288, + 282, 282, 282, 295, 282, 321, 282, 321, + 42, 282, 282, 58, 322, 282, 40, 287, + 288, 282, 282, 282, 295, 282, 321, 282, + 314, 315, 320, 320, 45, 40, 287, 288, + 282, 282, 282, 318, 282, 282, 290, 282, + 314, 315, 316, 320, 45, 40, 287, 288, + 282, 282, 71, 318, 282, 282, 290, 282, + 312, 282, 355, 282, 340, 340, 45, 40, + 287, 288, 282, 282, 282, 295, 282, 312, + 282, 312, 282, 282, 282, 331, 331, 282, + 40, 287, 288, 282, 282, 282, 295, 282, + 312, 282, 312, 282, 282, 282, 331, 356, + 282, 40, 287, 288, 282, 282, 282, 295, + 282, 312, 282, 312, 282, 355, 282, 331, + 331, 282, 40, 287, 288, 282, 282, 282, + 295, 282, 312, 282, 312, 42, 282, 282, + 58, 313, 282, 40, 287, 288, 282, 282, + 282, 295, 282, 312, 282, 305, 306, 311, + 311, 45, 40, 287, 288, 282, 282, 282, + 309, 282, 282, 290, 282, 305, 306, 307, + 311, 45, 40, 287, 288, 282, 282, 73, + 309, 282, 282, 290, 282, 303, 282, 357, + 282, 340, 340, 45, 40, 287, 288, 282, + 282, 282, 295, 282, 303, 282, 303, 282, + 282, 282, 331, 331, 282, 40, 287, 288, + 282, 282, 282, 295, 282, 303, 282, 303, + 282, 282, 282, 331, 358, 282, 40, 287, + 288, 282, 282, 282, 295, 282, 303, 282, + 303, 282, 357, 282, 331, 331, 282, 40, + 287, 288, 282, 282, 282, 295, 282, 303, + 282, 303, 42, 282, 282, 58, 304, 282, + 40, 287, 288, 282, 282, 282, 295, 282, + 303, 282, 296, 297, 302, 302, 45, 40, + 287, 288, 282, 282, 282, 300, 282, 282, + 290, 282, 296, 297, 298, 302, 45, 40, + 287, 288, 282, 282, 75, 300, 282, 282, + 290, 282, 293, 282, 359, 282, 340, 340, + 45, 40, 287, 288, 282, 282, 282, 295, + 282, 293, 282, 293, 282, 282, 282, 331, + 331, 282, 40, 287, 288, 282, 282, 282, + 295, 282, 293, 282, 293, 282, 282, 282, + 331, 360, 282, 40, 287, 288, 282, 282, + 282, 295, 282, 293, 282, 293, 282, 359, + 282, 331, 331, 282, 40, 287, 288, 282, + 282, 282, 295, 282, 293, 282, 76, 44, + 44, 45, 40, 282, 282, 282, 282, 282, + 76, 282, 293, 42, 282, 282, 58, 294, + 282, 40, 287, 288, 282, 282, 282, 295, + 282, 293, 282, 283, 284, 292, 286, 45, + 40, 287, 288, 282, 282, 282, 289, 282, + 282, 290, 282, 362, 191, 363, 363, 84, + 79, 194, 195, 361, 361, 361, 197, 361, + 361, 200, 361, 191, 363, 363, 84, 79, + 194, 195, 361, 361, 361, 197, 361, 361, + 200, 361, 364, 361, 361, 361, 98, 365, + 361, 79, 194, 195, 361, 361, 361, 366, + 361, 364, 361, 367, 368, 369, 370, 84, + 79, 194, 195, 361, 361, 115, 371, 361, + 361, 200, 361, 372, 368, 373, 373, 84, + 79, 194, 195, 361, 361, 361, 371, 361, + 361, 200, 361, 368, 373, 373, 84, 79, + 194, 195, 361, 361, 361, 371, 361, 361, + 200, 361, 374, 361, 361, 361, 98, 375, + 361, 79, 194, 195, 361, 361, 361, 366, + 361, 374, 361, 376, 377, 378, 379, 84, + 79, 194, 195, 361, 361, 113, 380, 361, + 361, 200, 361, 381, 377, 382, 382, 84, + 79, 194, 195, 361, 361, 361, 380, 361, + 361, 200, 361, 377, 382, 382, 84, 79, + 194, 195, 361, 361, 361, 380, 361, 361, + 200, 361, 383, 361, 361, 361, 98, 384, + 361, 79, 194, 195, 361, 361, 361, 366, + 361, 383, 361, 385, 386, 387, 388, 84, + 79, 194, 195, 361, 361, 111, 389, 361, + 361, 200, 361, 390, 386, 391, 391, 84, + 79, 194, 195, 361, 361, 361, 389, 361, + 361, 200, 361, 386, 391, 391, 84, 79, + 194, 195, 361, 361, 361, 389, 361, 361, + 200, 361, 392, 361, 361, 361, 98, 393, + 361, 79, 194, 195, 361, 361, 361, 366, + 361, 392, 361, 394, 395, 396, 397, 84, + 79, 194, 195, 361, 361, 109, 398, 361, + 361, 200, 361, 399, 395, 400, 400, 84, + 79, 194, 195, 361, 361, 361, 398, 361, + 361, 200, 361, 395, 400, 400, 84, 79, + 194, 195, 361, 361, 361, 398, 361, 361, + 200, 361, 98, 401, 361, 79, 194, 195, + 361, 361, 361, 366, 361, 402, 402, 361, + 79, 194, 195, 361, 361, 361, 366, 361, + 403, 361, 361, 404, 194, 195, 361, 194, + 195, 361, 405, 361, 194, 406, 361, 194, + 407, 361, 194, 361, 403, 361, 361, 361, + 194, 195, 361, 408, 361, 409, 410, 361, + 79, 194, 195, 361, 361, 82, 361, 81, + 361, 402, 402, 361, 79, 194, 195, 361, + 402, 402, 361, 79, 194, 195, 361, 408, + 361, 402, 402, 361, 79, 194, 195, 361, + 408, 361, 409, 402, 361, 79, 194, 195, + 361, 361, 82, 361, 98, 361, 411, 411, + 84, 79, 194, 195, 361, 361, 361, 366, + 361, 412, 107, 413, 414, 88, 79, 194, + 195, 361, 361, 361, 366, 361, 107, 413, + 414, 88, 79, 194, 195, 361, 361, 361, + 366, 361, 413, 413, 88, 79, 194, 195, + 361, 361, 361, 366, 361, 415, 104, 416, + 417, 91, 79, 194, 195, 361, 361, 361, + 366, 361, 104, 416, 417, 91, 79, 194, + 195, 361, 361, 361, 366, 361, 416, 416, + 91, 79, 194, 195, 361, 361, 361, 366, + 361, 418, 101, 419, 420, 94, 79, 194, + 195, 361, 361, 361, 366, 361, 101, 419, + 420, 94, 79, 194, 195, 361, 361, 361, + 366, 361, 419, 419, 94, 79, 194, 195, + 361, 361, 361, 366, 361, 421, 98, 402, + 422, 361, 79, 194, 195, 361, 361, 361, + 366, 361, 98, 402, 422, 361, 79, 194, + 195, 361, 361, 361, 366, 361, 402, 423, + 361, 79, 194, 195, 361, 361, 361, 366, + 361, 98, 361, 402, 402, 361, 79, 194, + 195, 361, 361, 361, 366, 361, 80, 81, + 361, 361, 98, 401, 361, 79, 194, 195, + 361, 361, 361, 366, 361, 80, 361, 395, + 400, 400, 84, 79, 194, 195, 361, 361, + 361, 398, 361, 394, 395, 400, 400, 84, + 79, 194, 195, 361, 361, 361, 398, 361, + 361, 200, 361, 394, 395, 396, 400, 84, + 79, 194, 195, 361, 361, 109, 398, 361, + 361, 200, 361, 392, 361, 424, 361, 411, + 411, 84, 79, 194, 195, 361, 361, 361, + 366, 361, 392, 361, 392, 361, 361, 361, + 402, 402, 361, 79, 194, 195, 361, 361, + 361, 366, 361, 392, 361, 392, 361, 361, + 361, 402, 425, 361, 79, 194, 195, 361, + 361, 361, 366, 361, 392, 361, 392, 361, + 424, 361, 402, 402, 361, 79, 194, 195, + 361, 361, 361, 366, 361, 392, 361, 392, + 81, 361, 361, 98, 393, 361, 79, 194, + 195, 361, 361, 361, 366, 361, 392, 361, + 385, 386, 391, 391, 84, 79, 194, 195, + 361, 361, 361, 389, 361, 361, 200, 361, + 385, 386, 387, 391, 84, 79, 194, 195, + 361, 361, 111, 389, 361, 361, 200, 361, + 383, 361, 426, 361, 411, 411, 84, 79, + 194, 195, 361, 361, 361, 366, 361, 383, + 361, 383, 361, 361, 361, 402, 402, 361, + 79, 194, 195, 361, 361, 361, 366, 361, + 383, 361, 383, 361, 361, 361, 402, 427, + 361, 79, 194, 195, 361, 361, 361, 366, + 361, 383, 361, 383, 361, 426, 361, 402, + 402, 361, 79, 194, 195, 361, 361, 361, + 366, 361, 383, 361, 383, 81, 361, 361, + 98, 384, 361, 79, 194, 195, 361, 361, + 361, 366, 361, 383, 361, 376, 377, 382, + 382, 84, 79, 194, 195, 361, 361, 361, + 380, 361, 361, 200, 361, 376, 377, 378, + 382, 84, 79, 194, 195, 361, 361, 113, + 380, 361, 361, 200, 361, 374, 361, 428, + 361, 411, 411, 84, 79, 194, 195, 361, + 361, 361, 366, 361, 374, 361, 374, 361, + 361, 361, 402, 402, 361, 79, 194, 195, + 361, 361, 361, 366, 361, 374, 361, 374, + 361, 361, 361, 402, 429, 361, 79, 194, + 195, 361, 361, 361, 366, 361, 374, 361, + 374, 361, 428, 361, 402, 402, 361, 79, + 194, 195, 361, 361, 361, 366, 361, 374, + 361, 374, 81, 361, 361, 98, 375, 361, + 79, 194, 195, 361, 361, 361, 366, 361, + 374, 361, 367, 368, 373, 373, 84, 79, + 194, 195, 361, 361, 361, 371, 361, 361, + 200, 361, 367, 368, 369, 373, 84, 79, + 194, 195, 361, 361, 115, 371, 361, 361, + 200, 361, 364, 361, 430, 361, 411, 411, + 84, 79, 194, 195, 361, 361, 361, 366, + 361, 364, 361, 364, 361, 361, 361, 402, + 402, 361, 79, 194, 195, 361, 361, 361, + 366, 361, 364, 361, 364, 361, 361, 361, + 402, 431, 361, 79, 194, 195, 361, 361, + 361, 366, 361, 364, 361, 364, 361, 430, + 361, 402, 402, 361, 79, 194, 195, 361, + 361, 361, 366, 361, 364, 361, 364, 81, + 361, 361, 98, 365, 361, 79, 194, 195, + 361, 361, 361, 366, 361, 364, 361, 116, + 83, 83, 84, 79, 432, 432, 432, 432, + 156, 116, 432, 190, 191, 363, 363, 84, + 79, 194, 195, 361, 361, 361, 197, 361, + 361, 200, 361, 116, 83, 83, 84, 79, + 432, 432, 432, 432, 432, 116, 432, 434, + 435, 436, 437, 123, 118, 438, 439, 433, + 433, 155, 440, 433, 433, 441, 433, 442, + 435, 437, 437, 123, 118, 438, 439, 433, + 433, 433, 440, 433, 433, 441, 433, 435, + 437, 437, 123, 118, 438, 439, 433, 433, + 433, 440, 433, 433, 441, 433, 443, 433, + 433, 433, 136, 444, 433, 118, 438, 439, + 433, 433, 433, 445, 433, 443, 433, 446, + 447, 448, 449, 123, 118, 438, 439, 433, + 433, 153, 450, 433, 433, 441, 433, 451, + 447, 452, 452, 123, 118, 438, 439, 433, + 433, 433, 450, 433, 433, 441, 433, 447, + 452, 452, 123, 118, 438, 439, 433, 433, + 433, 450, 433, 433, 441, 433, 453, 433, + 433, 433, 136, 454, 433, 118, 438, 439, + 433, 433, 433, 445, 433, 453, 433, 455, + 456, 457, 458, 123, 118, 438, 439, 433, + 433, 151, 459, 433, 433, 441, 433, 460, + 456, 461, 461, 123, 118, 438, 439, 433, + 433, 433, 459, 433, 433, 441, 433, 456, + 461, 461, 123, 118, 438, 439, 433, 433, + 433, 459, 433, 433, 441, 433, 462, 433, + 433, 433, 136, 463, 433, 118, 438, 439, + 433, 433, 433, 445, 433, 462, 433, 464, + 465, 466, 467, 123, 118, 438, 439, 433, + 433, 149, 468, 433, 433, 441, 433, 469, + 465, 470, 470, 123, 118, 438, 439, 433, + 433, 433, 468, 433, 433, 441, 433, 465, + 470, 470, 123, 118, 438, 439, 433, 433, + 433, 468, 433, 433, 441, 433, 471, 433, + 433, 433, 136, 472, 433, 118, 438, 439, + 433, 433, 433, 445, 433, 471, 433, 473, + 474, 475, 476, 123, 118, 438, 439, 433, + 433, 147, 477, 433, 433, 441, 433, 478, + 474, 479, 479, 123, 118, 438, 439, 433, + 433, 433, 477, 433, 433, 441, 433, 474, + 479, 479, 123, 118, 438, 439, 433, 433, + 433, 477, 433, 433, 441, 433, 136, 480, + 433, 118, 438, 439, 433, 433, 433, 445, + 433, 481, 481, 433, 118, 438, 439, 433, + 433, 433, 445, 433, 482, 433, 433, 483, + 438, 439, 433, 438, 439, 433, 484, 433, + 438, 485, 433, 438, 486, 433, 438, 433, + 482, 433, 433, 433, 438, 439, 433, 487, + 433, 488, 489, 433, 118, 438, 439, 433, + 433, 121, 433, 120, 433, 481, 481, 433, + 118, 438, 439, 433, 481, 481, 433, 118, + 438, 439, 433, 487, 433, 481, 481, 433, + 118, 438, 439, 433, 487, 433, 488, 481, + 433, 118, 438, 439, 433, 433, 121, 433, + 136, 433, 490, 490, 123, 118, 438, 439, + 433, 433, 433, 445, 433, 491, 145, 492, + 493, 126, 118, 438, 439, 433, 433, 433, + 445, 433, 145, 492, 493, 126, 118, 438, + 439, 433, 433, 433, 445, 433, 492, 492, + 126, 118, 438, 439, 433, 433, 433, 445, + 433, 494, 142, 495, 496, 129, 118, 438, + 439, 433, 433, 433, 445, 433, 142, 495, + 496, 129, 118, 438, 439, 433, 433, 433, + 445, 433, 495, 495, 129, 118, 438, 439, + 433, 433, 433, 445, 433, 497, 139, 498, + 499, 132, 118, 438, 439, 433, 433, 433, + 445, 433, 139, 498, 499, 132, 118, 438, + 439, 433, 433, 433, 445, 433, 498, 498, + 132, 118, 438, 439, 433, 433, 433, 445, + 433, 500, 136, 481, 501, 433, 118, 438, + 439, 433, 433, 433, 445, 433, 136, 481, + 501, 433, 118, 438, 439, 433, 433, 433, + 445, 433, 481, 502, 433, 118, 438, 439, + 433, 433, 433, 445, 433, 136, 433, 481, + 481, 433, 118, 438, 439, 433, 433, 433, + 445, 433, 119, 120, 433, 433, 136, 480, + 433, 118, 438, 439, 433, 433, 433, 445, + 433, 119, 433, 474, 479, 479, 123, 118, + 438, 439, 433, 433, 433, 477, 433, 473, + 474, 479, 479, 123, 118, 438, 439, 433, + 433, 433, 477, 433, 433, 441, 433, 473, + 474, 475, 479, 123, 118, 438, 439, 433, + 433, 147, 477, 433, 433, 441, 433, 471, + 433, 503, 433, 490, 490, 123, 118, 438, + 439, 433, 433, 433, 445, 433, 471, 433, + 471, 433, 433, 433, 481, 481, 433, 118, + 438, 439, 433, 433, 433, 445, 433, 471, + 433, 471, 433, 433, 433, 481, 504, 433, + 118, 438, 439, 433, 433, 433, 445, 433, + 471, 433, 471, 433, 503, 433, 481, 481, + 433, 118, 438, 439, 433, 433, 433, 445, + 433, 471, 433, 471, 120, 433, 433, 136, + 472, 433, 118, 438, 439, 433, 433, 433, + 445, 433, 471, 433, 464, 465, 470, 470, + 123, 118, 438, 439, 433, 433, 433, 468, + 433, 433, 441, 433, 464, 465, 466, 470, + 123, 118, 438, 439, 433, 433, 149, 468, + 433, 433, 441, 433, 462, 433, 505, 433, + 490, 490, 123, 118, 438, 439, 433, 433, + 433, 445, 433, 462, 433, 462, 433, 433, + 433, 481, 481, 433, 118, 438, 439, 433, + 433, 433, 445, 433, 462, 433, 462, 433, + 433, 433, 481, 506, 433, 118, 438, 439, + 433, 433, 433, 445, 433, 462, 433, 462, + 433, 505, 433, 481, 481, 433, 118, 438, + 439, 433, 433, 433, 445, 433, 462, 433, + 462, 120, 433, 433, 136, 463, 433, 118, + 438, 439, 433, 433, 433, 445, 433, 462, + 433, 455, 456, 461, 461, 123, 118, 438, + 439, 433, 433, 433, 459, 433, 433, 441, + 433, 455, 456, 457, 461, 123, 118, 438, + 439, 433, 433, 151, 459, 433, 433, 441, + 433, 453, 433, 507, 433, 490, 490, 123, + 118, 438, 439, 433, 433, 433, 445, 433, + 453, 433, 453, 433, 433, 433, 481, 481, + 433, 118, 438, 439, 433, 433, 433, 445, + 433, 453, 433, 453, 433, 433, 433, 481, + 508, 433, 118, 438, 439, 433, 433, 433, + 445, 433, 453, 433, 453, 433, 507, 433, + 481, 481, 433, 118, 438, 439, 433, 433, + 433, 445, 433, 453, 433, 453, 120, 433, + 433, 136, 454, 433, 118, 438, 439, 433, + 433, 433, 445, 433, 453, 433, 446, 447, + 452, 452, 123, 118, 438, 439, 433, 433, + 433, 450, 433, 433, 441, 433, 446, 447, + 448, 452, 123, 118, 438, 439, 433, 433, + 153, 450, 433, 433, 441, 433, 443, 433, + 509, 433, 490, 490, 123, 118, 438, 439, + 433, 433, 433, 445, 433, 443, 433, 443, + 433, 433, 433, 481, 481, 433, 118, 438, + 439, 433, 433, 433, 445, 433, 443, 433, + 443, 433, 433, 433, 481, 510, 433, 118, + 438, 439, 433, 433, 433, 445, 433, 443, + 433, 443, 433, 509, 433, 481, 481, 433, + 118, 438, 439, 433, 433, 433, 445, 433, + 443, 433, 443, 120, 433, 433, 136, 444, + 433, 118, 438, 439, 433, 433, 433, 445, + 433, 443, 433, 434, 435, 437, 437, 123, + 118, 438, 439, 433, 433, 433, 440, 433, + 433, 441, 433, 188, 189, 190, 191, 511, + 363, 84, 79, 194, 195, 196, 196, 156, + 197, 361, 188, 200, 361, 204, 512, 206, + 207, 6, 1, 208, 209, 203, 203, 38, + 210, 203, 203, 211, 203, 214, 189, 190, + 191, 513, 514, 84, 157, 515, 516, 203, + 196, 156, 517, 203, 214, 200, 203, 116, + 518, 518, 84, 157, 208, 209, 203, 203, + 156, 519, 203, 520, 203, 203, 521, 515, + 516, 203, 515, 516, 203, 255, 203, 515, + 522, 203, 515, 523, 203, 515, 203, 520, + 203, 203, 203, 515, 516, 203, 524, 3, + 361, 361, 402, 431, 361, 79, 194, 195, + 361, 361, 361, 366, 361, 524, 361, 525, + 368, 526, 527, 84, 157, 515, 516, 203, + 203, 158, 371, 203, 203, 200, 203, 528, + 368, 529, 529, 84, 157, 515, 516, 203, + 203, 203, 371, 203, 203, 200, 203, 368, + 529, 529, 84, 157, 515, 516, 203, 203, + 203, 371, 203, 203, 200, 203, 525, 368, + 529, 529, 84, 157, 515, 516, 203, 203, + 203, 371, 203, 203, 200, 203, 525, 368, + 526, 529, 84, 157, 515, 516, 203, 203, + 158, 371, 203, 203, 200, 203, 214, 203, + 280, 116, 530, 530, 160, 157, 208, 209, + 203, 203, 203, 519, 203, 214, 203, 531, + 184, 532, 533, 162, 157, 515, 516, 203, + 203, 203, 534, 203, 184, 532, 533, 162, + 157, 515, 516, 203, 203, 203, 534, 203, + 532, 532, 162, 157, 515, 516, 203, 203, + 203, 534, 203, 535, 181, 536, 537, 165, + 157, 515, 516, 203, 203, 203, 534, 203, + 181, 536, 537, 165, 157, 515, 516, 203, + 203, 203, 534, 203, 536, 536, 165, 157, + 515, 516, 203, 203, 203, 534, 203, 538, + 178, 539, 540, 168, 157, 515, 516, 203, + 203, 203, 534, 203, 178, 539, 540, 168, + 157, 515, 516, 203, 203, 203, 534, 203, + 539, 539, 168, 157, 515, 516, 203, 203, + 203, 534, 203, 541, 175, 542, 543, 203, + 157, 515, 516, 203, 203, 203, 534, 203, + 175, 542, 543, 203, 157, 515, 516, 203, + 203, 203, 534, 203, 542, 542, 203, 157, + 515, 516, 203, 203, 203, 534, 203, 544, + 203, 545, 546, 203, 157, 515, 516, 203, + 203, 172, 203, 171, 203, 542, 542, 203, + 157, 515, 516, 203, 542, 542, 203, 157, + 515, 516, 203, 544, 203, 542, 542, 203, + 157, 515, 516, 203, 544, 203, 545, 542, + 203, 157, 515, 516, 203, 203, 172, 203, + 524, 171, 361, 361, 98, 365, 361, 79, + 194, 195, 361, 361, 361, 366, 361, 524, + 361, 548, 547, 549, 549, 547, 186, 550, + 551, 547, 549, 549, 547, 186, 550, 551, + 547, 552, 547, 547, 553, 550, 551, 547, + 550, 551, 547, 554, 547, 550, 555, 547, + 550, 556, 547, 550, 547, 552, 547, 547, + 547, 550, 551, 547, 188, 432, 432, 432, + 432, 432, 432, 432, 432, 432, 196, 432, + 432, 432, 432, 188, 432, 0 }; static const short _indic_syllable_machine_trans_targs[] = { @@ -1014,51 +1016,51 @@ static const short _indic_syllable_machine_trans_targs[] = { 169, 170, 520, 172, 173, 517, 175, 176, 514, 178, 532, 178, 179, 258, 337, 339, 413, 415, 359, 360, 416, 412, 494, 495, - 384, 530, 178, 180, 182, 36, 257, 202, - 203, 255, 227, 181, 35, 183, 251, 1, - 184, 186, 34, 250, 248, 185, 33, 187, - 244, 188, 190, 32, 243, 241, 189, 31, - 191, 237, 192, 194, 30, 236, 234, 193, - 29, 195, 230, 196, 198, 28, 229, 226, - 197, 27, 212, 0, 201, 206, 178, 204, - 205, 208, 2, 211, 3, 214, 6, 24, - 217, 9, 21, 220, 12, 18, 223, 15, - 225, 231, 233, 238, 240, 245, 247, 252, - 254, 178, 259, 261, 73, 334, 281, 282, - 335, 306, 260, 72, 262, 330, 38, 263, - 265, 71, 329, 327, 264, 70, 266, 323, - 267, 269, 69, 322, 320, 268, 68, 270, - 316, 271, 273, 67, 315, 313, 272, 66, - 274, 309, 275, 277, 65, 308, 305, 276, - 64, 291, 37, 280, 285, 178, 283, 284, - 287, 39, 290, 40, 293, 43, 61, 296, - 46, 58, 299, 49, 55, 302, 52, 304, - 310, 312, 317, 319, 324, 326, 331, 333, - 178, 338, 109, 340, 408, 75, 341, 343, - 108, 407, 405, 342, 107, 344, 401, 345, - 347, 106, 400, 398, 346, 105, 348, 394, - 349, 351, 104, 393, 391, 350, 103, 352, - 387, 353, 355, 102, 386, 383, 354, 101, - 369, 74, 358, 363, 178, 361, 362, 365, - 76, 368, 77, 371, 80, 98, 374, 83, - 95, 377, 86, 92, 380, 89, 382, 388, - 390, 395, 397, 402, 404, 409, 411, 178, - 178, 417, 419, 146, 145, 439, 440, 492, - 464, 418, 420, 488, 111, 421, 423, 144, - 487, 485, 422, 143, 424, 481, 425, 427, - 142, 480, 478, 426, 141, 428, 474, 429, - 431, 140, 473, 471, 430, 139, 432, 467, - 433, 435, 138, 466, 463, 434, 137, 449, - 110, 438, 443, 178, 441, 442, 445, 112, - 448, 113, 451, 116, 134, 454, 119, 131, - 457, 122, 128, 460, 125, 462, 468, 470, - 475, 477, 482, 484, 489, 491, 147, 496, - 497, 511, 500, 501, 529, 148, 505, 499, - 504, 502, 503, 506, 507, 150, 510, 508, - 149, 151, 513, 153, 174, 163, 516, 156, - 171, 519, 159, 168, 522, 162, 165, 525, - 164, 528, 178, 531, 177, 534, 535, 533, - 538, 178, 536, 537 + 384, 530, 539, 178, 180, 182, 36, 257, + 202, 203, 255, 227, 181, 35, 183, 251, + 1, 184, 186, 34, 250, 248, 185, 33, + 187, 244, 188, 190, 32, 243, 241, 189, + 31, 191, 237, 192, 194, 30, 236, 234, + 193, 29, 195, 230, 196, 198, 28, 229, + 226, 197, 27, 212, 0, 201, 206, 178, + 204, 205, 208, 2, 211, 3, 214, 6, + 24, 217, 9, 21, 220, 12, 18, 223, + 15, 225, 231, 233, 238, 240, 245, 247, + 252, 254, 178, 259, 261, 73, 334, 281, + 282, 335, 306, 260, 72, 262, 330, 38, + 263, 265, 71, 329, 327, 264, 70, 266, + 323, 267, 269, 69, 322, 320, 268, 68, + 270, 316, 271, 273, 67, 315, 313, 272, + 66, 274, 309, 275, 277, 65, 308, 305, + 276, 64, 291, 37, 280, 285, 178, 283, + 284, 287, 39, 290, 40, 293, 43, 61, + 296, 46, 58, 299, 49, 55, 302, 52, + 304, 310, 312, 317, 319, 324, 326, 331, + 333, 178, 338, 109, 340, 408, 75, 341, + 343, 108, 407, 405, 342, 107, 344, 401, + 345, 347, 106, 400, 398, 346, 105, 348, + 394, 349, 351, 104, 393, 391, 350, 103, + 352, 387, 353, 355, 102, 386, 383, 354, + 101, 369, 74, 358, 363, 178, 361, 362, + 365, 76, 368, 77, 371, 80, 98, 374, + 83, 95, 377, 86, 92, 380, 89, 382, + 388, 390, 395, 397, 402, 404, 409, 411, + 178, 178, 417, 419, 146, 145, 439, 440, + 492, 464, 418, 420, 488, 111, 421, 423, + 144, 487, 485, 422, 143, 424, 481, 425, + 427, 142, 480, 478, 426, 141, 428, 474, + 429, 431, 140, 473, 471, 430, 139, 432, + 467, 433, 435, 138, 466, 463, 434, 137, + 449, 110, 438, 443, 178, 441, 442, 445, + 112, 448, 113, 451, 116, 134, 454, 119, + 131, 457, 122, 128, 460, 125, 462, 468, + 470, 475, 477, 482, 484, 489, 491, 147, + 496, 497, 511, 500, 501, 529, 148, 505, + 499, 504, 502, 503, 506, 507, 150, 510, + 508, 149, 151, 513, 153, 174, 163, 516, + 156, 171, 519, 159, 168, 522, 162, 165, + 525, 164, 528, 178, 531, 177, 534, 535, + 533, 538, 178, 536, 537 }; static const char _indic_syllable_machine_trans_actions[] = { @@ -1087,51 +1089,51 @@ static const char _indic_syllable_machine_trans_actions[] = { 0, 0, 2, 0, 0, 2, 0, 0, 2, 9, 0, 12, 2, 2, 6, 2, 13, 13, 0, 0, 2, 2, 6, 2, - 6, 2, 14, 2, 2, 0, 2, 0, + 6, 2, 0, 14, 2, 2, 0, 2, + 0, 0, 2, 2, 2, 0, 2, 2, + 0, 2, 2, 0, 2, 2, 2, 0, + 2, 2, 2, 2, 0, 2, 2, 2, + 0, 2, 2, 2, 2, 0, 2, 2, + 2, 0, 2, 2, 2, 2, 0, 2, + 2, 2, 0, 2, 0, 0, 0, 15, + 0, 0, 2, 0, 2, 0, 2, 0, + 0, 2, 0, 0, 2, 0, 0, 2, + 0, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 16, 2, 2, 0, 2, 0, 0, 2, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, - 2, 0, 2, 0, 0, 0, 15, 0, + 2, 0, 2, 0, 0, 0, 17, 0, 0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 16, 2, 2, 0, 2, 0, 0, - 2, 2, 2, 0, 2, 2, 0, 2, - 2, 0, 2, 2, 2, 0, 2, 2, - 2, 2, 0, 2, 2, 2, 0, 2, - 2, 2, 2, 0, 2, 2, 2, 0, - 2, 2, 2, 2, 0, 2, 2, 2, - 0, 2, 0, 0, 0, 17, 0, 0, - 2, 0, 2, 0, 2, 0, 0, 2, - 0, 0, 2, 0, 0, 2, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, - 18, 6, 0, 6, 6, 0, 6, 2, - 0, 6, 2, 6, 0, 6, 6, 6, + 2, 18, 6, 0, 6, 6, 0, 6, 2, 0, 6, 2, 6, 0, 6, 6, 6, 2, 0, 6, 2, 6, 0, 6, 6, 6, 2, 0, 6, 2, 6, 0, - 6, 0, 0, 0, 19, 0, 0, 2, - 0, 2, 0, 2, 0, 0, 2, 0, - 0, 2, 0, 0, 2, 0, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 20, - 21, 2, 2, 0, 0, 0, 0, 2, - 2, 2, 2, 2, 0, 2, 2, 0, - 2, 2, 2, 0, 2, 2, 2, 2, + 6, 6, 6, 2, 0, 6, 2, 6, + 0, 6, 0, 0, 0, 19, 0, 0, + 2, 0, 2, 0, 2, 0, 0, 2, + 0, 0, 2, 0, 0, 2, 0, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 20, 21, 2, 2, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, - 0, 0, 0, 22, 0, 0, 2, 0, - 2, 0, 2, 0, 0, 2, 0, 0, - 2, 0, 0, 2, 0, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 0, 0, - 8, 2, 0, 0, 2, 0, 2, 0, - 0, 0, 0, 8, 8, 0, 8, 8, - 0, 0, 2, 0, 0, 0, 2, 0, - 0, 2, 0, 0, 2, 0, 0, 2, - 0, 2, 23, 2, 0, 0, 0, 0, - 0, 24, 0, 0 + 2, 2, 2, 0, 2, 2, 2, 0, + 2, 0, 0, 0, 22, 0, 0, 2, + 0, 2, 0, 2, 0, 0, 2, 0, + 0, 2, 0, 0, 2, 0, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 0, + 0, 8, 2, 0, 0, 2, 0, 2, + 0, 0, 0, 0, 8, 8, 0, 8, + 8, 0, 0, 2, 0, 0, 0, 2, + 0, 0, 2, 0, 0, 2, 0, 0, + 2, 0, 2, 23, 2, 0, 0, 0, + 0, 0, 24, 0, 0 }; static const char _indic_syllable_machine_to_state_actions[] = { @@ -1202,7 +1204,7 @@ static const char _indic_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }; static const char _indic_syllable_machine_from_state_actions[] = { @@ -1273,7 +1275,7 @@ static const char _indic_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 + 0, 0, 0, 0 }; static const short _indic_syllable_machine_eof_trans[] = { @@ -1299,52 +1301,52 @@ static const short _indic_syllable_machine_eof_trans[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 186, 0, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, - 282, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 361, 361, 361, - 361, 361, 361, 361, 361, 432, 361, 432, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 433, 433, - 433, 433, 433, 433, 433, 433, 361, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 361, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 203, 203, 203, 203, 203, 203, 203, - 203, 361, 547, 547, 547, 547, 547, 547, - 547, 547, 547 + 1, 186, 0, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 362, 362, 362, 433, 362, 433, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 434, 434, + 434, 434, 434, 434, 434, 434, 362, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 362, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 362, 548, 548, 548, 548, 548, 548, + 548, 548, 548, 433 }; static const int indic_syllable_machine_start = 178; @@ -1358,7 +1360,7 @@ static const int indic_syllable_machine_en_main = 178; -#line 96 "hb-ot-shape-complex-indic-machine.rl" +#line 97 "hb-ot-shape-complex-indic-machine.rl" #define found_syllable(syllable_type) \ @@ -1378,7 +1380,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 1382 "hb-ot-shape-complex-indic-machine.hh" +#line 1384 "hb-ot-shape-complex-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -1386,7 +1388,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 117 "hb-ot-shape-complex-indic-machine.rl" +#line 118 "hb-ot-shape-complex-indic-machine.rl" p = 0; @@ -1395,7 +1397,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 1399 "hb-ot-shape-complex-indic-machine.hh" +#line 1401 "hb-ot-shape-complex-indic-machine.hh" { int _slen; int _trans; @@ -1409,7 +1411,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 1413 "hb-ot-shape-complex-indic-machine.hh" +#line 1415 "hb-ot-shape-complex-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -1432,71 +1434,71 @@ _eof_trans: {te = p+1;} break; case 15: -#line 87 "hb-ot-shape-complex-indic-machine.rl" +#line 88 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (consonant_syllable); }} break; case 17: -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 89 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (vowel_syllable); }} break; case 22: -#line 89 "hb-ot-shape-complex-indic-machine.rl" +#line 90 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (standalone_cluster); }} break; case 24: -#line 90 "hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (symbol_cluster); }} break; case 19: -#line 91 "hb-ot-shape-complex-indic-machine.rl" +#line 92 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 12: -#line 92 "hb-ot-shape-complex-indic-machine.rl" +#line 93 "hb-ot-shape-complex-indic-machine.rl" {te = p+1;{ found_syllable (non_indic_cluster); }} break; case 14: -#line 87 "hb-ot-shape-complex-indic-machine.rl" +#line 88 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; case 16: -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 89 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (vowel_syllable); }} break; case 21: -#line 89 "hb-ot-shape-complex-indic-machine.rl" +#line 90 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (standalone_cluster); }} break; case 23: -#line 90 "hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (symbol_cluster); }} break; case 18: -#line 91 "hb-ot-shape-complex-indic-machine.rl" +#line 92 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; case 20: -#line 92 "hb-ot-shape-complex-indic-machine.rl" +#line 93 "hb-ot-shape-complex-indic-machine.rl" {te = p;p--;{ found_syllable (non_indic_cluster); }} break; case 1: -#line 87 "hb-ot-shape-complex-indic-machine.rl" +#line 88 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} break; case 3: -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 89 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (vowel_syllable); }} break; case 7: -#line 89 "hb-ot-shape-complex-indic-machine.rl" +#line 90 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (standalone_cluster); }} break; case 9: -#line 90 "hb-ot-shape-complex-indic-machine.rl" +#line 91 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (symbol_cluster); }} break; case 4: -#line 91 "hb-ot-shape-complex-indic-machine.rl" +#line 92 "hb-ot-shape-complex-indic-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; case 5: @@ -1517,22 +1519,22 @@ _eof_trans: case 8: #line 1 "NONE" {te = p+1;} -#line 87 "hb-ot-shape-complex-indic-machine.rl" +#line 88 "hb-ot-shape-complex-indic-machine.rl" {act = 1;} break; case 6: #line 1 "NONE" {te = p+1;} -#line 91 "hb-ot-shape-complex-indic-machine.rl" +#line 92 "hb-ot-shape-complex-indic-machine.rl" {act = 5;} break; case 13: #line 1 "NONE" {te = p+1;} -#line 92 "hb-ot-shape-complex-indic-machine.rl" +#line 93 "hb-ot-shape-complex-indic-machine.rl" {act = 6;} break; -#line 1536 "hb-ot-shape-complex-indic-machine.hh" +#line 1538 "hb-ot-shape-complex-indic-machine.hh" } _again: @@ -1541,7 +1543,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1545 "hb-ot-shape-complex-indic-machine.hh" +#line 1547 "hb-ot-shape-complex-indic-machine.hh" } if ( ++p != pe ) @@ -1557,7 +1559,7 @@ _again: } -#line 126 "hb-ot-shape-complex-indic-machine.rl" +#line 127 "hb-ot-shape-complex-indic-machine.rl" } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh index 5879c3e491..a1e0d5266b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-private.hh @@ -60,7 +60,8 @@ enum indic_category_t { OT_Repha = 15, /* Atomically-encoded logical or visual repha. */ OT_Ra = 16, OT_CM = 17, /* Consonant-Medial. */ - OT_Symbol = 18 /* Avagraha, etc that take marks (SM,A,VD). */ + OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */ + OT_CS = 19 }; #define MEDIAL_FLAGS (FLAG (OT_CM)) @@ -70,7 +71,7 @@ enum indic_category_t { * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels * cannot happen in a consonant syllable. The plus side however is, we can call the * consonant syllable logic from the vowel syllable function and get it all right! */ -#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE)) +#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE)) #define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ)) #define HALANT_OR_COENG_FLAGS (FLAG (OT_H) | FLAG (OT_Coeng)) @@ -121,8 +122,8 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */ INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM, INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_N, - INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_Repha, /* TODO */ - INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, + INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_CS, + INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */ INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng, INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ, INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X, @@ -132,7 +133,7 @@ enum indic_syllabic_category_t { INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */ INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */ INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS, - INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_M, /* Misc Khmer signs. */ + INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_SM, INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X, INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N, INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc index 80a6b25e3b..bfd1c6d342 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc @@ -6,61 +6,62 @@ * * on files with these headers: * - * # IndicSyllabicCategory-9.0.0.txt - * # Date: 2016-05-21, 02:46:00 GMT [RP] - * # IndicPositionalCategory-9.0.0.txt - * # Date: 2016-02-25, 00:48:00 GMT [RP] - * # Blocks-9.0.0.txt - * # Date: 2016-02-05, 23:48:00 GMT [KW] + * # IndicSyllabicCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [KW, RP] + * # IndicPositionalCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [RP] + * # Blocks-10.0.0.txt + * # Date: 2017-04-12, 17:30:00 GMT [KW] */ #include "hb-ot-shape-complex-indic-private.hh" #define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 15 chars; Avagraha */ -#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 67 chars; Bindu */ +#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 80 chars; Bindu */ #define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */ -#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 53 chars; Cantillation_Mark */ -#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 1907 chars; Consonant */ +#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 57 chars; Cantillation_Mark */ +#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2024 chars; Consonant */ #define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 10 chars; Consonant_Dead */ -#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 62 chars; Consonant_Final */ +#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 68 chars; Consonant_Final */ #define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */ #define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */ -#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 22 chars; Consonant_Medial */ -#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 16 chars; Consonant_Placeholder */ -#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 1 chars; Consonant_Preceding_Repha */ -#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 2 chars; Consonant_Prefixed */ -#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 90 chars; Consonant_Subjoined */ -#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 4 chars; Consonant_Succeeding_Repha */ +#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 27 chars; Consonant_Medial */ +#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 18 chars; Consonant_Placeholder */ +#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 2 chars; Consonant_Preceding_Repha */ +#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 7 chars; Consonant_Prefixed */ +#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 95 chars; Consonant_Subjoined */ +#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 5 chars; Consonant_Succeeding_Repha */ #define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 4 chars; Consonant_With_Stacker */ -#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 2 chars; Gemination_Mark */ -#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 7 chars; Invisible_Stacker */ +#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */ +#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 10 chars; Invisible_Stacker */ #define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */ #define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */ #define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */ -#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 24 chars; Nukta */ -#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 459 chars; Number */ +#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 28 chars; Nukta */ +#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 469 chars; Number */ #define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */ #define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */ -#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 16 chars; Pure_Killer */ +#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 21 chars; Pure_Killer */ #define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */ #define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 22 chars; Syllable_Modifier */ #define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */ #define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */ #define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 24 chars; Virama */ -#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 31 chars; Visarga */ +#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 34 chars; Visarga */ #define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */ -#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 602 chars; Vowel_Dependent */ -#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 431 chars; Vowel_Independent */ +#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 633 chars; Vowel_Dependent */ +#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 443 chars; Vowel_Independent */ -#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 300 chars; Bottom */ +#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 330 chars; Bottom */ +#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */ #define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 2 chars; Bottom_And_Right */ #define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 57 chars; Left */ #define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 21 chars; Left_And_Right */ #define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */ #define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */ -#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 258 chars; Right */ -#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 342 chars; Top */ +#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 262 chars; Right */ +#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 380 chars; Top */ #define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */ #define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */ #define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */ @@ -133,7 +134,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(Bi,x), _(x,x), _(x,x), _(x,x), /* Gurmukhi */ @@ -171,7 +172,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x), /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), - /* 0AF8 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* 0AF8 */ _(x,x), _(C,x), _(Ca,T), _(Ca,T), _(Ca,T), _(N,T), _(N,T), _(N,T), /* Oriya */ @@ -251,14 +252,14 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* Malayalam */ - /* 0D00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), + /* 0D00 */ _(Bi,T), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x), /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x), /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), /* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), - /* 0D38 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(A,x), _(M,R), _(M,R), + /* 0D38 */ _(C,x), _(C,x), _(C,x), _(PK,T), _(PK,T), _(A,x), _(M,R), _(M,R), /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L), /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,x), _(x,x), /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(M,R), @@ -341,7 +342,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B), /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x), - /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(x,x), + /* 1CF0 */ _(x,x), _(x,x), _(Vs,x), _(Vs,x), _(Ca,T), _(x,x), _(x,x), _(Ca,R), /* 1CF8 */ _(Ca,x), _(Ca,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), #define indic_offset_0x2008u 1656 @@ -368,7 +369,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), - /* A8F0 */ _(Ca,T), _(Ca,T), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), + /* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x), #define indic_offset_0xa9e0u 1720 @@ -390,7 +391,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x), -}; /* Table items: 1784; occupancy: 69% */ +}; /* Table items: 1784; occupancy: 70% */ INDIC_TABLE_ELEMENT_TYPE hb_indic_get_categories (hb_codepoint_t u) @@ -398,28 +399,28 @@ hb_indic_get_categories (hb_codepoint_t u) switch (u >> 12) { case 0x0u: - if (hb_in_range (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; - if (hb_in_range (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u]; - if (hb_in_range (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; + if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u]; + if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u]; if (unlikely (u == 0x00A0u)) return _(CP,x); break; case 0x1u: - if (hb_in_range (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; - if (hb_in_range (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u]; - if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u]; break; case 0x2u: - if (hb_in_range (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; - if (hb_in_range (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u]; + if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u]; + if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u]; if (unlikely (u == 0x25CCu)) return _(CP,x); break; case 0xAu: - if (hb_in_range (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u]; - if (hb_in_range (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u]; - if (hb_in_range (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u]; + if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8F7u)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u]; + if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u]; + if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u]; break; default: @@ -467,6 +468,7 @@ hb_indic_get_categories (hb_codepoint_t u) #undef ISC_VI #undef IMC_B +#undef IMC_BL #undef IMC_BR #undef IMC_L #undef IMC_LR diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc index b48fb561c3..97d6d38287 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc @@ -142,7 +142,7 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags) { /* If it ligated, all bets are off. */ if (_hb_glyph_info_ligated (&info)) return false; - return !!(FLAG_SAFE (info.indic_category()) & flags); + return !!(FLAG_UNSAFE (info.indic_category()) & flags); } static inline bool @@ -177,15 +177,15 @@ set_indic_properties (hb_glyph_info_t &info) */ /* The following act more like the Bindus. */ - if (unlikely (hb_in_range (u, 0x0953u, 0x0954u))) + if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u))) cat = OT_SM; /* The following act like consonants. */ - else if (unlikely (hb_in_ranges (u, 0x0A72u, 0x0A73u, + else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u, 0x1CF5u, 0x1CF6u))) cat = OT_C; /* TODO: The following should only be allowed after a Visarga. * For now, just treat them like regular tone marks. */ - else if (unlikely (hb_in_range (u, 0x1CE2u, 0x1CE8u))) + else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u))) cat = OT_A; /* TODO: The following should only be allowed after some of * the nasalization marks, maybe only for U+1CE9..U+1CF1. @@ -193,15 +193,39 @@ set_indic_properties (hb_glyph_info_t &info) else if (unlikely (u == 0x1CEDu)) cat = OT_A; /* The following take marks in standalone clusters, similar to Avagraha. */ - else if (unlikely (hb_in_ranges (u, 0xA8F2u, 0xA8F7u, + else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u, 0x1CE9u, 0x1CECu, 0x1CEEu, 0x1CF1u))) { cat = OT_Symbol; - ASSERT_STATIC ((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol); + static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), ""); } + else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CDu, 0x17D1u) || + u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */ + { + /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier. + * https://github.com/roozbehp/unicode-data/issues/5 */ + cat = OT_M; + pos = POS_ABOVE_C; + } + else if (unlikely (u == 0x0A51u)) + { + /* https://github.com/harfbuzz/harfbuzz/issues/524 */ + cat = OT_M; + pos = POS_BELOW_C; + } + + /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil, + * so the Indic shaper needs to know their categories. */ + else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM; + else if (unlikely (u == 0x1133cu)) cat = OT_N; + + else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */ + + else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */ + else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */ else if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */ - else if (unlikely (hb_in_range (u, 0x2010u, 0x2011u))) + else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER; else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE; @@ -210,7 +234,7 @@ set_indic_properties (hb_glyph_info_t &info) * Re-assign position. */ - if ((FLAG_SAFE (cat) & CONSONANT_FLAGS)) + if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS)) { pos = POS_BASE_C; if (is_ra (u)) @@ -220,7 +244,7 @@ set_indic_properties (hb_glyph_info_t &info) { pos = matra_position (u, pos); } - else if ((FLAG_SAFE (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol)))) + else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) | FLAG (OT_VD) | FLAG (OT_A) | FLAG (OT_Symbol)))) { pos = POS_SMVD; } @@ -411,12 +435,12 @@ collect_features_indic (hb_ot_shape_planner_t *plan) unsigned int i = 0; map->add_gsub_pause (initial_reordering); for (; i < INDIC_BASIC_FEATURES; i++) { - map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); - map->add_gsub_pause (NULL); + map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); + map->add_gsub_pause (nullptr); } map->add_gsub_pause (final_reordering); for (; i < INDIC_NUM_FEATURES; i++) { - map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ); + map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ); } map->add_global_bool_feature (HB_TAG('c','a','l','t')); @@ -485,7 +509,7 @@ struct indic_shape_plan_t /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph * during shape planning... Instead, overwrite it here. It's safe. Don't worry! */ - (const_cast<indic_shape_plan_t *> (this))->virama_glyph = glyph; + virama_glyph = glyph; } *pglyph = glyph; @@ -495,7 +519,7 @@ struct indic_shape_plan_t const indic_config_t *config; bool is_old_spec; - hb_codepoint_t virama_glyph; + mutable hb_codepoint_t virama_glyph; would_substitute_feature_t rphf; would_substitute_feature_t pref; @@ -510,7 +534,7 @@ data_create_indic (const hb_ot_shape_plan_t *plan) { indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) calloc (1, sizeof (indic_shape_plan_t)); if (unlikely (!indic_plan)) - return NULL; + return nullptr; indic_plan->config = &indic_configs[0]; for (unsigned int i = 1; i < ARRAY_LENGTH (indic_configs); i++) @@ -615,6 +639,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer) { find_syllables (buffer); + foreach_syllable (buffer, start, end) + buffer->unsafe_to_break (start, end); } static int @@ -666,6 +692,21 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data; hb_glyph_info_t *info = buffer->info; + /* https://github.com/harfbuzz/harfbuzz/issues/435#issuecomment-335560167 + * // For compatibility with legacy usage in Kannada, + * // Ra+h+ZWJ must behave like Ra+ZWJ+h... + */ + if (buffer->props.script == HB_SCRIPT_KANNADA && + start + 3 <= end && + is_one_of (info[start ], FLAG (OT_Ra)) && + is_one_of (info[start+1], FLAG (OT_H)) && + is_one_of (info[start+2], FLAG (OT_ZWJ))) + { + buffer->merge_clusters (start+1, start+3); + hb_glyph_info_t tmp = info[start+1]; + info[start+1] = info[start+2]; + info[start+2] = tmp; + } /* 1. Find base consonant: * @@ -673,7 +714,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * following algorithm: starting from the end of the syllable, move backwards * until a consonant is found that does not have a below-base or post-base * form (post-base forms have to follow below-base forms), or that is not a - * pre-base reordering Ra, or arrive at the first consonant. The consonant + * pre-base-reordering Ra, or arrive at the first consonant. The consonant * stopped at will be the base. * * o If the syllable starts with Ra + Halant (in a script that has Reph) @@ -744,11 +785,11 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, if (info[i].indic_position() == POS_BELOW_C) seen_below = true; - /* -> or that is not a pre-base reordering Ra, + /* -> or that is not a pre-base-reordering Ra, * * IMPLEMENTATION NOTES: * - * Our pre-base reordering Ra's are marked POS_POST_C, so will be skipped + * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped * by the logic above already. */ @@ -831,8 +872,8 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, /* 2. Decompose and reorder Matras: * - * Each matra and any syllable modifier sign in the cluster are moved to the - * appropriate position relative to the consonant(s) in the cluster. The + * Each matra and any syllable modifier sign in the syllable are moved to the + * appropriate position relative to the consonant(s) in the syllable. The * shaping engine decomposes two- or three-part matras into their constituent * parts before any repositioning. Matra characters are classified by which * consonant in a conjunct they have affinity for and are reordered to the @@ -928,7 +969,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, indic_position_t last_pos = POS_START; for (unsigned int i = start; i < end; i++) { - if ((FLAG_SAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | HALANT_OR_COENG_FLAGS))) + if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | HALANT_OR_COENG_FLAGS))) { info[i].indic_position() = last_pos; if (unlikely (info[i].indic_category() == OT_H && @@ -1083,7 +1124,7 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, unsigned int pref_len = 2; if (indic_plan->mask_array[PREF] && base + pref_len < end) { - /* Find a Halant,Ra sequence and mark it for pre-base reordering processing. */ + /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */ for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) { hb_codepoint_t glyphs[2]; for (unsigned int j = 0; j < pref_len; j++) @@ -1258,7 +1299,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* This function relies heavily on halant glyphs. Lots of ligation - * and possibly multiplication substitutions happened prior to this + * and possibly multiple substitutions happened prior to this * phase, and that might have messed up our properties. Recover * from a particular case of that where we're fairly sure that a * class of OT_H is desired but has been lost. */ @@ -1282,7 +1323,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * After the localized forms and basic shaping forms GSUB features have been * applied (see below), the shaping engine performs some final glyph * reordering before applying all the remaining font features to the entire - * cluster. + * syllable. */ bool try_pref = !!indic_plan->mask_array[PREF]; @@ -1477,7 +1518,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* 3. If reph should be repositioned after the main consonant: find the * first consonant not ligated with main, or find the first - * consonant that is not a potential pre-base reordering Ra. + * consonant that is not a potential pre-base-reordering Ra. */ if (reph_pos == REPH_POS_AFTER_MAIN) { @@ -1497,8 +1538,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (reph_pos == REPH_POS_AFTER_SUB) { new_reph_pos = base; - while (new_reph_pos < end && - !( FLAG_SAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD)))) + while (new_reph_pos + 1 < end && + !( FLAG_UNSAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD)))) new_reph_pos++; if (new_reph_pos < end) goto reph_move; @@ -1566,13 +1607,13 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, } - /* o Reorder pre-base reordering consonants: + /* o Reorder pre-base-reordering consonants: * - * If a pre-base reordering consonant is found, reorder it according to + * If a pre-base-reordering consonant is found, reorder it according to * the following rules: */ - if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base reordering Ra. */ + if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */ { for (unsigned int i = base + 1; i < end; i++) if ((info[i].mask & indic_plan->mask_array[PREF]) != 0) @@ -1646,11 +1687,15 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, /* Apply 'init' to the Left Matra if it's a word start. */ - if (info[start].indic_position () == POS_PRE_M && - (!start || - !(FLAG_SAFE (_hb_glyph_info_get_general_category (&info[start - 1])) & - FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))) - info[start].mask |= indic_plan->mask_array[INIT]; + if (info[start].indic_position () == POS_PRE_M) + { + if (!start || + !(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) & + FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) + info[start].mask |= indic_plan->mask_array[INIT]; + else + buffer->unsafe_to_break (start - 1, start + 1); + } /* @@ -1665,8 +1710,8 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, break; default: - /* Uniscribe merges the entire cluster... Except for Tamil & Sinhala. - * This means, half forms are submerged into the main consonants cluster. + /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala. + * This means, half forms are submerged into the main consonant's cluster. * This is unnecessary, and makes cursor positioning harder, but that's what * Uniscribe does. */ buffer->merge_clusters (start, end); @@ -1738,7 +1783,7 @@ decompose_indic (const hb_ot_shape_normalize_context_t *c, #endif } - if ((ab == 0x0DDAu || hb_in_range (ab, 0x0DDCu, 0x0DDEu))) + if ((ab == 0x0DDAu || hb_in_range<hb_codepoint_t> (ab, 0x0DDCu, 0x0DDEu))) { /* * Sinhala split matras... Let the fun begin. @@ -1803,18 +1848,18 @@ compose_indic (const hb_ot_shape_normalize_context_t *c, const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic = { - "indic", collect_features_indic, override_features_indic, data_create_indic, data_destroy_indic, - NULL, /* preprocess_text */ - NULL, /* postprocess_glyphs */ + nullptr, /* preprocess_text */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_indic, compose_indic, setup_masks_indic, - NULL, /* disable_otl */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, false, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh index 29fdf9a1ae..ed87404305 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar-machine.hh @@ -34,197 +34,201 @@ #line 36 "hb-ot-shape-complex-myanmar-machine.hh" static const unsigned char _myanmar_syllable_machine_trans_keys[] = { - 1u, 31u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, + 1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 30u, 3u, 29u, 1u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, - 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 8u, 8u, 0 + 3u, 30u, 3u, 29u, 1u, 32u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, + 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 32u, 8u, 8u, 0 }; static const char _myanmar_syllable_machine_key_spans[] = { - 31, 28, 25, 4, 25, 23, 21, 21, + 32, 28, 25, 4, 25, 23, 21, 21, 27, 27, 27, 27, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 25, 4, 25, 23, 21, 21, 27, 27, 27, 27, - 28, 27, 30, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 1 + 28, 27, 32, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 32, 1 }; static const short _myanmar_syllable_machine_index_offsets[] = { - 0, 32, 61, 87, 92, 118, 142, 164, - 186, 214, 242, 270, 298, 315, 343, 371, - 399, 427, 455, 483, 511, 539, 567, 593, - 598, 624, 648, 670, 692, 720, 748, 776, - 804, 833, 861, 892, 920, 948, 976, 1004, - 1032, 1060, 1088, 1116, 1144 + 0, 33, 62, 88, 93, 119, 143, 165, + 187, 215, 243, 271, 299, 316, 344, 372, + 400, 428, 456, 484, 512, 540, 568, 594, + 599, 625, 649, 671, 693, 721, 749, 777, + 805, 834, 862, 895, 923, 951, 979, 1007, + 1035, 1063, 1091, 1119, 1147, 1180 }; static const char _myanmar_syllable_machine_indicies[] = { 1, 1, 2, 3, 4, 4, 0, 5, 0, 6, 1, 0, 0, 0, 0, 7, - 0, 8, 1, 0, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 0, - 21, 22, 23, 23, 20, 24, 20, 25, - 20, 20, 20, 20, 20, 20, 20, 26, - 20, 20, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 20, 23, 23, 20, - 24, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 37, 20, 20, 20, 20, 20, - 20, 31, 20, 20, 20, 35, 20, 23, - 23, 20, 24, 20, 23, 23, 20, 24, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 31, 20, 20, 20, 35, 20, 38, 20, - 23, 23, 20, 24, 20, 31, 20, 20, - 20, 20, 20, 20, 20, 39, 20, 20, - 20, 20, 20, 20, 31, 20, 23, 23, - 20, 24, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 39, 20, 20, 20, 20, - 20, 20, 31, 20, 23, 23, 20, 24, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 31, 20, 21, 20, 23, 23, 20, 24, - 20, 25, 20, 20, 20, 20, 20, 20, - 20, 40, 20, 20, 40, 20, 20, 20, - 31, 41, 20, 20, 35, 20, 21, 20, - 23, 23, 20, 24, 20, 25, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 31, 20, 20, 20, - 35, 20, 21, 20, 23, 23, 20, 24, - 20, 25, 20, 20, 20, 20, 20, 20, - 20, 40, 20, 20, 20, 20, 20, 20, - 31, 41, 20, 20, 35, 20, 21, 20, - 23, 23, 20, 24, 20, 25, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 31, 41, 20, 20, - 35, 20, 1, 1, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 1, 20, 21, 20, 23, 23, 20, - 24, 20, 25, 20, 20, 20, 20, 20, - 20, 20, 26, 20, 20, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 20, 21, - 20, 23, 23, 20, 24, 20, 25, 20, - 20, 20, 20, 20, 20, 20, 34, 20, - 20, 20, 20, 20, 20, 31, 32, 33, - 34, 35, 20, 21, 20, 23, 23, 20, - 24, 20, 25, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 31, 32, 33, 34, 35, 20, 21, - 20, 23, 23, 20, 24, 20, 25, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 31, 32, 33, - 20, 35, 20, 21, 20, 23, 23, 20, - 24, 20, 25, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, - 20, 31, 20, 33, 20, 35, 20, 21, - 20, 23, 23, 20, 24, 20, 25, 20, - 20, 20, 20, 20, 20, 20, 34, 20, - 20, 27, 20, 29, 20, 31, 32, 33, - 34, 35, 20, 21, 20, 23, 23, 20, - 24, 20, 25, 20, 20, 20, 20, 20, - 20, 20, 34, 20, 20, 27, 20, 20, - 20, 31, 32, 33, 34, 35, 20, 21, - 20, 23, 23, 20, 24, 20, 25, 20, - 20, 20, 20, 20, 20, 20, 34, 20, - 20, 27, 28, 29, 20, 31, 32, 33, - 34, 35, 20, 21, 22, 23, 23, 20, - 24, 20, 25, 20, 20, 20, 20, 20, - 20, 20, 26, 20, 20, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 20, 3, - 3, 42, 5, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 43, 42, 42, 42, - 42, 42, 42, 13, 42, 42, 42, 17, - 42, 3, 3, 42, 5, 42, 3, 3, - 42, 5, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 13, 42, 42, 42, 17, 42, - 44, 42, 3, 3, 42, 5, 42, 13, - 42, 42, 42, 42, 42, 42, 42, 45, - 42, 42, 42, 42, 42, 42, 13, 42, - 3, 3, 42, 5, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 45, 42, 42, - 42, 42, 42, 42, 13, 42, 3, 3, - 42, 5, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 13, 42, 2, 42, 3, 3, - 42, 5, 42, 6, 42, 42, 42, 42, - 42, 42, 42, 46, 42, 42, 46, 42, - 42, 42, 13, 47, 42, 42, 17, 42, - 2, 42, 3, 3, 42, 5, 42, 6, - 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 13, 42, - 42, 42, 17, 42, 2, 42, 3, 3, - 42, 5, 42, 6, 42, 42, 42, 42, - 42, 42, 42, 46, 42, 42, 42, 42, - 42, 42, 13, 47, 42, 42, 17, 42, - 2, 42, 3, 3, 42, 5, 42, 6, - 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 13, 47, - 42, 42, 17, 42, 21, 22, 23, 23, - 20, 24, 20, 25, 20, 20, 20, 20, - 20, 20, 20, 48, 20, 20, 27, 28, + 0, 8, 9, 0, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 1, + 0, 22, 23, 24, 24, 21, 25, 21, + 26, 21, 21, 21, 21, 21, 21, 21, + 27, 21, 21, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 21, 24, 24, + 21, 25, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 38, 21, 21, 21, 21, + 21, 21, 32, 21, 21, 21, 36, 21, + 24, 24, 21, 25, 21, 24, 24, 21, + 25, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 32, 21, 21, 21, 36, 21, 39, + 21, 24, 24, 21, 25, 21, 32, 21, + 21, 21, 21, 21, 21, 21, 40, 21, + 21, 21, 21, 21, 21, 32, 21, 24, + 24, 21, 25, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 40, 21, 21, 21, + 21, 21, 21, 32, 21, 24, 24, 21, + 25, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 32, 21, 22, 21, 24, 24, 21, + 25, 21, 26, 21, 21, 21, 21, 21, + 21, 21, 41, 21, 21, 41, 21, 21, + 21, 32, 42, 21, 21, 36, 21, 22, + 21, 24, 24, 21, 25, 21, 26, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 32, 21, 21, + 21, 36, 21, 22, 21, 24, 24, 21, + 25, 21, 26, 21, 21, 21, 21, 21, + 21, 21, 41, 21, 21, 21, 21, 21, + 21, 32, 42, 21, 21, 36, 21, 22, + 21, 24, 24, 21, 25, 21, 26, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 32, 42, 21, + 21, 36, 21, 1, 1, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 1, 21, 22, 21, 24, 24, + 21, 25, 21, 26, 21, 21, 21, 21, + 21, 21, 21, 27, 21, 21, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 21, + 22, 21, 24, 24, 21, 25, 21, 26, + 21, 21, 21, 21, 21, 21, 21, 35, + 21, 21, 21, 21, 21, 21, 32, 33, + 34, 35, 36, 21, 22, 21, 24, 24, + 21, 25, 21, 26, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 32, 33, 34, 35, 36, 21, + 22, 21, 24, 24, 21, 25, 21, 26, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 32, 33, + 34, 21, 36, 21, 22, 21, 24, 24, + 21, 25, 21, 26, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 32, 21, 34, 21, 36, 21, + 22, 21, 24, 24, 21, 25, 21, 26, + 21, 21, 21, 21, 21, 21, 21, 35, + 21, 21, 28, 21, 30, 21, 32, 33, + 34, 35, 36, 21, 22, 21, 24, 24, + 21, 25, 21, 26, 21, 21, 21, 21, + 21, 21, 21, 35, 21, 21, 28, 21, + 21, 21, 32, 33, 34, 35, 36, 21, + 22, 21, 24, 24, 21, 25, 21, 26, + 21, 21, 21, 21, 21, 21, 21, 35, + 21, 21, 28, 29, 30, 21, 32, 33, + 34, 35, 36, 21, 22, 23, 24, 24, + 21, 25, 21, 26, 21, 21, 21, 21, + 21, 21, 21, 27, 21, 21, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 21, + 3, 3, 43, 5, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 44, 43, 43, + 43, 43, 43, 43, 14, 43, 43, 43, + 18, 43, 3, 3, 43, 5, 43, 3, + 3, 43, 5, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 14, 43, 43, 43, 18, + 43, 45, 43, 3, 3, 43, 5, 43, + 14, 43, 43, 43, 43, 43, 43, 43, + 46, 43, 43, 43, 43, 43, 43, 14, + 43, 3, 3, 43, 5, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 46, 43, + 43, 43, 43, 43, 43, 14, 43, 3, + 3, 43, 5, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 14, 43, 2, 43, 3, + 3, 43, 5, 43, 6, 43, 43, 43, + 43, 43, 43, 43, 47, 43, 43, 47, + 43, 43, 43, 14, 48, 43, 43, 18, + 43, 2, 43, 3, 3, 43, 5, 43, + 6, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 14, + 43, 43, 43, 18, 43, 2, 43, 3, + 3, 43, 5, 43, 6, 43, 43, 43, + 43, 43, 43, 43, 47, 43, 43, 43, + 43, 43, 43, 14, 48, 43, 43, 18, + 43, 2, 43, 3, 3, 43, 5, 43, + 6, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 14, + 48, 43, 43, 18, 43, 22, 23, 24, + 24, 21, 25, 21, 26, 21, 21, 21, + 21, 21, 21, 21, 49, 21, 21, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 20, 21, 49, 23, 23, 20, 24, 20, - 25, 20, 20, 20, 20, 20, 20, 20, - 26, 20, 20, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 20, 1, 1, 2, - 3, 3, 3, 42, 5, 42, 6, 1, - 42, 42, 42, 42, 1, 42, 8, 1, - 42, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 42, 2, 42, 3, 3, - 42, 5, 42, 6, 42, 42, 42, 42, - 42, 42, 42, 8, 42, 42, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 42, - 2, 42, 3, 3, 42, 5, 42, 6, - 42, 42, 42, 42, 42, 42, 42, 16, - 42, 42, 42, 42, 42, 42, 13, 14, - 15, 16, 17, 42, 2, 42, 3, 3, - 42, 5, 42, 6, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 13, 14, 15, 16, 17, 42, - 2, 42, 3, 3, 42, 5, 42, 6, - 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 13, 14, - 15, 42, 17, 42, 2, 42, 3, 3, - 42, 5, 42, 6, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 13, 42, 15, 42, 17, 42, - 2, 42, 3, 3, 42, 5, 42, 6, - 42, 42, 42, 42, 42, 42, 42, 16, - 42, 42, 9, 42, 11, 42, 13, 14, - 15, 16, 17, 42, 2, 42, 3, 3, - 42, 5, 42, 6, 42, 42, 42, 42, - 42, 42, 42, 16, 42, 42, 9, 42, - 42, 42, 13, 14, 15, 16, 17, 42, - 2, 42, 3, 3, 42, 5, 42, 6, - 42, 42, 42, 42, 42, 42, 42, 16, - 42, 42, 9, 10, 11, 42, 13, 14, - 15, 16, 17, 42, 2, 3, 3, 3, - 42, 5, 42, 6, 42, 42, 42, 42, - 42, 42, 42, 8, 42, 42, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 42, - 51, 50, 0 + 37, 21, 22, 50, 24, 24, 21, 25, + 21, 26, 21, 21, 21, 21, 21, 21, + 21, 27, 21, 21, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 21, 1, 1, + 2, 3, 3, 3, 43, 5, 43, 6, + 1, 43, 43, 43, 43, 1, 43, 8, + 43, 43, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 43, 1, 43, 2, + 43, 3, 3, 43, 5, 43, 6, 43, + 43, 43, 43, 43, 43, 43, 8, 43, + 43, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 43, 2, 43, 3, 3, 43, + 5, 43, 6, 43, 43, 43, 43, 43, + 43, 43, 17, 43, 43, 43, 43, 43, + 43, 14, 15, 16, 17, 18, 43, 2, + 43, 3, 3, 43, 5, 43, 6, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 14, 15, 16, + 17, 18, 43, 2, 43, 3, 3, 43, + 5, 43, 6, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 14, 15, 16, 43, 18, 43, 2, + 43, 3, 3, 43, 5, 43, 6, 43, + 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 14, 43, 16, + 43, 18, 43, 2, 43, 3, 3, 43, + 5, 43, 6, 43, 43, 43, 43, 43, + 43, 43, 17, 43, 43, 10, 43, 12, + 43, 14, 15, 16, 17, 18, 43, 2, + 43, 3, 3, 43, 5, 43, 6, 43, + 43, 43, 43, 43, 43, 43, 17, 43, + 43, 10, 43, 43, 43, 14, 15, 16, + 17, 18, 43, 2, 43, 3, 3, 43, + 5, 43, 6, 43, 43, 43, 43, 43, + 43, 43, 17, 43, 43, 10, 11, 12, + 43, 14, 15, 16, 17, 18, 43, 2, + 3, 3, 3, 43, 5, 43, 6, 43, + 43, 43, 43, 43, 43, 43, 8, 43, + 43, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 43, 1, 1, 51, 51, 51, + 51, 51, 51, 51, 51, 1, 51, 51, + 51, 51, 1, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 1, 51, 52, 51, 0 }; static const char _myanmar_syllable_machine_trans_targs[] = { 0, 1, 22, 0, 0, 23, 29, 32, - 35, 36, 40, 41, 42, 25, 38, 39, - 37, 28, 43, 44, 0, 2, 12, 0, - 3, 9, 13, 14, 18, 19, 20, 5, - 16, 17, 15, 8, 21, 4, 6, 7, - 10, 11, 0, 24, 26, 27, 30, 31, - 33, 34, 0, 0 + 35, 44, 36, 40, 41, 42, 25, 38, + 39, 37, 28, 43, 45, 0, 2, 12, + 0, 3, 9, 13, 14, 18, 19, 20, + 5, 16, 17, 15, 8, 21, 4, 6, + 7, 10, 11, 0, 24, 26, 27, 30, + 31, 33, 34, 0, 0 }; static const char _myanmar_syllable_machine_trans_actions[] = { 3, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, 0, 0, 7, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 8, 0, 0, 0, 0, 0, - 0, 0, 9, 10 + 0, 0, 0, 8, 0, 0, 0, 0, + 0, 0, 0, 9, 10 }; static const char _myanmar_syllable_machine_to_state_actions[] = { @@ -233,7 +237,7 @@ static const char _myanmar_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }; static const char _myanmar_syllable_machine_from_state_actions[] = { @@ -242,16 +246,16 @@ static const char _myanmar_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0 }; static const short _myanmar_syllable_machine_eof_trans[] = { - 0, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 43, 43, - 43, 43, 43, 43, 43, 43, 43, 43, - 21, 21, 43, 43, 43, 43, 43, 43, - 43, 43, 43, 43, 51 + 0, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 22, 22, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 52, 52 }; static const int myanmar_syllable_machine_start = 0; @@ -265,7 +269,7 @@ static const int myanmar_syllable_machine_en_main = 0; -#line 93 "hb-ot-shape-complex-myanmar-machine.rl" +#line 94 "hb-ot-shape-complex-myanmar-machine.rl" #define found_syllable(syllable_type) \ @@ -285,7 +289,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 289 "hb-ot-shape-complex-myanmar-machine.hh" +#line 293 "hb-ot-shape-complex-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -293,7 +297,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 114 "hb-ot-shape-complex-myanmar-machine.rl" +#line 115 "hb-ot-shape-complex-myanmar-machine.rl" p = 0; @@ -302,7 +306,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 306 "hb-ot-shape-complex-myanmar-machine.hh" +#line 310 "hb-ot-shape-complex-myanmar-machine.hh" { int _slen; int _trans; @@ -316,7 +320,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 320 "hb-ot-shape-complex-myanmar-machine.hh" +#line 324 "hb-ot-shape-complex-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -335,38 +339,38 @@ _eof_trans: switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { case 7: -#line 85 "hb-ot-shape-complex-myanmar-machine.rl" +#line 86 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (consonant_syllable); }} break; case 5: -#line 86 "hb-ot-shape-complex-myanmar-machine.rl" +#line 87 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (non_myanmar_cluster); }} break; case 10: -#line 87 "hb-ot-shape-complex-myanmar-machine.rl" +#line 88 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (punctuation_cluster); }} break; case 4: -#line 88 "hb-ot-shape-complex-myanmar-machine.rl" +#line 89 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 3: -#line 89 "hb-ot-shape-complex-myanmar-machine.rl" +#line 90 "hb-ot-shape-complex-myanmar-machine.rl" {te = p+1;{ found_syllable (non_myanmar_cluster); }} break; case 6: -#line 85 "hb-ot-shape-complex-myanmar-machine.rl" +#line 86 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (consonant_syllable); }} break; case 8: -#line 88 "hb-ot-shape-complex-myanmar-machine.rl" +#line 89 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; case 9: -#line 89 "hb-ot-shape-complex-myanmar-machine.rl" +#line 90 "hb-ot-shape-complex-myanmar-machine.rl" {te = p;p--;{ found_syllable (non_myanmar_cluster); }} break; -#line 370 "hb-ot-shape-complex-myanmar-machine.hh" +#line 374 "hb-ot-shape-complex-myanmar-machine.hh" } _again: @@ -375,7 +379,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 379 "hb-ot-shape-complex-myanmar-machine.hh" +#line 383 "hb-ot-shape-complex-myanmar-machine.hh" } if ( ++p != pe ) @@ -391,7 +395,7 @@ _again: } -#line 123 "hb-ot-shape-complex-myanmar-machine.rl" +#line 124 "hb-ot-shape-complex-myanmar-machine.rl" } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc index bb68622e2a..5ea1dbff27 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc @@ -103,7 +103,7 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++) { map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ); - map->add_gsub_pause (NULL); + map->add_gsub_pause (nullptr); } map->add_gsub_pause (final_reordering); for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) @@ -130,8 +130,7 @@ enum syllable_type_t { /* Note: This enum is duplicated in the -machine.rl source file. * Not sure how to avoid duplication. */ enum myanmar_category_t { - OT_As = 18, /* Asat */ - OT_D = 19, /* Digits except zero */ + OT_As = 18, /* Asat */ OT_D0 = 20, /* Digit zero */ OT_DB = OT_N, /* Dot below */ OT_GB = OT_PLACEHOLDER, @@ -145,7 +144,8 @@ enum myanmar_category_t { OT_VPre = 28, OT_VPst = 29, OT_VS = 30, /* Variation selectors */ - OT_P = 31 /* Punctuation */ + OT_P = 31, /* Punctuation */ + OT_D = 32, /* Digits except zero */ }; @@ -154,7 +154,7 @@ is_one_of (const hb_glyph_info_t &info, unsigned int flags) { /* If it ligated, all bets are off. */ if (_hb_glyph_info_ligated (&info)) return false; - return !!(FLAG_SAFE (info.myanmar_category()) & flags); + return !!(FLAG_UNSAFE (info.myanmar_category()) & flags); } static inline bool @@ -175,7 +175,7 @@ set_myanmar_properties (hb_glyph_info_t &info) /* Myanmar * http://www.microsoft.com/typography/OpenTypeDev/myanmar/intro.htm#analyze */ - if (unlikely (hb_in_range (u, 0xFE00u, 0xFE0Fu))) + if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu))) cat = (indic_category_t) OT_VS; switch (u) @@ -297,6 +297,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer) { find_syllables (buffer); + foreach_syllable (buffer, start, end) + buffer->unsafe_to_break (start, end); } static int @@ -510,36 +512,36 @@ final_reordering (const hb_ot_shape_plan_t *plan, * generic shaper, except that it zeros mark advances GDEF_LATE. */ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old = { - "default", - NULL, /* collect_features */ - NULL, /* override_features */ - NULL, /* data_create */ - NULL, /* data_destroy */ - NULL, /* preprocess_text */ - NULL, /* postprocess_glyphs */ + nullptr, /* collect_features */ + nullptr, /* override_features */ + nullptr, /* data_create */ + nullptr, /* data_destroy */ + nullptr, /* preprocess_text */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, - NULL, /* decompose */ - NULL, /* compose */ - NULL, /* setup_masks */ - NULL, /* disable_otl */ + nullptr, /* decompose */ + nullptr, /* compose */ + nullptr, /* setup_masks */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar = { - "myanmar", collect_features_myanmar, override_features_myanmar, - NULL, /* data_create */ - NULL, /* data_destroy */ - NULL, /* preprocess_text */ - NULL, /* postprocess_glyphs */ + nullptr, /* data_create */ + nullptr, /* data_destroy */ + nullptr, /* preprocess_text */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, - NULL, /* decompose */ - NULL, /* compose */ + nullptr, /* decompose */ + nullptr, /* compose */ setup_masks_myanmar, - NULL, /* disable_otl */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh index 39572dfe00..fb2f61157a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-private.hh @@ -39,6 +39,8 @@ #define complex_var_u8_1() var2.u8[3] +#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32 + enum hb_ot_shape_zero_width_marks_type_t { HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE, HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, @@ -63,12 +65,10 @@ enum hb_ot_shape_zero_width_marks_type_t { struct hb_ot_complex_shaper_t { - char name[8]; - /* collect_features() * Called during shape_plan(). * Shapers should use plan->map to add their features and callbacks. - * May be NULL. + * May be nullptr. */ void (*collect_features) (hb_ot_shape_planner_t *plan); @@ -76,7 +76,7 @@ struct hb_ot_complex_shaper_t * Called during shape_plan(). * Shapers should use plan->map to override features and add callbacks after * common features are added. - * May be NULL. + * May be nullptr. */ void (*override_features) (hb_ot_shape_planner_t *plan); @@ -84,15 +84,15 @@ struct hb_ot_complex_shaper_t /* data_create() * Called at the end of shape_plan(). * Whatever shapers return will be accessible through plan->data later. - * If NULL is returned, means a plan failure. + * If nullptr is returned, means a plan failure. */ void *(*data_create) (const hb_ot_shape_plan_t *plan); /* data_destroy() * Called when the shape_plan is being destroyed. * plan->data is passed here for destruction. - * If NULL is returned, means a plan failure. - * May be NULL. + * If nullptr is returned, means a plan failure. + * May be nullptr. */ void (*data_destroy) (void *data); @@ -100,7 +100,7 @@ struct hb_ot_complex_shaper_t /* preprocess_text() * Called during shape(). * Shapers can use to modify text before shaping starts. - * May be NULL. + * May be nullptr. */ void (*preprocess_text) (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, @@ -109,7 +109,7 @@ struct hb_ot_complex_shaper_t /* postprocess_glyphs() * Called during shape(). * Shapers can use to modify glyphs after shaping ends. - * May be NULL. + * May be nullptr. */ void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, @@ -120,7 +120,7 @@ struct hb_ot_complex_shaper_t /* decompose() * Called during shape()'s normalization. - * May be NULL. + * May be nullptr. */ bool (*decompose) (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t ab, @@ -129,7 +129,7 @@ struct hb_ot_complex_shaper_t /* compose() * Called during shape()'s normalization. - * May be NULL. + * May be nullptr. */ bool (*compose) (const hb_ot_shape_normalize_context_t *c, hb_codepoint_t a, @@ -140,7 +140,7 @@ struct hb_ot_complex_shaper_t * Called during shape(). * Shapers should use map to get feature masks and set on buffer. * Shapers may NOT modify characters. - * May be NULL. + * May be nullptr. */ void (*setup_masks) (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, @@ -150,10 +150,20 @@ struct hb_ot_complex_shaper_t * Called during shape(). * If set and returns true, GDEF/GSUB/GPOS of the font are ignored * and fallback operations used. - * May be NULL. + * May be nullptr. */ bool (*disable_otl) (const hb_ot_shape_plan_t *plan); + /* reorder_marks() + * Called during shape(). + * Shapers can use to modify ordering of combining marks. + * May be nullptr. + */ + void (*reorder_marks) (const hb_ot_shape_plan_t *plan, + hb_buffer_t *buffer, + unsigned int start, + unsigned int end); + hb_ot_shape_zero_width_marks_type_t zero_width_marks; bool fallback_position; @@ -191,6 +201,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_MANICHAEAN: case HB_SCRIPT_PSALTER_PAHLAVI: + /* Unicode-9.0 additions */ + case HB_SCRIPT_ADLAM: + /* For Arabic script, use the Arabic shaper even if no OT script tag was found. * This is because we do fallback shaping for Arabic script (and not others). * But note that Arabic shaping is applicable only to horizontal layout; for @@ -250,10 +263,12 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_SINHALA: /* If the designer designed the font for the 'DFLT' script, - * use the default shaper. Otherwise, use the specific shaper. + * (or we ended up arbitrarily pick 'latn'), use the default shaper. + * Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* * GSUB/GPOS needed, so there may be no scripts found! */ - if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') || + planner->map.chosen_script[0] == HB_TAG ('l','a','t','n')) return &_hb_ot_complex_shaper_default; else return &_hb_ot_complex_shaper_indic; @@ -269,7 +284,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) planner->map.script_index[0], planner->map.language_index[0], HB_TAG ('p','r','e','f'), - NULL)) + nullptr)) return &_hb_ot_complex_shaper_indic; else return &_hb_ot_complex_shaper_default; @@ -359,11 +374,18 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_MARCHEN: case HB_SCRIPT_NEWA: + /* Unicode-10.0 additions */ + case HB_SCRIPT_MASARAM_GONDI: + case HB_SCRIPT_SOYOMBO: + case HB_SCRIPT_ZANABAZAR_SQUARE: + /* If the designer designed the font for the 'DFLT' script, - * use the default shaper. Otherwise, use the specific shaper. + * (or we ended up arbitrarily pick 'latn'), use the default shaper. + * Otherwise, use the specific shaper. * Note that for some simple scripts, there may not be *any* * GSUB/GPOS needed, so there may be no scripts found! */ - if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T')) + if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') || + planner->map.chosen_script[0] == HB_TAG ('l','a','t','n')) return &_hb_ot_complex_shaper_default; else return &_hb_ot_complex_shaper_use; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc index e6f80f59e7..6ba925c675 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc @@ -52,7 +52,7 @@ get_consonant_type (hb_codepoint_t u) return RC; if (u == 0x0E0Eu || u == 0x0E0Fu) return DC; - if (hb_in_range (u, 0x0E01u, 0x0E2Eu)) + if (hb_in_range<hb_codepoint_t> (u, 0x0E01u, 0x0E2Eu)) return NC; return NOT_CONSONANT; } @@ -70,12 +70,12 @@ enum thai_mark_type_t static thai_mark_type_t get_mark_type (hb_codepoint_t u) { - if (u == 0x0E31u || hb_in_range (u, 0x0E34u, 0x0E37u) || - u == 0x0E47u || hb_in_range (u, 0x0E4Du, 0x0E4Eu)) + if (u == 0x0E31u || hb_in_range<hb_codepoint_t> (u, 0x0E34u, 0x0E37u) || + u == 0x0E47u || hb_in_range<hb_codepoint_t> (u, 0x0E4Du, 0x0E4Eu)) return AV; - if (hb_in_range (u, 0x0E38u, 0x0E3Au)) + if (hb_in_range<hb_codepoint_t> (u, 0x0E38u, 0x0E3Au)) return BV; - if (hb_in_range (u, 0x0E48u, 0x0E4Cu)) + if (hb_in_range<hb_codepoint_t> (u, 0x0E48u, 0x0E4Cu)) return T; return NOT_MARK; } @@ -97,7 +97,7 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font) hb_codepoint_t u; hb_codepoint_t win_pua; hb_codepoint_t mac_pua; - } const *pua_mappings = NULL; + } const *pua_mappings = nullptr; static const thai_pua_mapping_t SD_mappings[] = { {0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */ {0x0E49u, 0xF70Bu, 0xF88Eu}, /* MAI THO */ @@ -244,6 +244,7 @@ do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED, /* At least one of the above/below actions is NOP. */ thai_action_t action = above_edge.action != NOP ? above_edge.action : below_edge.action; + buffer->unsafe_to_break (base, i); if (action == RD) info[base].codepoint = thai_pua_shape (info[base].codepoint, action, font); else @@ -310,7 +311,7 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan, #define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u) #define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du) #define SARA_AA_FROM_SARA_AM(x) ((x) - 1) -#define IS_TONE_MARK(x) (hb_in_ranges ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u)) +#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u)) buffer->clear_output (); unsigned int count = buffer->len; @@ -365,18 +366,18 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan, const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai = { - "thai", - NULL, /* collect_features */ - NULL, /* override_features */ - NULL, /* data_create */ - NULL, /* data_destroy */ + nullptr, /* collect_features */ + nullptr, /* override_features */ + nullptr, /* data_create */ + nullptr, /* data_destroy */ preprocess_text_thai, - NULL, /* postprocess_glyphs */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, - NULL, /* decompose */ - NULL, /* compose */ - NULL, /* setup_masks */ - NULL, /* disable_otl */ + nullptr, /* decompose */ + nullptr, /* compose */ + nullptr, /* setup_masks */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, false,/* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc index aadf59f5ad..eaac0bf689 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc @@ -46,18 +46,18 @@ collect_features_tibetan (hb_ot_shape_planner_t *plan) const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan = { - "default", collect_features_tibetan, - NULL, /* override_features */ - NULL, /* data_create */ - NULL, /* data_destroy */ - NULL, /* preprocess_text */ - NULL, /* postprocess_glyphs */ + nullptr, /* override_features */ + nullptr, /* data_create */ + nullptr, /* data_destroy */ + nullptr, /* preprocess_text */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, - NULL, /* decompose */ - NULL, /* compose */ - NULL, /* setup_masks */ - NULL, /* disable_otl */ + nullptr, /* decompose */ + nullptr, /* compose */ + nullptr, /* setup_masks */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE, true, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh index 44e5d0d56b..4f6727186d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-machine.hh @@ -36,33 +36,33 @@ #line 38 "hb-ot-shape-complex-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { - 1u, 1u, 0u, 39u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, + 1u, 1u, 0u, 43u, 21u, 21u, 8u, 39u, 8u, 39u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u, - 4u, 4u, 13u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, - 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, - 8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, - 42u, 42u, 0 + 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, + 13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, + 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, + 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 1u, 1u, 1u, 39u, 8u, 39u, + 21u, 42u, 41u, 42u, 42u, 42u, 1u, 5u, 0 }; static const char _use_syllable_machine_key_spans[] = { - 1, 40, 1, 32, 32, 1, 32, 32, + 1, 44, 1, 32, 32, 1, 32, 32, 32, 19, 19, 19, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 9, - 1, 1, 32, 32, 32, 32, 19, 19, - 19, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 1, 39, 32, 22, 2, - 1 + 32, 32, 32, 32, 32, 32, 32, 32, + 9, 1, 1, 32, 32, 32, 32, 19, + 19, 19, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 1, 39, 32, + 22, 2, 1, 5 }; static const short _use_syllable_machine_index_offsets[] = { - 0, 2, 43, 45, 78, 111, 113, 146, - 179, 212, 232, 252, 272, 305, 338, 371, - 404, 437, 470, 503, 536, 569, 602, 635, - 645, 647, 649, 682, 715, 748, 781, 801, - 821, 841, 874, 907, 940, 973, 1006, 1039, - 1072, 1105, 1138, 1171, 1173, 1213, 1246, 1269, - 1272 + 0, 2, 47, 49, 82, 115, 117, 150, + 183, 216, 236, 256, 276, 309, 342, 375, + 408, 441, 474, 507, 540, 573, 606, 639, + 672, 682, 684, 686, 719, 752, 785, 818, + 838, 858, 878, 911, 944, 977, 1010, 1043, + 1076, 1109, 1142, 1175, 1208, 1241, 1243, 1283, + 1316, 1339, 1342, 1344 }; static const char _use_syllable_machine_indicies[] = { @@ -71,183 +71,192 @@ static const char _use_syllable_machine_indicies[] = { 4, 4, 2, 2, 8, 9, 4, 4, 10, 11, 12, 13, 14, 15, 16, 10, 17, 18, 19, 20, 21, 22, 4, 23, - 24, 25, 4, 27, 26, 29, 28, 28, - 30, 31, 28, 28, 28, 28, 28, 28, - 28, 28, 32, 33, 34, 35, 36, 37, - 38, 39, 33, 40, 32, 41, 42, 43, - 44, 28, 45, 46, 47, 28, 29, 28, - 28, 30, 31, 28, 28, 28, 28, 28, - 28, 28, 28, 48, 33, 34, 35, 36, - 37, 38, 39, 33, 40, 41, 41, 42, - 43, 44, 28, 45, 46, 47, 28, 30, - 49, 29, 28, 28, 30, 31, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 33, - 34, 35, 36, 37, 38, 39, 33, 40, - 41, 41, 42, 43, 44, 28, 45, 46, - 47, 28, 29, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 33, 34, 35, 36, 37, 28, 28, 28, - 28, 28, 28, 42, 43, 44, 28, 45, - 46, 47, 28, 29, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 34, 35, 36, 37, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 45, 46, 47, 28, 29, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 35, 36, 37, 28, - 29, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 36, 37, 28, 29, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 37, 28, - 29, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 35, 36, 37, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 45, 46, 47, - 28, 29, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 35, 36, 37, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 46, - 47, 28, 29, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 35, 36, 37, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 47, 28, 29, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 34, 35, 36, 37, 28, 28, - 28, 28, 28, 28, 42, 43, 44, 28, - 45, 46, 47, 28, 29, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 34, 35, 36, 37, 28, - 28, 28, 28, 28, 28, 28, 43, 44, - 28, 45, 46, 47, 28, 29, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 34, 35, 36, 37, - 28, 28, 28, 28, 28, 28, 28, 28, - 44, 28, 45, 46, 47, 28, 29, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 33, 34, 35, 36, - 37, 28, 39, 33, 28, 28, 28, 42, - 43, 44, 28, 45, 46, 47, 28, 29, - 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 33, 34, 35, - 36, 37, 28, 28, 33, 28, 28, 28, - 42, 43, 44, 28, 45, 46, 47, 28, - 29, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 33, 34, - 35, 36, 37, 38, 39, 33, 28, 28, - 28, 42, 43, 44, 28, 45, 46, 47, - 28, 29, 28, 28, 30, 31, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 33, - 34, 35, 36, 37, 38, 39, 33, 40, - 28, 41, 42, 43, 44, 28, 45, 46, - 47, 28, 29, 28, 28, 30, 31, 28, - 28, 28, 28, 28, 28, 28, 28, 28, - 33, 34, 35, 36, 37, 38, 39, 33, - 40, 32, 41, 42, 43, 44, 28, 45, - 46, 47, 28, 51, 50, 50, 50, 50, - 50, 50, 50, 52, 50, 5, 53, 51, - 50, 6, 54, 54, 1, 55, 54, 54, - 54, 54, 54, 54, 54, 54, 56, 10, - 11, 12, 13, 14, 15, 16, 10, 17, - 19, 19, 20, 21, 22, 54, 23, 24, - 25, 54, 6, 54, 54, 1, 55, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 10, 11, 12, 13, 14, 15, 16, 10, - 17, 19, 19, 20, 21, 22, 54, 23, - 24, 25, 54, 6, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 10, 11, 12, 13, 14, 54, 54, - 54, 54, 54, 54, 20, 21, 22, 54, - 23, 24, 25, 54, 6, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 11, 12, 13, 14, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 23, 24, 25, 54, 6, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 12, 13, 14, - 54, 6, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 13, 14, 54, 6, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 14, - 54, 6, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 12, 13, 14, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 23, 24, - 25, 54, 6, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 12, 13, 14, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 24, 25, 54, 6, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 12, 13, 14, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 25, 54, 6, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 11, 12, 13, 14, 54, - 54, 54, 54, 54, 54, 20, 21, 22, - 54, 23, 24, 25, 54, 6, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 11, 12, 13, 14, - 54, 54, 54, 54, 54, 54, 54, 21, - 22, 54, 23, 24, 25, 54, 6, 54, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 11, 12, 13, - 14, 54, 54, 54, 54, 54, 54, 54, - 54, 22, 54, 23, 24, 25, 54, 6, - 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 10, 11, 12, - 13, 14, 54, 16, 10, 54, 54, 54, - 20, 21, 22, 54, 23, 24, 25, 54, - 6, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 10, 11, - 12, 13, 14, 54, 54, 10, 54, 54, - 54, 20, 21, 22, 54, 23, 24, 25, - 54, 6, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 10, - 11, 12, 13, 14, 15, 16, 10, 54, - 54, 54, 20, 21, 22, 54, 23, 24, - 25, 54, 6, 54, 54, 1, 55, 54, - 54, 54, 54, 54, 54, 54, 54, 54, + 24, 25, 4, 4, 4, 26, 4, 28, + 27, 30, 29, 29, 31, 32, 29, 29, + 29, 29, 29, 29, 29, 29, 33, 34, + 35, 36, 37, 38, 39, 40, 34, 41, + 33, 42, 43, 44, 45, 29, 46, 47, + 48, 29, 30, 29, 29, 31, 32, 29, + 29, 29, 29, 29, 29, 29, 29, 49, + 34, 35, 36, 37, 38, 39, 40, 34, + 41, 42, 42, 43, 44, 45, 29, 46, + 47, 48, 29, 31, 50, 30, 29, 29, + 31, 32, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 34, 35, 36, 37, 38, + 39, 40, 34, 41, 42, 42, 43, 44, + 45, 29, 46, 47, 48, 29, 30, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 34, 35, 36, 37, + 38, 29, 29, 29, 29, 29, 29, 43, + 44, 45, 29, 46, 47, 48, 29, 30, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 35, 36, + 37, 38, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 46, 47, 48, 29, + 30, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 36, 37, 38, 29, 30, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 37, 38, 29, + 30, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 38, 29, 30, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 36, 37, 38, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 46, 47, 48, 29, 30, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 36, 37, 38, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 47, 48, 29, 30, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 36, 37, + 38, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 48, 29, 30, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 35, 36, + 37, 38, 29, 29, 29, 29, 29, 29, + 43, 44, 45, 29, 46, 47, 48, 29, + 30, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 35, + 36, 37, 38, 29, 29, 29, 29, 29, + 29, 29, 44, 45, 29, 46, 47, 48, + 29, 30, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 35, 36, 37, 38, 29, 29, 29, 29, + 29, 29, 29, 29, 45, 29, 46, 47, + 48, 29, 30, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 34, 35, 36, 37, 38, 29, 40, 34, + 29, 29, 29, 43, 44, 45, 29, 46, + 47, 48, 29, 30, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 34, 35, 36, 37, 38, 29, 51, + 34, 29, 29, 29, 43, 44, 45, 29, + 46, 47, 48, 29, 30, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 34, 35, 36, 37, 38, 29, + 29, 34, 29, 29, 29, 43, 44, 45, + 29, 46, 47, 48, 29, 30, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 34, 35, 36, 37, 38, + 39, 40, 34, 29, 29, 29, 43, 44, + 45, 29, 46, 47, 48, 29, 30, 29, + 29, 31, 32, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 34, 35, 36, 37, + 38, 39, 40, 34, 41, 29, 42, 43, + 44, 45, 29, 46, 47, 48, 29, 30, + 29, 29, 31, 32, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 34, 35, 36, + 37, 38, 39, 40, 34, 41, 33, 42, + 43, 44, 45, 29, 46, 47, 48, 29, + 53, 52, 52, 52, 52, 52, 52, 52, + 54, 52, 5, 55, 53, 52, 6, 56, + 56, 1, 57, 56, 56, 56, 56, 56, + 56, 56, 56, 58, 10, 11, 12, 13, + 14, 15, 16, 10, 17, 19, 19, 20, + 21, 22, 56, 23, 24, 25, 56, 6, + 56, 56, 1, 57, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 10, 11, 12, + 13, 14, 15, 16, 10, 17, 19, 19, + 20, 21, 22, 56, 23, 24, 25, 56, + 6, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 10, 11, + 12, 13, 14, 56, 56, 56, 56, 56, + 56, 20, 21, 22, 56, 23, 24, 25, + 56, 6, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 11, 12, 13, 14, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 23, 24, + 25, 56, 6, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 12, 13, 14, 56, 6, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 13, + 14, 56, 6, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 14, 56, 6, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 12, 13, + 14, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 23, 24, 25, 56, 6, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 12, + 13, 14, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 24, 25, 56, + 6, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 12, 13, 14, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 25, + 56, 6, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 11, 12, 13, 14, 56, 56, 56, 56, + 56, 56, 20, 21, 22, 56, 23, 24, + 25, 56, 6, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 11, 12, 13, 14, 56, 56, 56, + 56, 56, 56, 56, 21, 22, 56, 23, + 24, 25, 56, 6, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 11, 12, 13, 14, 56, 56, + 56, 56, 56, 56, 56, 56, 22, 56, + 23, 24, 25, 56, 6, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 10, 11, 12, 13, 14, 56, + 16, 10, 56, 56, 56, 20, 21, 22, + 56, 23, 24, 25, 56, 6, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 10, 11, 12, 13, 14, + 56, 59, 10, 56, 56, 56, 20, 21, + 22, 56, 23, 24, 25, 56, 6, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 10, 11, 12, 13, + 14, 56, 56, 10, 56, 56, 56, 20, + 21, 22, 56, 23, 24, 25, 56, 6, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 10, 11, 12, + 13, 14, 15, 16, 10, 56, 56, 56, + 20, 21, 22, 56, 23, 24, 25, 56, + 6, 56, 56, 1, 57, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 10, 11, + 12, 13, 14, 15, 16, 10, 17, 56, + 19, 20, 21, 22, 56, 23, 24, 25, + 56, 1, 60, 3, 56, 56, 56, 3, + 56, 56, 6, 56, 56, 1, 57, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 10, 11, 12, 13, 14, 15, 16, 10, - 17, 54, 19, 20, 21, 22, 54, 23, - 24, 25, 54, 1, 57, 3, 54, 54, - 54, 3, 54, 54, 6, 54, 54, 1, - 55, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 10, 11, 12, 13, 14, 15, - 16, 10, 17, 18, 19, 20, 21, 22, - 54, 23, 24, 25, 54, 6, 54, 54, - 1, 55, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 10, 11, 12, 13, 14, - 15, 16, 10, 17, 18, 19, 20, 21, - 22, 54, 23, 24, 25, 54, 59, 58, - 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 58, 58, 58, 58, 58, 58, - 58, 58, 59, 60, 58, 59, 60, 58, - 60, 58, 0 + 17, 18, 19, 20, 21, 22, 56, 23, + 24, 25, 56, 6, 56, 56, 1, 57, + 56, 56, 56, 56, 56, 56, 56, 56, + 56, 10, 11, 12, 13, 14, 15, 16, + 10, 17, 18, 19, 20, 21, 22, 56, + 23, 24, 25, 56, 62, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, + 62, 63, 61, 62, 63, 61, 63, 61, + 3, 60, 60, 60, 3, 60, 0 }; static const char _use_syllable_machine_trans_targs[] = { - 1, 26, 2, 3, 1, 23, 1, 43, - 44, 46, 28, 29, 30, 31, 32, 39, - 40, 41, 45, 42, 36, 37, 38, 33, - 34, 35, 1, 1, 1, 1, 4, 5, - 22, 7, 8, 9, 10, 11, 18, 19, - 20, 21, 15, 16, 17, 12, 13, 14, - 6, 1, 1, 24, 25, 1, 1, 0, - 27, 1, 1, 47, 48 + 1, 27, 2, 3, 1, 24, 1, 45, + 46, 48, 29, 30, 31, 32, 33, 40, + 41, 43, 47, 44, 37, 38, 39, 34, + 35, 36, 51, 1, 1, 1, 1, 4, + 5, 23, 7, 8, 9, 10, 11, 18, + 19, 21, 22, 15, 16, 17, 12, 13, + 14, 6, 1, 20, 1, 25, 26, 1, + 1, 0, 28, 42, 1, 1, 49, 50 }; static const char _use_syllable_machine_trans_actions[] = { 1, 2, 0, 0, 5, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, - 0, 0, 7, 8, 9, 10, 0, 0, + 0, 0, 0, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 11, 12, 0, 0, 13, 14, 0, - 2, 15, 16, 0, 0 + 0, 0, 11, 0, 12, 0, 0, 13, + 14, 0, 2, 0, 15, 16, 0, 0 }; static const char _use_syllable_machine_to_state_actions[] = { @@ -257,7 +266,7 @@ static const char _use_syllable_machine_to_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0, 0, 0 }; static const char _use_syllable_machine_from_state_actions[] = { @@ -267,17 +276,17 @@ static const char _use_syllable_machine_from_state_actions[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 0, 0, 0, 0 }; static const short _use_syllable_machine_eof_trans[] = { - 1, 0, 27, 29, 29, 50, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 51, - 54, 51, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 58, 55, 55, 59, 59, - 59 + 1, 0, 28, 30, 30, 51, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, + 53, 56, 53, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 61, 57, 57, + 62, 62, 62, 61 }; static const int use_syllable_machine_start = 1; @@ -291,7 +300,7 @@ static const int use_syllable_machine_en_main = 1; -#line 138 "hb-ot-shape-complex-use-machine.rl" +#line 140 "hb-ot-shape-complex-use-machine.rl" #define found_syllable(syllable_type) \ @@ -311,7 +320,7 @@ find_syllables (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 315 "hb-ot-shape-complex-use-machine.hh" +#line 324 "hb-ot-shape-complex-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -319,7 +328,7 @@ find_syllables (hb_buffer_t *buffer) act = 0; } -#line 159 "hb-ot-shape-complex-use-machine.rl" +#line 161 "hb-ot-shape-complex-use-machine.rl" p = 0; @@ -328,7 +337,7 @@ find_syllables (hb_buffer_t *buffer) unsigned int last = 0; unsigned int syllable_serial = 1; -#line 332 "hb-ot-shape-complex-use-machine.hh" +#line 341 "hb-ot-shape-complex-use-machine.hh" { int _slen; int _trans; @@ -342,7 +351,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 346 "hb-ot-shape-complex-use-machine.hh" +#line 355 "hb-ot-shape-complex-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -365,58 +374,58 @@ _eof_trans: {te = p+1;} break; case 8: -#line 127 "hb-ot-shape-complex-use-machine.rl" +#line 129 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (independent_cluster); }} break; case 10: -#line 129 "hb-ot-shape-complex-use-machine.rl" +#line 131 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (standard_cluster); }} break; case 6: -#line 133 "hb-ot-shape-complex-use-machine.rl" +#line 135 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (broken_cluster); }} break; case 5: -#line 134 "hb-ot-shape-complex-use-machine.rl" +#line 136 "hb-ot-shape-complex-use-machine.rl" {te = p+1;{ found_syllable (non_cluster); }} break; case 7: -#line 127 "hb-ot-shape-complex-use-machine.rl" +#line 129 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (independent_cluster); }} break; case 11: -#line 128 "hb-ot-shape-complex-use-machine.rl" +#line 130 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (virama_terminated_cluster); }} break; case 9: -#line 129 "hb-ot-shape-complex-use-machine.rl" +#line 131 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (standard_cluster); }} break; case 13: -#line 130 "hb-ot-shape-complex-use-machine.rl" +#line 132 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }} break; case 12: -#line 131 "hb-ot-shape-complex-use-machine.rl" +#line 133 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (numeral_cluster); }} break; case 16: -#line 132 "hb-ot-shape-complex-use-machine.rl" +#line 134 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (symbol_cluster); }} break; case 14: -#line 133 "hb-ot-shape-complex-use-machine.rl" +#line 135 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (broken_cluster); }} break; case 15: -#line 134 "hb-ot-shape-complex-use-machine.rl" +#line 136 "hb-ot-shape-complex-use-machine.rl" {te = p;p--;{ found_syllable (non_cluster); }} break; case 1: -#line 133 "hb-ot-shape-complex-use-machine.rl" +#line 135 "hb-ot-shape-complex-use-machine.rl" {{p = ((te))-1;}{ found_syllable (broken_cluster); }} break; -#line 420 "hb-ot-shape-complex-use-machine.hh" +#line 429 "hb-ot-shape-complex-use-machine.hh" } _again: @@ -425,7 +434,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 429 "hb-ot-shape-complex-use-machine.hh" +#line 438 "hb-ot-shape-complex-use-machine.hh" } if ( ++p != pe ) @@ -441,7 +450,7 @@ _again: } -#line 168 "hb-ot-shape-complex-use-machine.rl" +#line 170 "hb-ot-shape-complex-use-machine.rl" } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-private.hh index ae428cb5eb..3e763ae393 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-private.hh @@ -87,7 +87,8 @@ enum use_category_t { USE_VMPst = 39, /* VOWEL_MOD_POST */ USE_VMPre = 23, /* VOWEL_MOD_PRE */ USE_SMAbv = 41, /* SYM_MOD_ABOVE */ - USE_SMBlw = 42 /* SYM_MOD_BELOW */ + USE_SMBlw = 42, /* SYM_MOD_BELOW */ + USE_CS = 43 /* CONS_WITH_STACKER */ }; HB_INTERNAL USE_TABLE_ELEMENT_TYPE diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.cc index 38c46d002d..fd6978f281 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use-table.cc @@ -6,12 +6,12 @@ * * on files with these headers: * - * # IndicSyllabicCategory-9.0.0.txt - * # Date: 2016-05-21, 02:46:00 GMT [RP] - * # IndicPositionalCategory-9.0.0.txt - * # Date: 2016-02-25, 00:48:00 GMT [RP] - * # Blocks-9.0.0.txt - * # Date: 2016-02-05, 23:48:00 GMT [KW] + * # IndicSyllabicCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [KW, RP] + * # IndicPositionalCategory-10.0.0.txt + * # Date: 2017-05-31, 01:07:00 GMT [RP] + * # Blocks-10.0.0.txt + * # Date: 2017-04-12, 17:30:00 GMT [KW] * UnicodeData.txt does not have a header. */ @@ -19,6 +19,7 @@ #define B USE_B /* BASE */ #define CGJ USE_CGJ /* CGJ */ +#define CS USE_CS /* CONS_WITH_STACKER */ #define FM USE_FM /* CONS_FINAL_MOD */ #define GB USE_GB /* BASE_OTHER */ #define H USE_H /* HALANT */ @@ -97,7 +98,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, IND, O, /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B, /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, O, O, /* Gurmukhi */ @@ -119,7 +120,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O, /* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* 0AE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, O, O, O, O, O, O, + /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv, /* Oriya */ @@ -163,14 +164,14 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O, /* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O, /* 0CE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, - /* 0CF0 */ O, R, R, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* 0CF0 */ O, CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O, /* Malayalam */ - /* 0D00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, + /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B, /* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, O, O, B, VPst, VPst, + /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst, /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O, /* 0D50 */ O, O, O, O, IND, IND, IND, VPst, O, O, O, O, O, O, O, B, /* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B, @@ -274,9 +275,9 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* 1A50 */ B, B, B, B, B, MPre, MBlw, FPst, FAbv, FAbv, FAbv, FBlw, FBlw, FBlw, FBlw, O, + /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, FAbv, SUB, SUB, SUB, SUB, O, /* 1A60 */ H, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre, - /* 1A70 */ VPre, VPre, VPre, VAbv, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, FM, FM, FM, O, O, FM, + /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, FM, FM, O, O, FBlw, /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -323,7 +324,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw, /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O, - /* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, O, VMAbv, VMAbv, O, O, O, O, O, O, + /* 1CF0 */ O, O, VMPst, VMPst, VMAbv, O, O, VMPst, VMAbv, VMAbv, O, O, O, O, O, O, #define use_offset_0x1df8u 2552 @@ -347,7 +348,14 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 2070 */ O, O, O, O, FM, O, O, O, O, O, O, O, O, O, O, O, /* 2080 */ O, O, FM, FM, FM, O, O, O, -#define use_offset_0xa800u 2616 +#define use_offset_0x20f0u 2616 + + + /* Combining Diacritical Marks for Symbols */ + + /* 20F0 */ VMAbv, O, O, O, O, O, O, O, + +#define use_offset_0xa800u 2624 /* Syloti Nagri */ @@ -369,14 +377,14 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* A880 */ VMPst, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A8B0 */ B, B, B, B, FPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, + /* A8B0 */ B, B, B, B, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, O, O, O, O, O, O, O, O, O, O, /* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, /* Devanagari Extended */ /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, - /* A8F0 */ VMAbv, VMAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, + /* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, O, O, /* Kayah Li */ @@ -397,7 +405,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MPst, + /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, SUB, MPst, MBlw, /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, /* A9D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -410,7 +418,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, - /* AA20 */ B, B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, + /* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre, /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MBlw, MBlw, O, O, O, O, O, O, O, O, O, /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O, /* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, @@ -434,7 +442,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst, /* AAF0 */ O, O, O, O, O, VMPst, H, O, -#define use_offset_0xabc0u 3376 +#define use_offset_0xabc0u 3384 /* Meetei Mayek */ @@ -444,14 +452,14 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O, /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0xfe00u 3440 +#define use_offset_0xfe00u 3448 /* Variation Selectors */ /* FE00 */ VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, VS, -#define use_offset_0x10a00u 3456 +#define use_offset_0x10a00u 3464 /* Kharoshthi */ @@ -462,12 +470,12 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 10A30 */ B, B, B, B, O, O, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H, /* 10A40 */ B, B, B, B, B, B, B, B, -#define use_offset_0x11000u 3528 +#define use_offset_0x11000u 3536 /* Brahmi */ - /* 11000 */ VMPst, VMAbv, VMPst, R, R, B, B, B, B, B, B, B, B, B, B, B, + /* 11000 */ VMPst, VMAbv, VMPst, CS, CS, B, B, B, B, B, B, B, B, B, B, B, /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, @@ -483,7 +491,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O, -#define use_offset_0x11100u 3720 +#define use_offset_0x11100u 3728 /* Chakma */ @@ -521,7 +529,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw, /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O, -#define use_offset_0x11280u 4040 +#define use_offset_0x11280u 4048 /* Multani */ @@ -545,11 +553,11 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPst, /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O, - /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O, + /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B, /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, -#define use_offset_0x11400u 4288 +#define use_offset_0x11400u 4296 /* Newa */ @@ -572,7 +580,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 114C0 */ VMAbv, VMPst, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O, /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, -#define use_offset_0x11580u 4512 +#define use_offset_0x11580u 4520 /* Siddham */ @@ -615,7 +623,26 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O, /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, -#define use_offset_0x11c00u 4960 +#define use_offset_0x11a00u 4968 + + + /* Zanabazar Square */ + + /* 11A00 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, B, B, B, B, B, + /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A30 */ B, B, B, FM, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB, + /* 11A40 */ O, O, O, O, O, GB, O, H, O, O, O, O, O, O, O, O, + + /* Soyombo */ + + /* 11A50 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VBlw, VBlw, VBlw, B, B, B, B, + /* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11A80 */ B, B, B, B, O, O, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, + /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, O, O, O, + +#define use_offset_0x11c00u 5128 /* Bhaiksuki */ @@ -636,7 +663,19 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O, -}; /* Table items: 5144; occupancy: 72% */ +#define use_offset_0x11d00u 5312 + + + /* Masaram Gondi */ + + /* 11D00 */ B, B, B, B, B, B, B, O, B, B, O, B, B, B, B, B, + /* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, + /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, O, O, O, VAbv, O, VAbv, VAbv, O, VAbv, + /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, H, R, MBlw, O, O, O, O, O, O, O, O, + /* 11D50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, + +}; /* Table items: 5408; occupancy: 73% */ USE_TABLE_ELEMENT_TYPE hb_use_get_categories (hb_codepoint_t u) @@ -644,47 +683,50 @@ hb_use_get_categories (hb_codepoint_t u) switch (u >> 12) { case 0x0u: - if (hb_in_range (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u]; - if (hb_in_range (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; - if (hb_in_range (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u]; + if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u]; + if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u]; if (unlikely (u == 0x034Fu)) return CGJ; break; case 0x1u: - if (hb_in_range (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u]; - if (hb_in_range (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u]; - if (hb_in_range (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u]; - if (hb_in_range (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u]; - if (hb_in_range (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u]; - if (hb_in_range (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1700u, 0x17EFu)) return use_table[u - 0x1700u + use_offset_0x1700u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u]; + if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u]; break; case 0x2u: - if (hb_in_range (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u]; - if (hb_in_range (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u]; + if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u]; + if (hb_in_range<hb_codepoint_t> (u, 0x2060u, 0x2087u)) return use_table[u - 0x2060u + use_offset_0x2060u]; + if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u]; if (unlikely (u == 0x25CCu)) return GB; break; case 0xAu: - if (hb_in_range (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u]; - if (hb_in_range (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u]; + if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u]; + if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u]; break; case 0xFu: - if (hb_in_range (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; + if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u]; break; case 0x10u: - if (hb_in_range (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; + if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A47u)) return use_table[u - 0x10A00u + use_offset_0x10a00u]; break; case 0x11u: - if (hb_in_range (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u]; - if (hb_in_range (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u]; - if (hb_in_range (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; - if (hb_in_range (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u]; - if (hb_in_range (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u]; - if (hb_in_range (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11000u, 0x110BFu)) return use_table[u - 0x11000u + use_offset_0x11000u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x1173Fu)) return use_table[u - 0x11580u + use_offset_0x11580u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11A00u, 0x11A9Fu)) return use_table[u - 0x11A00u + use_offset_0x11a00u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u]; + if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11D5Fu)) return use_table[u - 0x11D00u + use_offset_0x11d00u]; if (unlikely (u == 0x1107Fu)) return HN; break; @@ -696,6 +738,7 @@ hb_use_get_categories (hb_codepoint_t u) #undef B #undef CGJ +#undef CS #undef FM #undef GB #undef H diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc index 5b19d5d74a..62acd697bd 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-complex-use.cc @@ -144,7 +144,7 @@ collect_features_use (hb_ot_shape_planner_t *plan) /* "Topographical features" */ for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++) map->add_feature (arabic_features[i], 1, F_NONE); - map->add_gsub_pause (NULL); + map->add_gsub_pause (nullptr); /* "Standard typographic presentation" and "Positional feature application" */ for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++) @@ -199,7 +199,7 @@ data_create_use (const hb_ot_shape_plan_t *plan) { use_shape_plan_t *use_plan = (use_shape_plan_t *) calloc (1, sizeof (use_shape_plan_t)); if (unlikely (!use_plan)) - return NULL; + return nullptr; use_plan->rphf_mask = plan->map.get_1_mask (HB_TAG('r','p','h','f')); @@ -209,7 +209,7 @@ data_create_use (const hb_ot_shape_plan_t *plan) if (unlikely (!use_plan->arabic_plan)) { free (use_plan); - return NULL; + return nullptr; } } @@ -292,7 +292,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, if (use_plan->arabic_plan) return; - ASSERT_STATIC (INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4); + static_assert ((INIT < 4 && ISOL < 4 && MEDI < 4 && FINA < 4), ""); hb_mask_t masks[4], all_masks = 0; for (unsigned int i = 0; i < 4; i++) { @@ -354,6 +354,8 @@ setup_syllables (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) { find_syllables (buffer); + foreach_syllable (buffer, start, end) + buffer->unsafe_to_break (start, end); setup_rphf_mask (plan, buffer); setup_topographical_masks (plan, buffer); } @@ -422,7 +424,7 @@ reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end) { syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F); /* Only a few syllable types need reordering. */ - if (unlikely (!(FLAG_SAFE (syllable_type) & + if (unlikely (!(FLAG_UNSAFE (syllable_type) & (FLAG (virama_terminated_cluster) | FLAG (standard_cluster) | FLAG (broken_cluster) | @@ -572,28 +574,6 @@ decompose_use (const hb_ot_shape_normalize_context_t *c, */ case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true; case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true; - - /* - * Decompose split matras that don't have Unicode decompositions. - */ - - /* Limbu */ - case 0x1925u : *a = 0x1920u; *b= 0x1923u; return true; - case 0x1926u : *a = 0x1920u; *b= 0x1924u; return true; - - /* Balinese */ - case 0x1B3Cu : *a = 0x1B42u; *b= 0x1B3Cu; return true; - -#if 0 - /* Lepcha */ - case 0x1C29u : *a = no decomp, -> LEFT; return true; - - /* Javanese */ - case 0xA9C0u : *a = no decomp, -> RIGHT; return true; - - /* Sharada */ - case 0x111BFu : *a = no decomp, -> ABOVE; return true; -#endif } return (bool) c->unicode->decompose (ab, a, b); @@ -615,18 +595,18 @@ compose_use (const hb_ot_shape_normalize_context_t *c, const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use = { - "use", collect_features_use, - NULL, /* override_features */ + nullptr, /* override_features */ data_create_use, data_destroy_use, - NULL, /* preprocess_text */ - NULL, /* postprocess_glyphs */ + nullptr, /* preprocess_text */ + nullptr, /* postprocess_glyphs */ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, decompose_use, compose_use, setup_masks_use, - NULL, /* disable_otl */ + nullptr, /* disable_otl */ + nullptr, /* reorder_marks */ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY, false, /* fallback_position */ }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc index ea8312b223..458c8eaa04 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-fallback.cc @@ -210,7 +210,7 @@ position_mark (const hb_ot_shape_plan_t *plan, pos.x_offset = pos.y_offset = 0; - /* We dont position LEFT and RIGHT marks. */ + /* We don't position LEFT and RIGHT marks. */ /* X positioning */ switch (combining_class) @@ -218,10 +218,10 @@ position_mark (const hb_ot_shape_plan_t *plan, case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW: case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE: if (buffer->props.direction == HB_DIRECTION_LTR) { - pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing; + pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing; break; } else if (buffer->props.direction == HB_DIRECTION_RTL) { - pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing; + pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing; break; } HB_FALLTHROUGH; @@ -307,6 +307,9 @@ position_around_base (const hb_ot_shape_plan_t *plan, unsigned int end) { hb_direction_t horiz_dir = HB_DIRECTION_INVALID; + + buffer->unsafe_to_break (base, end); + hb_glyph_extents_t base_extents; if (!font->get_glyph_extents (buffer->info[base].codepoint, &base_extents)) 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 107617e81c..fd9e7c2a8d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc @@ -91,7 +91,7 @@ compose_unicode (const hb_ot_shape_normalize_context_t *c, static inline void set_glyph (hb_glyph_info_t &info, hb_font_t *font) { - font->get_nominal_glyph (info.codepoint, &info.glyph_index()); + (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index()); } static inline void @@ -345,14 +345,18 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0) break; - /* We are going to do a O(n^2). Only do this if the sequence is short. */ - if (end - i > 10) { + /* We are going to do a O(n^2). Only do this if the sequence is short, + * but not too short ;). */ + if (end - i < 2 || end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) { i = end; continue; } buffer->sort (i, end, compare_combining_class); + if (plan->shaper->reorder_marks) + plan->shaper->reorder_marks (plan, buffer, i, end); + i = end; } @@ -369,46 +373,58 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer->clear_output (); count = buffer->len; unsigned int starter = 0; + bool combine = true; buffer->next_glyph (); while (buffer->idx < count && !buffer->in_error) { hb_codepoint_t composed, glyph; - if (/* We don't try to compose a non-mark character with it's preceding starter. + if (combine && + /* We don't try to compose a non-mark character with it's preceding starter. * This is both an optimization to avoid trying to compose every two neighboring * glyphs in most scripts AND a desired feature for Hangul. Apparently Hangul * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */ - HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())) && - /* If there's anything between the starter and this char, they should have CCC - * smaller than this character's. */ - (starter == buffer->out_len - 1 || - _hb_glyph_info_get_modified_combining_class (&buffer->prev()) < _hb_glyph_info_get_modified_combining_class (&buffer->cur())) && - /* And compose. */ - c.compose (&c, - buffer->out_info[starter].codepoint, - buffer->cur().codepoint, - &composed) && - /* And the font has glyph for the composite. */ - font->get_nominal_glyph (composed, &glyph)) + HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur()))) { - /* Composes. */ - buffer->next_glyph (); /* Copy to out-buffer. */ - if (unlikely (buffer->in_error)) - return; - buffer->merge_out_clusters (starter, buffer->out_len); - buffer->out_len--; /* Remove the second composable. */ - /* Modify starter and carry on. */ - buffer->out_info[starter].codepoint = composed; - buffer->out_info[starter].glyph_index() = glyph; - _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); - - continue; + if (/* If there's anything between the starter and this char, they should have CCC + * smaller than this character's. */ + (starter == buffer->out_len - 1 || + info_cc (buffer->prev()) < info_cc (buffer->cur())) && + /* And compose. */ + c.compose (&c, + buffer->out_info[starter].codepoint, + buffer->cur().codepoint, + &composed) && + /* And the font has glyph for the composite. */ + font->get_nominal_glyph (composed, &glyph)) + { + /* Composes. */ + buffer->next_glyph (); /* Copy to out-buffer. */ + if (unlikely (buffer->in_error)) + return; + buffer->merge_out_clusters (starter, buffer->out_len); + buffer->out_len--; /* Remove the second composable. */ + /* Modify starter and carry on. */ + buffer->out_info[starter].codepoint = composed; + buffer->out_info[starter].glyph_index() = glyph; + _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); + + continue; + } + else if (/* We sometimes custom-tailor the sorted order of marks. In that case, stop + * trying to combine as soon as combining-class drops. */ + starter < buffer->out_len - 1 && + info_cc (buffer->prev()) > info_cc (buffer->cur())) + combine = false; } /* Blocked, or doesn't compose. */ buffer->next_glyph (); - if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) + if (info_cc (buffer->prev()) == 0) + { starter = buffer->out_len - 1; + combine = true; + } } buffer->swap_buffers (); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh index 594e54c026..fe5d2b7f33 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-private.hh @@ -73,7 +73,7 @@ struct hb_ot_shape_planner_t hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : face (master_plan->face_unsafe), props (master_plan->props), - shaper (NULL), + shaper (nullptr), map (face, &props) {} ~hb_ot_shape_planner_t (void) { map.finish (); } @@ -99,7 +99,9 @@ struct hb_ot_shape_planner_t } private: - NO_COPY (hb_ot_shape_planner_t); + /* No copy. */ + hb_ot_shape_planner_t (const hb_ot_shape_planner_t &); + hb_ot_shape_planner_t &operator = (const hb_ot_shape_planner_t &); }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc index ddd6662e84..2f28b5620d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc @@ -70,7 +70,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, hb_ot_map_builder_t *map = &planner->map; map->add_global_bool_feature (HB_TAG('r','v','r','n')); - map->add_gsub_pause (NULL); + map->add_gsub_pause (nullptr); switch (props->direction) { case HB_DIRECTION_LTR: @@ -108,7 +108,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, /* We really want to find a 'vert' feature if there's any in the font, no * matter which script/langsys it is listed (or not) under. * See various bugs referenced from: - * https://github.com/behdad/harfbuzz/issues/63 */ + * https://github.com/harfbuzz/harfbuzz/issues/63 */ map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH); } @@ -128,6 +128,8 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, * shaper face data */ +HB_SHAPER_DATA_ENSURE_DEFINE(ot, face) + hb_ot_shaper_face_data_t * _hb_ot_shaper_face_data_create (hb_face_t *face) { @@ -145,6 +147,8 @@ _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data) * shaper font data */ +HB_SHAPER_DATA_ENSURE_DEFINE(ot, font) + struct hb_ot_shaper_font_data_t {}; hb_ot_shaper_font_data_t * @@ -172,7 +176,7 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, { hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); if (unlikely (!plan)) - return NULL; + return nullptr; hb_ot_shape_planner_t planner (shape_plan); @@ -186,7 +190,7 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, if (plan->shaper->data_create) { plan->data = plan->shaper->data_create (plan); if (unlikely (!plan->data)) - return NULL; + return nullptr; } return plan; @@ -271,8 +275,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) static void hb_form_clusters (hb_buffer_t *buffer) { - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || - buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) return; /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */ @@ -284,11 +287,17 @@ hb_form_clusters (hb_buffer_t *buffer) if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) && !_hb_glyph_info_is_joiner (&info[i]))) { - buffer->merge_clusters (base, i); + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + buffer->merge_clusters (base, i); + else + buffer->unsafe_to_break (base, i); base = i; } } - buffer->merge_clusters (base, count); + if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) + buffer->merge_clusters (base, count); + else + buffer->unsafe_to_break (base, count); } static void @@ -362,7 +371,18 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) hb_buffer_t *buffer = c->buffer; - /* TODO look in pre/post context text also. */ + hb_mask_t pre_mask, post_mask; + if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) + { + pre_mask = c->plan->numr_mask | c->plan->frac_mask; + post_mask = c->plan->frac_mask | c->plan->dnom_mask; + } + else + { + pre_mask = c->plan->frac_mask | c->plan->dnom_mask; + post_mask = c->plan->numr_mask | c->plan->frac_mask; + } + unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) @@ -379,11 +399,13 @@ hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c) HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) end++; + buffer->unsafe_to_break (start, end); + for (unsigned int j = start; j < i; j++) - info[j].mask |= c->plan->numr_mask | c->plan->frac_mask; + info[j].mask |= pre_mask; info[i].mask |= c->plan->frac_mask; for (unsigned int j = i + 1; j < end; j++) - info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask; + info[j].mask |= post_mask; i = end - 1; } @@ -494,9 +516,10 @@ hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) /* Merge cluster backward. */ if (cluster < info[j - 1].cluster) { + unsigned int mask = info[i].mask; unsigned int old_cluster = info[j - 1].cluster; for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) - info[k - 1].cluster = cluster; + buffer->set_cluster (info[k - 1], cluster, mask); } continue; } @@ -562,8 +585,6 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) { hb_buffer_t *buffer = c->buffer; - hb_ot_shape_initialize_masks (c); - hb_ot_mirror_chars (c); HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); @@ -672,9 +693,9 @@ hb_ot_position_default (hb_ot_shape_context_t *c) static inline void hb_ot_position_complex (hb_ot_shape_context_t *c) { - hb_ot_layout_position_start (c->font, c->buffer); - unsigned int count = c->buffer->len; + hb_glyph_info_t *info = c->buffer->info; + hb_glyph_position_t *pos = c->buffer->pos; /* If the font has no GPOS, AND, no fallback positioning will * happen, AND, direction is forward, then when zeroing mark @@ -689,6 +710,17 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) !c->plan->shaper->fallback_position && HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); + /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ + + /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->add_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); + + hb_ot_layout_position_start (c->font, c->buffer); + switch (c->plan->shaper->zero_width_marks) { case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: @@ -702,30 +734,8 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) } if (likely (!c->fallback_positioning)) - { - hb_glyph_info_t *info = c->buffer->info; - hb_glyph_position_t *pos = c->buffer->pos; - - /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ - - /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ - if (c->font->has_glyph_h_origin_func ()) - for (unsigned int i = 0; i < count; i++) - c->font->add_glyph_h_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); - c->plan->position (c->font, c->buffer); - /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ - if (c->font->has_glyph_h_origin_func ()) - for (unsigned int i = 0; i < count; i++) - c->font->subtract_glyph_h_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); - - } - switch (c->plan->shaper->zero_width_marks) { case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: @@ -742,6 +752,13 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) hb_ot_layout_position_finish_advances (c->font, c->buffer); hb_ot_zero_width_default_ignorables (c); hb_ot_layout_position_finish_offsets (c->font, c->buffer); + + /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->subtract_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); } static inline void @@ -767,6 +784,31 @@ hb_ot_position (hb_ot_shape_context_t *c) _hb_buffer_deallocate_gsubgpos_vars (c->buffer); } +static inline void +hb_propagate_flags (hb_buffer_t *buffer) +{ + /* Propagate cluster-level glyph flags to be the same on all cluster glyphs. + * Simplifies using them. */ + + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK)) + return; + + hb_glyph_info_t *info = buffer->info; + + foreach_cluster (buffer, start, end) + { + unsigned int mask = 0; + for (unsigned int i = start; i < end; i++) + if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) + { + mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; + break; + } + if (mask) + for (unsigned int i = start; i < end; i++) + info[i].mask |= mask; + } +} /* Pull it all together! */ @@ -775,11 +817,16 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) { c->buffer->deallocate_var_all (); c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_EXPANSION_FACTOR))) + if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR))) { - c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_EXPANSION_FACTOR, + c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR, (unsigned) HB_BUFFER_MAX_LEN_MIN); } + if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR))) + { + c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR, + (unsigned) HB_BUFFER_MAX_OPS_MIN); + } bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan); //c->fallback_substitute = disable_otl || !hb_ot_layout_has_substitution (c->face); @@ -793,8 +840,10 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->clear_output (); + hb_ot_shape_initialize_masks (c); hb_set_unicode_props (c->buffer); hb_insert_dotted_circle (c->buffer, c->font); + hb_form_clusters (c->buffer); hb_ensure_native_direction (c->buffer); @@ -810,11 +859,14 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) if (c->plan->shaper->postprocess_glyphs) c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); + hb_propagate_flags (c->buffer); + _hb_buffer_deallocate_unicode_vars (c->buffer); c->buffer->props.direction = c->target_direction; c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; + c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT; c->buffer->deallocate_var_all (); } @@ -882,7 +934,7 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, { hb_ot_shape_plan_t plan; - const char *shapers[] = {"ot", NULL}; + const char *shapers[] = {"ot", nullptr}; hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shapers); @@ -893,18 +945,19 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, for (unsigned int i = 0; i < count; i++) add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs); - hb_set_t lookups; - lookups.init (); - hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups); + hb_set_t *lookups = hb_set_create (); + hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups); /* And find transitive closure. */ - hb_set_t copy; - copy.init (); + hb_set_t *copy = hb_set_create (); do { - copy.set (glyphs); - for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index);) + copy->set (glyphs); + for (hb_codepoint_t lookup_index = -1; hb_set_next (lookups, &lookup_index);) hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); - } while (!copy.is_equal (glyphs)); + } while (!copy->is_equal (glyphs)); + hb_set_destroy (copy); + + hb_set_destroy (lookups); hb_shape_plan_destroy (shape_plan); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc index 5f21ac0967..1338c31732 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-tag.cc @@ -28,9 +28,6 @@ #include "hb-private.hh" -#include <string.h> - - /* hb_script_t */ @@ -201,6 +198,7 @@ static const LangTag ot_languages[] = { {"alt", HB_TAG('A','L','T',' ')}, /* [Southern] Altai */ {"am", HB_TAG('A','M','H',' ')}, /* Amharic */ {"amf", HB_TAG('H','B','N',' ')}, /* Hammer-Banna */ + {"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic */ {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */ {"ang", HB_TAG('A','N','G',' ')}, /* Old English (ca. 450-1100) */ {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */ @@ -239,6 +237,7 @@ static const LangTag ot_languages[] = { {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */ {"bgc", HB_TAG('B','G','C',' ')}, /* Haryanvi */ {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */ + {"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin */ {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */ {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) */ {"bho", HB_TAG('B','H','O',' ')}, /* Bhojpuri */ @@ -270,18 +269,37 @@ static const LangTag ot_languages[] = { {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */ {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */ {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano */ + {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin */ + {"cco", HB_TAG('C','C','H','N')}, /* Chinantec */ {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */ {"ceb", HB_TAG('C','E','B',' ')}, /* Cebuano */ + {"cfm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin */ {"cgg", HB_TAG('C','G','G',' ')}, /* Chiga */ {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */ + {"chj", HB_TAG('C','C','H','N')}, /* Chinantec */ {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */ {"cho", HB_TAG('C','H','O',' ')}, /* Choctaw */ {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */ + {"chq", HB_TAG('C','C','H','N')}, /* Chinantec */ {"chr", HB_TAG('C','H','R',' ')}, /* Cherokee */ {"chy", HB_TAG('C','H','Y',' ')}, /* Cheyenne */ + {"chz", HB_TAG('C','C','H','N')}, /* Chinantec */ + {"cja", HB_TAG('C','J','A',' ')}, /* Western Cham */ + {"cjm", HB_TAG('C','J','M',' ')}, /* Eastern Cham */ + {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin */ {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish (Sorani) */ {"ckt", HB_TAG('C','H','K',' ')}, /* Chukchi */ + {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic */ + {"cle", HB_TAG('C','C','H','N')}, /* Chinantec */ + {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin */ + {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin */ + {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin */ + {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin */ + {"cnl", HB_TAG('C','C','H','N')}, /* Chinantec */ + {"cnt", HB_TAG('C','C','H','N')}, /* Chinantec */ + {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin */ {"cop", HB_TAG('C','O','P',' ')}, /* Coptic */ + {"cpa", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cpp", HB_TAG('C','P','P',' ')}, /* Creoles */ {"cr", HB_TAG('C','R','E',' ')}, /* Cree */ {"cre", HB_TAG('Y','C','R',' ')}, /* Y-Cree */ @@ -292,15 +310,26 @@ static const LangTag ot_languages[] = { {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */ {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */ {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */ + {"csa", HB_TAG('C','C','H','N')}, /* Chinantec */ {"csb", HB_TAG('C','S','B',' ')}, /* Kashubian */ + {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin */ + {"cso", HB_TAG('C','C','H','N')}, /* Chinantec */ + {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin */ + {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin */ + {"cte", HB_TAG('C','C','H','N')}, /* Chinantec */ {"ctg", HB_TAG('C','T','G',' ')}, /* Chittagonian */ + {"ctl", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol */ {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavic */ + {"cuc", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cuk", HB_TAG('C','U','K',' ')}, /* San Blas Kuna */ {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */ + {"cvn", HB_TAG('C','C','H','N')}, /* Chinantec */ {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */ {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */ + {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin */ {"da", HB_TAG('D','A','N',' ')}, /* Danish */ + {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin */ {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) */ {"dar", HB_TAG('D','A','R',' ')}, /* Dargwa */ {"dax", HB_TAG('D','A','X',' ')}, /* Dayi */ @@ -343,7 +372,7 @@ static const LangTag ot_languages[] = { {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */ {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */ {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */ - {"flm", HB_TAG('H','A','L',' ')}, /* Halam */ + {"flm", HB_TAG('H','A','L',' ')}, /* Halam/Falam Chin [retired ISO639 code] */ {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */ {"fon", HB_TAG('F','O','N',' ')}, /* Fon */ {"fr", HB_TAG('F','R','A',' ')}, /* French */ @@ -365,7 +394,6 @@ static const LangTag ot_languages[] = { {"gkp", HB_TAG('G','K','P',' ')}, /* Kpelle (Guinea) */ {"gl", HB_TAG('G','A','L',' ')}, /* Galician */ {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */ - {"gle", HB_TAG('I','R','T',' ')}, /* Irish Traditional */ {"glk", HB_TAG('G','L','K',' ')}, /* Gilaki */ {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */ {"gnn", HB_TAG('G','N','N',' ')}, /* Gumatj */ @@ -390,6 +418,7 @@ static const LangTag ot_languages[] = { {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */ {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */ {"hil", HB_TAG('H','I','L',' ')}, /* Hiligaynon */ + {"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin */ {"hmn", HB_TAG('H','M','N',' ')}, /* Hmong */ {"hnd", HB_TAG('H','N','D',' ')}, /* [Southern] Hindko */ {"hne", HB_TAG('C','H','H',' ')}, /* Chattisgarhi */ @@ -522,7 +551,6 @@ static const LangTag ot_languages[] = { {"mag", HB_TAG('M','A','G',' ')}, /* Magahi */ {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */ {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */ - {"mal", HB_TAG('M','A','L',' ')}, /* Malayalam */ {"mam", HB_TAG('M','A','M',' ')}, /* Mam */ {"man", HB_TAG('M','N','K',' ')}, /* Manding/Mandingo [macrolanguage] */ {"mdc", HB_TAG('M','L','E',' ')}, /* Male (Papua New Guinea) */ @@ -553,6 +581,7 @@ static const LangTag ot_languages[] = { {"mos", HB_TAG('M','O','S',' ')}, /* Mossi */ {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */ {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */ + {"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin */ {"mrj", HB_TAG('H','M','A',' ')}, /* High Mari */ {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */ {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka */ @@ -617,6 +646,7 @@ static const LangTag ot_languages[] = { {"pcc", HB_TAG('P','C','C',' ')}, /* Bouyei */ {"pcd", HB_TAG('P','C','D',' ')}, /* Picard */ {"pce", HB_TAG('P','L','G',' ')}, /* [Ruching] Palaung */ + {"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin */ {"pdc", HB_TAG('P','D','C',' ')}, /* Pennsylvania German */ {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian */ {"phk", HB_TAG('P','H','K',' ')}, /* Phake */ @@ -674,6 +704,7 @@ static const LangTag ot_languages[] = { {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */ {"seh", HB_TAG('S','N','A',' ')}, /* Sena */ {"sel", HB_TAG('S','E','L',' ')}, /* Selkup */ + {"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin */ {"sg", HB_TAG('S','G','O',' ')}, /* Sango */ {"sga", HB_TAG('S','G','A',' ')}, /* Old Irish (to 900) */ {"sgs", HB_TAG('S','G','S',' ')}, /* Samogitian */ @@ -713,12 +744,15 @@ static const LangTag ot_languages[] = { {"swh", HB_TAG('S','W','K',' ')}, /* Kiswahili/Swahili */ {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati */ {"sxu", HB_TAG('S','X','U',' ')}, /* Upper Saxon */ + {"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac */ {"syl", HB_TAG('S','Y','L',' ')}, /* Sylheti */ {"syr", HB_TAG('S','Y','R',' ')}, /* Syriac [macrolanguage] */ {"szl", HB_TAG('S','Z','L',' ')}, /* Silesian */ {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */ {"tab", HB_TAG('T','A','B',' ')}, /* Tabasaran */ + {"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin */ {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu */ + {"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin */ {"tdd", HB_TAG('T','D','D',' ')}, /* Tai Nüa */ {"te", HB_TAG('T','E','L',' ')}, /* Telugu */ {"tem", HB_TAG('T','M','N',' ')}, /* Temne */ @@ -786,11 +820,13 @@ static const LangTag ot_languages[] = { {"yap", HB_TAG('Y','A','P',' ')}, /* Yapese */ {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */ {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */ + {"yos", HB_TAG('Q','I','N',' ')}, /* Yos, deprecated by IANA in favor of Zou [zom] */ {"yso", HB_TAG('N','I','S',' ')}, /* Nisi (China) */ {"za", HB_TAG('Z','H','A',' ')}, /* Chuang/Zhuang [macrolanguage] */ {"zea", HB_TAG('Z','E','A',' ')}, /* Zeeuws */ {"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Morrocan Tamazigh */ {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */ + {"zom", HB_TAG('Q','I','N',' ')}, /* Zou */ {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */ {"zum", HB_TAG('L','R','C',' ')}, /* Kumzari */ {"zza", HB_TAG('Z','Z','A',' ')}, /* Zazaki */ @@ -843,9 +879,11 @@ static const LangTagLong ot_languages_zh[] = { }; static int -lang_compare_first_component (const char *a, - const char *b) +lang_compare_first_component (const void *pa, + const void *pb) { + const char *a = (const char *) pa; + const char *b = (const char *) pb; unsigned int da, db; const char *p; @@ -882,12 +920,12 @@ hb_ot_tag_from_language (hb_language_t language) char tag[4]; int i; s += 6; - for (i = 0; i < 4 && ISALPHA (s[i]); i++) + for (i = 0; i < 4 && ISALNUM (s[i]); i++) tag[i] = TOUPPER (s[i]); if (i) { for (; i < 4; i++) tag[i] = ' '; - return HB_TAG_CHAR4 (tag); + return HB_TAG (tag[0], tag[1], tag[2], tag[3]); } } @@ -907,12 +945,36 @@ hb_ot_tag_from_language (hb_language_t language) return HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */ } + /* + * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syre")) { + return HB_TAG('S','Y','R','E'); /* Estrangela Syriac */ + } + + /* + * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syrj")) { + return HB_TAG('S','Y','R','J'); /* Western Syriac */ + } + + /* + * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script. + * It can be applied to any language. + */ + if (strstr (lang_str, "-syrn")) { + return HB_TAG('S','Y','R','N'); /* Eastern Syriac */ + } + /* Find a language matching in the first component */ { const LangTag *lang_tag; lang_tag = (LangTag *) bsearch (lang_str, ot_languages, ARRAY_LENGTH (ot_languages), sizeof (LangTag), - (hb_compare_func_t) lang_compare_first_component); + lang_compare_first_component); if (lang_tag) return lang_tag->tag; } @@ -960,7 +1022,23 @@ hb_ot_tag_to_language (hb_tag_t tag) unsigned int i; if (tag == HB_OT_TAG_DEFAULT_LANGUAGE) - return NULL; + return nullptr; + + /* struct LangTag has only room for 3-letter language tags. */ + switch (tag) { + case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */ + return hb_language_from_string ("und-fonnapa", -1); + case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ + return hb_language_from_string ("und-fonipa", -1); + case HB_TAG('S','Y','R',' '): /* Syriac [macrolanguage] */ + return hb_language_from_string ("syr", -1); + case HB_TAG('S','Y','R','E'): /* Estrangela Syriac */ + return hb_language_from_string ("und-Syre", -1); + case HB_TAG('S','Y','R','J'): /* Western Syriac */ + return hb_language_from_string ("und-Syrj", -1); + case HB_TAG('S','Y','R','N'): /* Eastern Syriac */ + return hb_language_from_string ("und-Syrn", -1); + } for (i = 0; i < ARRAY_LENGTH (ot_languages); i++) if (ot_languages[i].tag == tag) @@ -976,14 +1054,6 @@ hb_ot_tag_to_language (hb_tag_t tag) } } - /* struct LangTag has only room for 3-letter language tags. */ - switch (tag) { - case HB_TAG('A','P','P','H'): /* Phonetic transcription—Americanist conventions */ - return hb_language_from_string ("und-fonnapa", -1); - case HB_TAG('I','P','P','H'): /* Phonetic transcription—IPA conventions */ - return hb_language_from_string ("und-fonipa", -1); - } - /* Else return a custom language in the form of "x-hbotABCD" */ { unsigned char buf[11] = "x-hbot"; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh new file mode 100644 index 0000000000..4b88a40304 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-avar-table.hh @@ -0,0 +1,149 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_OT_VAR_AVAR_TABLE_HH +#define HB_OT_VAR_AVAR_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + + +struct AxisValueMap +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + F2DOT14 fromCoord; /* A normalized coordinate value obtained using + * default normalization. */ + F2DOT14 toCoord; /* The modified, normalized coordinate value. */ + + public: + DEFINE_SIZE_STATIC (4); +}; + +struct SegmentMaps : ArrayOf<AxisValueMap> +{ + inline int map (int value) const + { + /* The following special-cases are not part of OpenType, which requires + * that at least -1, 0, and +1 must be mapped. But we include these as + * part of a better error recovery scheme. */ + + if (len < 2) + { + if (!len) + return value; + else /* len == 1*/ + return value - array[0].fromCoord + array[0].toCoord; + } + + if (value <= array[0].fromCoord) + return value - array[0].fromCoord + array[0].toCoord; + + unsigned int i; + unsigned int count = len; + for (i = 1; i < count && value > array[i].fromCoord; i++) + ; + + if (value >= array[i].fromCoord) + return value - array[i].fromCoord + array[i].toCoord; + + if (unlikely (array[i-1].fromCoord == array[i].fromCoord)) + return array[i-1].toCoord; + + int denom = array[i].fromCoord - array[i-1].fromCoord; + return array[i-1].toCoord + + ((array[i].toCoord - array[i-1].toCoord) * + (value - array[i-1].fromCoord) + denom/2) / denom; + } + + DEFINE_SIZE_ARRAY (2, array); +}; + +/* + * avar — Axis Variations Table + */ + +#define HB_OT_TAG_avar HB_TAG('a','v','a','r') + +struct avar +{ + static const hb_tag_t tableTag = HB_OT_TAG_avar; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!(version.sanitize (c) && + version.major == 1 && + c->check_struct (this)))) + return_trace (false); + + const SegmentMaps *map = &axisSegmentMapsZ; + unsigned int count = axisCount; + for (unsigned int i = 0; i < count; i++) + { + if (unlikely (!map->sanitize (c))) + return_trace (false); + map = &StructAfter<SegmentMaps> (*map); + } + + return_trace (true); + } + + inline void map_coords (int *coords, unsigned int coords_length) const + { + unsigned int count = MIN<unsigned int> (coords_length, axisCount); + + const SegmentMaps *map = &axisSegmentMapsZ; + for (unsigned int i = 0; i < count; i++) + { + coords[i] = map->map (coords[i]); + map = &StructAfter<SegmentMaps> (*map); + } + } + + protected: + FixedVersion<>version; /* Version of the avar table + * initially set to 0x00010000u */ + UINT16 reserved; /* This field is permanently reserved. Set to 0. */ + UINT16 axisCount; /* The number of variation axes in the font. This + * must be the same number as axisCount in the + * 'fvar' table. */ + SegmentMaps axisSegmentMapsZ; + + public: + DEFINE_SIZE_MIN (8); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_AVAR_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh new file mode 100644 index 0000000000..2a9357a5e2 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-fvar-table.hh @@ -0,0 +1,209 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_OT_VAR_FVAR_TABLE_HH +#define HB_OT_VAR_FVAR_TABLE_HH + +#include "hb-open-type-private.hh" + +namespace OT { + + +struct InstanceRecord +{ + inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (coordinates, coordinates[0].static_size, axis_count)); + } + + protected: + UINT16 subfamilyNameID;/* The name ID for entries in the 'name' table + * that provide subfamily names for this instance. */ + UINT16 reserved; /* Reserved for future use — set to 0. */ + Fixed coordinates[VAR];/* The coordinates array for this instance. */ + //UINT16 postScriptNameIDX;/*Optional. The name ID for entries in the 'name' + // * table that provide PostScript names for this + // * instance. */ + + public: + DEFINE_SIZE_ARRAY (4, coordinates); +}; + +struct AxisRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + Tag axisTag; /* Tag identifying the design variation for the axis. */ + Fixed minValue; /* The minimum coordinate value for the axis. */ + Fixed defaultValue; /* The default coordinate value for the axis. */ + Fixed maxValue; /* The maximum coordinate value for the axis. */ + UINT16 reserved; /* Reserved for future use — set to 0. */ + UINT16 axisNameID; /* The name ID for entries in the 'name' table that + * provide a display name for this axis. */ + + public: + DEFINE_SIZE_STATIC (20); +}; + + +/* + * fvar — Font Variations Table + */ + +#define HB_OT_TAG_fvar HB_TAG('f','v','a','r') + +struct fvar +{ + static const hb_tag_t tableTag = HB_OT_TAG_fvar; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + c->check_struct (this) && + instanceSize >= axisCount * 4 + 4 && + axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ + instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ + c->check_range (this, things) && + c->check_range (&StructAtOffset<char> (this, things), + axisCount * axisSize + instanceCount * instanceSize)); + } + + inline unsigned int get_axis_count (void) const + { return axisCount; } + + inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const + { + if (unlikely (index >= axisCount)) + return false; + + if (info) + { + const AxisRecord &axis = get_axes ()[index]; + info->tag = axis.axisTag; + info->name_id = axis.axisNameID; + info->default_value = axis.defaultValue / 65536.; + /* Ensure order, to simplify client math. */ + info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.); + info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.); + } + + return true; + } + + inline unsigned int get_axis_infos (unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */) const + { + if (axes_count) + { + unsigned int count = axisCount; + start_offset = MIN (start_offset, count); + + count -= start_offset; + axes_array += start_offset; + + count = MIN (count, *axes_count); + *axes_count = count; + + for (unsigned int i = 0; i < count; i++) + get_axis (start_offset + i, axes_array + i); + } + return axisCount; + } + + inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const + { + const AxisRecord *axes = get_axes (); + unsigned int count = get_axis_count (); + for (unsigned int i = 0; i < count; i++) + if (axes[i].axisTag == tag) + { + if (index) + *index = i; + return get_axis (i, info); + } + if (index) + *index = HB_OT_VAR_NO_AXIS_INDEX; + return false; + } + + inline int normalize_axis_value (unsigned int axis_index, float v) const + { + hb_ot_var_axis_t axis; + if (!get_axis (axis_index, &axis)) + return 0; + + v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */ + + if (v == axis.default_value) + return 0; + else if (v < axis.default_value) + v = (v - axis.default_value) / (axis.default_value - axis.min_value); + else + v = (v - axis.default_value) / (axis.max_value - axis.default_value); + return (int) (v * 16384. + (v >= 0. ? .5 : -.5)); + } + + protected: + inline const AxisRecord * get_axes (void) const + { return &StructAtOffset<AxisRecord> (this, things); } + + inline const InstanceRecord * get_instances (void) const + { return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); } + + protected: + FixedVersion<>version; /* Version of the fvar table + * initially set to 0x00010000u */ + Offset16 things; /* Offset in bytes from the beginning of the table + * to the start of the AxisRecord array. */ + UINT16 reserved; /* This field is permanently reserved. Set to 2. */ + UINT16 axisCount; /* The number of variation axes in the font (the + * number of records in the axes array). */ + UINT16 axisSize; /* The size in bytes of each VariationAxisRecord — + * set to 20 (0x0014) for this version. */ + UINT16 instanceCount; /* The number of named instances defined in the font + * (the number of records in the instances array). */ + UINT16 instanceSize; /* The size in bytes of each InstanceRecord — set + * to either axisCount * sizeof(Fixed) + 4, or to + * axisCount * sizeof(Fixed) + 6. */ + + public: + DEFINE_SIZE_STATIC (16); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_FVAR_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh new file mode 100644 index 0000000000..fac843a719 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-hvar-table.hh @@ -0,0 +1,165 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_OT_VAR_HVAR_TABLE_HH +#define HB_OT_VAR_HVAR_TABLE_HH + +#include "hb-ot-layout-common-private.hh" + + +namespace OT { + + +struct DeltaSetIndexMap +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + c->check_array (mapData, get_width (), mapCount)); + } + + unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */ + { + /* If count is zero, pass value unchanged. This takes + * care of direct mapping for advance map. */ + if (!mapCount) + return v; + + if (v >= mapCount) + v = mapCount - 1; + + unsigned int u = 0; + { /* Fetch it. */ + unsigned int w = get_width (); + const UINT8 *p = mapData + w * v; + for (; w; w--) + u = (u << 8) + *p++; + } + + { /* Repack it. */ + unsigned int n = get_inner_bitcount (); + unsigned int outer = u >> n; + unsigned int inner = u & ((1 << n) - 1); + u = (outer<<16) | inner; + } + + return u; + } + + protected: + inline unsigned int get_width (void) const + { return ((format >> 4) & 3) + 1; } + + inline unsigned int get_inner_bitcount (void) const + { return (format & 0xF) + 1; } + + protected: + UINT16 format; /* A packed field that describes the compressed + * representation of delta-set indices. */ + UINT16 mapCount; /* The number of mapping entries. */ + UINT8 mapData[VAR]; /* The delta-set index mapping data. */ + + public: + DEFINE_SIZE_ARRAY (4, mapData); +}; + + +/* + * HVAR -- The Horizontal Metrics Variations Table + * VVAR -- The Vertical Metrics Variations Table + */ + +#define HB_OT_TAG_HVAR HB_TAG('H','V','A','R') +#define HB_OT_TAG_VVAR HB_TAG('V','V','A','R') + +struct HVARVVAR +{ + static const hb_tag_t HVARTag = HB_OT_TAG_HVAR; + static const hb_tag_t VVARTag = HB_OT_TAG_VVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + varStore.sanitize (c, this) && + advMap.sanitize (c, this) && + lsbMap.sanitize (c, this) && + rsbMap.sanitize (c, this)); + } + + inline float get_advance_var (hb_codepoint_t glyph, + int *coords, unsigned int coord_count) const + { + unsigned int varidx = (this+advMap).map (glyph); + return (this+varStore).get_delta (varidx, coords, coord_count); + } + + inline bool has_sidebearing_deltas (void) const + { return lsbMap && rsbMap; } + + protected: + FixedVersion<>version; /* Version of the metrics variation table + * initially set to 0x00010000u */ + LOffsetTo<VariationStore> + varStore; /* Offset to item variation store table. */ + LOffsetTo<DeltaSetIndexMap> + advMap; /* Offset to advance var-idx mapping. */ + LOffsetTo<DeltaSetIndexMap> + lsbMap; /* Offset to lsb/tsb var-idx mapping. */ + LOffsetTo<DeltaSetIndexMap> + rsbMap; /* Offset to rsb/bsb var-idx mapping. */ + + public: + DEFINE_SIZE_STATIC (20); +}; + +struct HVAR : HVARVVAR { + static const hb_tag_t tableTag = HB_OT_TAG_HVAR; +}; +struct VVAR : HVARVVAR { + static const hb_tag_t tableTag = HB_OT_TAG_VVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) && + vorgMap.sanitize (c, this)); + } + + protected: + LOffsetTo<DeltaSetIndexMap> + vorgMap; /* Offset to vertical-origin var-idx mapping. */ + + public: + DEFINE_SIZE_STATIC (24); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_HVAR_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh new file mode 100644 index 0000000000..e17ff5160a --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var-mvar-table.hh @@ -0,0 +1,114 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_OT_VAR_MVAR_TABLE_HH +#define HB_OT_VAR_MVAR_TABLE_HH + +#include "hb-ot-layout-common-private.hh" + + +namespace OT { + + +struct VariationValueRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + Tag valueTag; /* Four-byte tag identifying a font-wide measure. */ + UINT32 varIdx; /* Outer/inner index into VariationStore item. */ + + public: + DEFINE_SIZE_STATIC (8); +}; + + +/* + * MVAR -- Metrics Variations Table + */ + +#define HB_OT_TAG_MVAR HB_TAG('M','V','A','R') + +struct MVAR +{ + static const hb_tag_t tableTag = HB_OT_TAG_MVAR; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (version.sanitize (c) && + likely (version.major == 1) && + c->check_struct (this) && + valueRecordSize >= VariationValueRecord::static_size && + varStore.sanitize (c, this) && + c->check_array (values, valueRecordSize, valueRecordCount)); + } + + inline float get_var (hb_tag_t tag, + int *coords, unsigned int coord_count) const + { + const VariationValueRecord *record; + record = (VariationValueRecord *) bsearch (&tag, values, + valueRecordCount, valueRecordSize, + tag_compare); + if (!record) + return 0.; + + return (this+varStore).get_delta (record->varIdx, coords, coord_count); + } + +protected: + static inline int tag_compare (const void *pa, const void *pb) + { + const hb_tag_t *a = (const hb_tag_t *) pa; + const Tag *b = (const Tag *) pb; + return b->cmp (*a); + } + + protected: + FixedVersion<>version; /* Version of the metrics variation table + * initially set to 0x00010000u */ + UINT16 reserved; /* Not used; set to 0. */ + UINT16 valueRecordSize;/* The size in bytes of each value record — + * must be greater than zero. */ + UINT16 valueRecordCount;/* The number of value records — may be zero. */ + OffsetTo<VariationStore> + varStore; /* Offset to item variation store table. */ + UINT8 values[VAR]; /* Array of value records. The records must be + * in binary order of their valueTag field. */ + + public: + DEFINE_SIZE_ARRAY (12, values); +}; + +} /* namespace OT */ + + +#endif /* HB_OT_VAR_MVAR_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc new file mode 100644 index 0000000000..90ba0bd02c --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.cc @@ -0,0 +1,159 @@ +/* + * Copyright © 2017 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-open-type-private.hh" + +#include "hb-ot-layout-private.hh" +#include "hb-ot-var-avar-table.hh" +#include "hb-ot-var-fvar-table.hh" +#include "hb-ot-var-mvar-table.hh" +#include "hb-ot-var.h" + +/* + * fvar/avar + */ + +static inline const OT::fvar& +_get_fvar (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::fvar); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->fvar.get ()); +} +static inline const OT::avar& +_get_avar (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::avar); + hb_ot_layout_t * layout = hb_ot_layout_from_face (face); + return *(layout->avar.get ()); +} + +/** + * hb_ot_var_has_data: + * @face: #hb_face_t to test + * + * This function allows to verify the presence of OpenType variation data on the face. + * Alternatively, use hb_ot_var_get_axis_count(). + * + * Return value: true if face has a `fvar' table and false otherwise + * + * Since: 1.4.2 + **/ +hb_bool_t +hb_ot_var_has_data (hb_face_t *face) +{ + return &_get_fvar (face) != &OT::Null(OT::fvar); +} + +/** + * hb_ot_var_get_axis_count: + * + * Since: 1.4.2 + **/ +unsigned int +hb_ot_var_get_axis_count (hb_face_t *face) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.get_axis_count (); +} + +/** + * hb_ot_var_get_axes: + * + * Since: 1.4.2 + **/ +unsigned int +hb_ot_var_get_axes (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.get_axis_infos (start_offset, axes_count, axes_array); +} + +/** + * hb_ot_var_find_axis: + * + * Since: 1.4.2 + **/ +hb_bool_t +hb_ot_var_find_axis (hb_face_t *face, + hb_tag_t axis_tag, + unsigned int *axis_index, + hb_ot_var_axis_t *axis_info) +{ + const OT::fvar &fvar = _get_fvar (face); + return fvar.find_axis (axis_tag, axis_index, axis_info); +} + + +/** + * hb_ot_var_normalize_variations: + * + * Since: 1.4.2 + **/ +void +hb_ot_var_normalize_variations (hb_face_t *face, + const hb_variation_t *variations, /* IN */ + unsigned int variations_length, + int *coords, /* OUT */ + unsigned int coords_length) +{ + for (unsigned int i = 0; i < coords_length; i++) + coords[i] = 0; + + const OT::fvar &fvar = _get_fvar (face); + for (unsigned int i = 0; i < variations_length; i++) + { + unsigned int axis_index; + if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) && + axis_index < coords_length) + coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value); + } + + const OT::avar &avar = _get_avar (face); + avar.map_coords (coords, coords_length); +} + +/** + * hb_ot_var_normalize_coords: + * + * Since: 1.4.2 + **/ +void +hb_ot_var_normalize_coords (hb_face_t *face, + unsigned int coords_length, + const float *design_coords, /* IN */ + int *normalized_coords /* OUT */) +{ + const OT::fvar &fvar = _get_fvar (face); + for (unsigned int i = 0; i < coords_length; i++) + normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]); + + const OT::avar &avar = _get_avar (face); + avar.map_coords (normalized_coords, coords_length); +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-var.h b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.h new file mode 100644 index 0000000000..a2c0c5f2b0 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-var.h @@ -0,0 +1,105 @@ +/* + * Copyright © 2017 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. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_OT_H_IN +#error "Include <hb-ot.h> instead." +#endif + +#ifndef HB_OT_VAR_H +#define HB_OT_VAR_H + +#include "hb.h" + +HB_BEGIN_DECLS + + +#define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l') +#define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z') +#define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t') +#define HB_OT_TAG_VAR_AXIS_WIDTH HB_TAG('w','d','t','h') +#define HB_OT_TAG_VAR_AXIS_WEIGHT HB_TAG('w','g','h','t') + + +/* + * fvar / avar + */ + +/** + * hb_ot_var_axis_t: + * + * Since: 1.4.2 + */ +typedef struct hb_ot_var_axis_t { + hb_tag_t tag; + unsigned int name_id; + float min_value; + float default_value; + float max_value; +} hb_ot_var_axis_t; + +HB_EXTERN hb_bool_t +hb_ot_var_has_data (hb_face_t *face); + +/** + * HB_OT_VAR_NO_AXIS_INDEX: + * + * Since: 1.4.2 + */ +#define HB_OT_VAR_NO_AXIS_INDEX 0xFFFFFFFFu + +HB_EXTERN unsigned int +hb_ot_var_get_axis_count (hb_face_t *face); + +HB_EXTERN unsigned int +hb_ot_var_get_axes (hb_face_t *face, + unsigned int start_offset, + unsigned int *axes_count /* IN/OUT */, + hb_ot_var_axis_t *axes_array /* OUT */); + +HB_EXTERN hb_bool_t +hb_ot_var_find_axis (hb_face_t *face, + hb_tag_t axis_tag, + unsigned int *axis_index, + hb_ot_var_axis_t *axis_info); + + +HB_EXTERN void +hb_ot_var_normalize_variations (hb_face_t *face, + const hb_variation_t *variations, /* IN */ + unsigned int variations_length, + int *coords, /* OUT */ + unsigned int coords_length); + +HB_EXTERN void +hb_ot_var_normalize_coords (hb_face_t *face, + unsigned int coords_length, + const float *design_coords, /* IN */ + int *normalized_coords /* OUT */); + + +HB_END_DECLS + +#endif /* HB_OT_VAR_H */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot.h b/src/3rdparty/harfbuzz-ng/src/hb-ot.h index 113e37b08a..2120a3efa3 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot.h @@ -35,6 +35,7 @@ #include "hb-ot-math.h" #include "hb-ot-tag.h" #include "hb-ot-shape.h" +#include "hb-ot-var.h" HB_BEGIN_DECLS diff --git a/src/3rdparty/harfbuzz-ng/src/hb-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-private.hh index 666af6260b..acddd89381 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-private.hh @@ -44,16 +44,14 @@ #include <stddef.h> #include <string.h> #include <assert.h> - -/* We only use these two for debug output. However, the debug code is - * always seen by the compiler (and optimized out in non-debug builds. - * If including these becomes a problem, we can start thinking about - * someway around that. */ -#include <stdio.h> #include <errno.h> +#include <stdio.h> #include <stdarg.h> +#define HB_PASTE1(a,b) a##b +#define HB_PASTE(a,b) HB_PASTE1(a,b) + /* Compile-time custom allocator support. */ #if defined(hb_malloc_impl) \ @@ -74,10 +72,25 @@ extern "C" void hb_free_impl(void *ptr); /* Compiler attributes */ -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) -#define _HB_BOOLEAN_EXPR(expr) ((expr) ? 1 : 0) -#define likely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 1)) -#define unlikely(expr) (__builtin_expect (_HB_BOOLEAN_EXPR(expr), 0)) +#if __cplusplus < 201103L + +#ifndef nullptr +#define nullptr NULL +#endif + +// Static assertions +#ifndef static_assert +#define static_assert(e, msg) \ + HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1] +#endif // static_assert + +#endif // __cplusplus < 201103L + +#define _GNU_SOURCE 1 + +#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__) +#define likely(expr) (__builtin_expect (!!(expr), 1)) +#define unlikely(expr) (__builtin_expect (!!(expr), 0)) #else #define likely(expr) (expr) #define unlikely(expr) (expr) @@ -99,6 +112,8 @@ extern "C" void hb_free_impl(void *ptr); #endif #if __GNUC__ >= 4 #define HB_UNUSED __attribute__((unused)) +#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */ +#define HB_UNUSED __pragma(warning(suppress: 4100 4101)) #else #define HB_UNUSED #endif @@ -168,21 +183,17 @@ extern "C" void hb_free_impl(void *ptr); # if defined(_WIN32_WCE) /* Some things not defined on Windows CE. */ -# define strdup _strdup # define vsnprintf _vsnprintf -# define getenv(Name) NULL +# define getenv(Name) nullptr # if _WIN32_WCE < 0x800 # define setlocale(Category, Locale) "C" static int errno = 0; /* Use something better? */ # endif # elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -# define getenv(Name) NULL +# define getenv(Name) nullptr # endif # if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf -# elif defined(_MSC_VER) && _MSC_VER >= 1900 -# /* Covers VC++ Error for strdup being a deprecated POSIX name and to instead use _strdup instead */ -# define strdup _strdup # endif #endif @@ -214,11 +225,6 @@ static int errno = 0; /* Use something better? */ /* Basics */ - -#ifndef NULL -# define NULL ((void *) 0) -#endif - #undef MIN template <typename Type> static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; } @@ -240,32 +246,26 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; } #define HB_STMT_START do #define HB_STMT_END while (0) -#define _ASSERT_STATIC1(_line, _cond) HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] -#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond)) -#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond)) - -template <unsigned int cond> class hb_assert_constant_t {}; +template <unsigned int cond> class hb_assert_constant_t; +template <> class hb_assert_constant_t<1> {}; #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>)) -#define _PASTE1(a,b) a##b -#define PASTE(a,b) _PASTE1(a,b) - /* Lets assert int types. Saves trouble down the road. */ -ASSERT_STATIC (sizeof (int8_t) == 1); -ASSERT_STATIC (sizeof (uint8_t) == 1); -ASSERT_STATIC (sizeof (int16_t) == 2); -ASSERT_STATIC (sizeof (uint16_t) == 2); -ASSERT_STATIC (sizeof (int32_t) == 4); -ASSERT_STATIC (sizeof (uint32_t) == 4); -ASSERT_STATIC (sizeof (int64_t) == 8); -ASSERT_STATIC (sizeof (uint64_t) == 8); +static_assert ((sizeof (int8_t) == 1), ""); +static_assert ((sizeof (uint8_t) == 1), ""); +static_assert ((sizeof (int16_t) == 2), ""); +static_assert ((sizeof (uint16_t) == 2), ""); +static_assert ((sizeof (int32_t) == 4), ""); +static_assert ((sizeof (uint32_t) == 4), ""); +static_assert ((sizeof (int64_t) == 8), ""); +static_assert ((sizeof (uint64_t) == 8), ""); -ASSERT_STATIC (sizeof (hb_codepoint_t) == 4); -ASSERT_STATIC (sizeof (hb_position_t) == 4); -ASSERT_STATIC (sizeof (hb_mask_t) == 4); -ASSERT_STATIC (sizeof (hb_var_int_t) == 4); +static_assert ((sizeof (hb_codepoint_t) == 4), ""); +static_assert ((sizeof (hb_position_t) == 4), ""); +static_assert ((sizeof (hb_mask_t) == 4), ""); +static_assert ((sizeof (hb_var_int_t) == 4), ""); /* We like our types POD */ @@ -300,7 +300,7 @@ ASSERT_STATIC (sizeof (hb_var_int_t) == 4); /* Void! */ struct _hb_void_t {}; typedef const _hb_void_t *hb_void_t; -#define HB_VOID ((const _hb_void_t *) NULL) +#define HB_VOID ((const _hb_void_t *) nullptr) /* Return the number of 1 bits in mask. */ static inline HB_CONST_FUNC unsigned int @@ -316,6 +316,18 @@ _hb_popcount32 (uint32_t mask) return (((y + (y >> 3)) & 030707070707) % 077); #endif } +static inline HB_CONST_FUNC unsigned int +_hb_popcount64 (uint64_t mask) +{ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + if (sizeof (long) >= sizeof (mask)) + return __builtin_popcountl (mask); +#endif + return _hb_popcount32 (mask & 0xFFFFFFFF) + _hb_popcount32 (mask >> 32); +} +template <typename T> static inline unsigned int _hb_popcount (T mask); +template <> inline unsigned int _hb_popcount<uint32_t> (uint32_t mask) { return _hb_popcount32 (mask); } +template <> inline unsigned int _hb_popcount<uint64_t> (uint64_t mask) { return _hb_popcount64 (mask); } /* Returns the number of bits needed to store number */ static inline HB_CONST_FUNC unsigned int @@ -357,16 +369,11 @@ _hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size) } -/* Type of bsearch() / qsort() compare function */ -typedef int (*hb_compare_func_t) (const void *, const void *); - - - /* arrays and maps */ -#define HB_PREALLOCED_ARRAY_INIT {0, 0, NULL} +#define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr} template <typename Type, unsigned int StaticSize=16> struct hb_prealloced_array_t { @@ -375,41 +382,56 @@ struct hb_prealloced_array_t Type *array; Type static_array[StaticSize]; - void init (void) { memset (this, 0, sizeof (*this)); } + void init (void) + { + len = 0; + allocated = ARRAY_LENGTH (static_array); + array = static_array; + } inline Type& operator [] (unsigned int i) { return array[i]; } inline const Type& operator [] (unsigned int i) const { return array[i]; } inline Type *push (void) { - if (!array) { - array = static_array; - allocated = ARRAY_LENGTH (static_array); - } - if (likely (len < allocated)) - return &array[len++]; + if (unlikely (!resize (len + 1))) + return nullptr; - /* Need to reallocate */ - unsigned int new_allocated = allocated + (allocated >> 1) + 8; - Type *new_array = NULL; + return &array[len - 1]; + } - if (array == static_array) { - new_array = (Type *) calloc (new_allocated, sizeof (Type)); - if (new_array) - memcpy (new_array, array, len * sizeof (Type)); - } else { - bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type)); - if (likely (!overflows)) { - new_array = (Type *) realloc (array, new_allocated * sizeof (Type)); + inline bool resize (unsigned int size) + { + if (unlikely (size > allocated)) + { + /* Need to reallocate */ + + unsigned int new_allocated = allocated; + while (size >= new_allocated) + new_allocated += (new_allocated >> 1) + 8; + + Type *new_array = nullptr; + + if (array == static_array) { + new_array = (Type *) calloc (new_allocated, sizeof (Type)); + if (new_array) + memcpy (new_array, array, len * sizeof (Type)); + } else { + bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type)); + if (likely (!overflows)) { + new_array = (Type *) realloc (array, new_allocated * sizeof (Type)); + } } - } - if (unlikely (!new_array)) - return NULL; + if (unlikely (!new_array)) + return false; + + array = new_array; + allocated = new_allocated; + } - array = new_array; - allocated = new_allocated; - return &array[len++]; + len = size; + return true; } inline void pop (void) @@ -438,42 +460,67 @@ struct hb_prealloced_array_t for (unsigned int i = 0; i < len; i++) if (array[i] == v) return &array[i]; - return NULL; + return nullptr; } template <typename T> inline const Type *find (T v) const { for (unsigned int i = 0; i < len; i++) if (array[i] == v) return &array[i]; - return NULL; + return nullptr; } inline void qsort (void) { - ::qsort (array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); + ::qsort (array, len, sizeof (Type), Type::cmp); } inline void qsort (unsigned int start, unsigned int end) { - ::qsort (array + start, end - start, sizeof (Type), (hb_compare_func_t) Type::cmp); + ::qsort (array + start, end - start, sizeof (Type), Type::cmp); } template <typename T> - inline Type *bsearch (T *key) + inline Type *bsearch (T *x) { - return (Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); + unsigned int i; + return bfind (x, &i) ? &array[i] : nullptr; } template <typename T> - inline const Type *bsearch (T *key) const + inline const Type *bsearch (T *x) const { - return (const Type *) ::bsearch (key, array, len, sizeof (Type), (hb_compare_func_t) Type::cmp); + unsigned int i; + return bfind (x, &i) ? &array[i] : nullptr; + } + template <typename T> + inline bool bfind (T *x, unsigned int *i) const + { + int min = 0, max = (int) this->len - 1; + while (min <= max) + { + int mid = (min + max) / 2; + int c = this->array[mid].cmp (x); + if (c < 0) + max = mid - 1; + else if (c > 0) + min = mid + 1; + else + { + *i = mid; + return true; + } + } + if (max < 0 || (max < (int) this->len && this->array[max].cmp (x) > 0)) + max++; + *i = max; + return false; } inline void finish (void) { if (array != static_array) free (array); - array = NULL; + array = nullptr; allocated = len = 0; } }; @@ -490,7 +537,7 @@ struct hb_auto_array_t : hb_prealloced_array_t <Type> template <typename item_t, typename lock_t> struct hb_lockable_set_t { - hb_prealloced_array_t <item_t, 2> items; + hb_prealloced_array_t <item_t, 1> items; inline void init (void) { items.init (); } @@ -507,7 +554,7 @@ struct hb_lockable_set_t old.finish (); } else { - item = NULL; + item = nullptr; l.unlock (); } } else { @@ -595,22 +642,6 @@ static inline unsigned char TOUPPER (unsigned char c) static inline unsigned char TOLOWER (unsigned char c) { return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; } -#define HB_TAG_CHAR4(s) (HB_TAG(((const char *) s)[0], \ - ((const char *) s)[1], \ - ((const char *) s)[2], \ - ((const char *) s)[3])) - - -/* C++ helpers */ - -/* Makes class uncopyable. Use in private: section. */ -#define NO_COPY(T) \ - T (const T &o); \ - T &operator = (const T &o) - - -/* Debug */ - /* HB_NDEBUG disables some sanity checks that are very safe to disable and * should be disabled in production systems. If NDEBUG is defined, enable @@ -621,255 +652,6 @@ static inline unsigned char TOLOWER (unsigned char c) #define HB_NDEBUG #endif -#ifndef HB_DEBUG -#define HB_DEBUG 0 -#endif - -static inline bool -_hb_debug (unsigned int level, - unsigned int max_level) -{ - return level < max_level; -} - -#define DEBUG_LEVEL_ENABLED(WHAT, LEVEL) (_hb_debug ((LEVEL), HB_DEBUG_##WHAT)) -#define DEBUG_ENABLED(WHAT) (DEBUG_LEVEL_ENABLED (WHAT, 0)) - -static inline void -_hb_print_func (const char *func) -{ - if (func) - { - unsigned int func_len = strlen (func); - /* Skip "static" */ - if (0 == strncmp (func, "static ", 7)) - func += 7; - /* Skip "typename" */ - if (0 == strncmp (func, "typename ", 9)) - func += 9; - /* Skip return type */ - const char *space = strchr (func, ' '); - if (space) - func = space + 1; - /* Skip parameter list */ - const char *paren = strchr (func, '('); - if (paren) - func_len = paren - func; - fprintf (stderr, "%.*s", func_len, func); - } -} - -template <int max_level> static inline void -_hb_debug_msg_va (const char *what, - const void *obj, - const char *func, - bool indented, - unsigned int level, - int level_dir, - const char *message, - va_list ap) HB_PRINTF_FUNC(7, 0); -template <int max_level> static inline void -_hb_debug_msg_va (const char *what, - const void *obj, - const char *func, - bool indented, - unsigned int level, - int level_dir, - const char *message, - va_list ap) -{ - if (!_hb_debug (level, max_level)) - return; - - fprintf (stderr, "%-10s", what ? what : ""); - - if (obj) - fprintf (stderr, "(%0*lx) ", (unsigned int) (2 * sizeof (void *)), (unsigned long) obj); - else - fprintf (stderr, " %*s ", (unsigned int) (2 * sizeof (void *)), ""); - - if (indented) { -#define VBAR "\342\224\202" /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ -#define VRBAR "\342\224\234" /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ -#define DLBAR "\342\225\256" /* U+256E BOX DRAWINGS LIGHT ARC DOWN AND LEFT */ -#define ULBAR "\342\225\257" /* U+256F BOX DRAWINGS LIGHT ARC UP AND LEFT */ -#define LBAR "\342\225\264" /* U+2574 BOX DRAWINGS LIGHT LEFT */ - static const char bars[] = - VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR - VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR - VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR - VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR - VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR; - fprintf (stderr, "%2u %s" VRBAR "%s", - level, - bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level), - level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR); - } else - fprintf (stderr, " " VRBAR LBAR); - - _hb_print_func (func); - - if (message) - { - fprintf (stderr, ": "); - vfprintf (stderr, message, ap); - } - - fprintf (stderr, "\n"); -} -template <> inline void -_hb_debug_msg_va<0> (const char *what HB_UNUSED, - const void *obj HB_UNUSED, - const char *func HB_UNUSED, - bool indented HB_UNUSED, - unsigned int level HB_UNUSED, - int level_dir HB_UNUSED, - const char *message HB_UNUSED, - va_list ap HB_UNUSED) {} - -template <int max_level> static inline void -_hb_debug_msg (const char *what, - const void *obj, - const char *func, - bool indented, - unsigned int level, - int level_dir, - const char *message, - ...) HB_PRINTF_FUNC(7, 8); -template <int max_level> static inline void -_hb_debug_msg (const char *what, - const void *obj, - const char *func, - bool indented, - unsigned int level, - int level_dir, - const char *message, - ...) -{ - va_list ap; - va_start (ap, message); - _hb_debug_msg_va<max_level> (what, obj, func, indented, level, level_dir, message, ap); - va_end (ap); -} -template <> inline void -_hb_debug_msg<0> (const char *what HB_UNUSED, - const void *obj HB_UNUSED, - const char *func HB_UNUSED, - bool indented HB_UNUSED, - unsigned int level HB_UNUSED, - int level_dir HB_UNUSED, - const char *message HB_UNUSED, - ...) HB_PRINTF_FUNC(7, 8); -template <> inline void -_hb_debug_msg<0> (const char *what HB_UNUSED, - const void *obj HB_UNUSED, - const char *func HB_UNUSED, - bool indented HB_UNUSED, - unsigned int level HB_UNUSED, - int level_dir HB_UNUSED, - const char *message HB_UNUSED, - ...) {} - -#define DEBUG_MSG_LEVEL(WHAT, OBJ, LEVEL, LEVEL_DIR, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, true, (LEVEL), (LEVEL_DIR), __VA_ARGS__) -#define DEBUG_MSG(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), NULL, false, 0, 0, __VA_ARGS__) -#define DEBUG_MSG_FUNC(WHAT, OBJ, ...) _hb_debug_msg<HB_DEBUG_##WHAT> (#WHAT, (OBJ), HB_FUNC, false, 0, 0, __VA_ARGS__) - - -/* - * Printer - */ - -template <typename T> -struct hb_printer_t { - const char *print (const T&) { return "something"; } -}; - -template <> -struct hb_printer_t<bool> { - const char *print (bool v) { return v ? "true" : "false"; } -}; - -template <> -struct hb_printer_t<hb_void_t> { - const char *print (hb_void_t) { return ""; } -}; - - -/* - * Trace - */ - -template <typename T> -static inline void _hb_warn_no_return (bool returned) -{ - if (unlikely (!returned)) { - fprintf (stderr, "OUCH, returned with no call to return_trace(). This is a bug, please report.\n"); - } -} -template <> -/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED) -{} - -template <int max_level, typename ret_t> -struct hb_auto_trace_t { - explicit inline hb_auto_trace_t (unsigned int *plevel_, - const char *what_, - const void *obj_, - const char *func, - const char *message, - ...) : plevel (plevel_), what (what_), obj (obj_), returned (false) - { - if (plevel) ++*plevel; - - va_list ap; - va_start (ap, message); - _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap); - va_end (ap); - } - inline ~hb_auto_trace_t (void) - { - _hb_warn_no_return<ret_t> (returned); - if (!returned) { - _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, " "); - } - if (plevel) --*plevel; - } - - inline ret_t ret (ret_t v, unsigned int line = 0) - { - if (unlikely (returned)) { - fprintf (stderr, "OUCH, double calls to return_trace(). This is a bug, please report.\n"); - return v; - } - - _hb_debug_msg<max_level> (what, obj, NULL, true, plevel ? *plevel : 1, -1, - "return %s (line %d)", - hb_printer_t<ret_t>().print (v), line); - if (plevel) --*plevel; - plevel = NULL; - returned = true; - return v; - } - - private: - unsigned int *plevel; - const char *what; - const void *obj; - bool returned; -}; -template <typename ret_t> /* Optimize when tracing is disabled */ -struct hb_auto_trace_t<0, ret_t> { - explicit inline hb_auto_trace_t (unsigned int *plevel_ HB_UNUSED, - const char *what HB_UNUSED, - const void *obj HB_UNUSED, - const char *func HB_UNUSED, - const char *message HB_UNUSED, - ...) {} - - inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; } -}; - -#define return_trace(RET) return trace.ret (RET, __LINE__) /* Misc */ @@ -887,7 +669,7 @@ hb_in_range (T u, T lo, T hi) * one right now. Declaring a variable won't work as HB_UNUSED * is unusable on some platforms and unused types are less likely * to generate a warning than unused variables. */ - ASSERT_STATIC (sizeof (hb_assert_unsigned_t<T>) >= 0); + static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), ""); /* The casts below are important as if T is smaller than int, * the subtract results will become a signed int! */ @@ -912,7 +694,7 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) * one enum to another... So this doesn't provide the type-checking that I * originally had in mind... :(. * - * For MSVC warnings, see: https://github.com/behdad/harfbuzz/pull/163 + * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163 */ #ifdef _MSC_VER # pragma warning(disable:4200) @@ -932,11 +714,10 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3) /* Useful for set-operations on small enums. * For example, for testing "x ∈ {x1, x2, x3}" use: - * (FLAG_SAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) + * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) */ -#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((x) < 32) + (1U << (x))) -#define FLAG_SAFE(x) (1U << (x)) -#define FLAG_UNSAFE(x) ((x) < 32 ? FLAG_SAFE(x) : 0) +#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x))) +#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0) #define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x)) @@ -968,7 +749,7 @@ hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), template <typename T> static inline void hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *)) { - hb_stable_sort (array, len, compar, (int *) NULL); + hb_stable_sort (array, len, compar, (int *) nullptr); } static inline hb_bool_t @@ -990,6 +771,73 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o } +/* Vectorization */ + +struct HbOpOr +{ + static const bool passthru_left = true; + static const bool passthru_right = true; + template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; } +}; +struct HbOpAnd +{ + static const bool passthru_left = false; + static const bool passthru_right = false; + template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; } +}; +struct HbOpMinus +{ + static const bool passthru_left = true; + static const bool passthru_right = false; + template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; } +}; +struct HbOpXor +{ + static const bool passthru_left = true; + static const bool passthru_right = true; + template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; } +}; + +/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */ +template <typename elt_t, unsigned int byte_size> +struct hb_vector_size_t +{ + elt_t& operator [] (unsigned int i) { return v[i]; } + const elt_t& operator [] (unsigned int i) const { return v[i]; } + + template <class Op> + inline hb_vector_size_t process (const hb_vector_size_t &o) const + { + hb_vector_size_t r; + for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) + Op::process (r.v[i], v[i], o.v[i]); + return r; + } + inline hb_vector_size_t operator | (const hb_vector_size_t &o) const + { return process<HbOpOr> (o); } + inline hb_vector_size_t operator & (const hb_vector_size_t &o) const + { return process<HbOpAnd> (o); } + inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const + { return process<HbOpXor> (o); } + inline hb_vector_size_t operator ~ () const + { + hb_vector_size_t r; + for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++) + r.v[i] = ~v[i]; + return r; + } + + private: + static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, ""); + elt_t v[byte_size / sizeof (elt_t)]; +}; + +/* The `vector_size' attribute was introduced in gcc 3.1. */ +#if defined( __GNUC__ ) && ( __GNUC__ >= 4 ) +#define HAVE_VECTOR_SIZE 1 +#endif + + /* Global runtime options. */ struct hb_options_t @@ -1002,7 +850,7 @@ union hb_options_union_t { unsigned int i; hb_options_t opts; }; -ASSERT_STATIC (sizeof (int) == sizeof (hb_options_union_t)); +static_assert ((sizeof (int) == sizeof (hb_options_union_t)), ""); HB_INTERNAL void _hb_options_init (void); @@ -1021,4 +869,31 @@ hb_options (void) /* Size signifying variable-sized array */ #define VAR 1 + +/* String type. */ + +struct hb_string_t +{ + inline hb_string_t (void) : bytes (nullptr), len (0) {} + inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {} + + inline int cmp (const hb_string_t &a) const + { + if (len != a.len) + return (int) a.len - (int) len; + + return memcmp (a.bytes, bytes, len); + } + static inline int cmp (const void *pa, const void *pb) + { + hb_string_t *a = (hb_string_t *) pa; + hb_string_t *b = (hb_string_t *) pb; + return b->cmp (*a); + } + + const char *bytes; + unsigned int len; +}; + + #endif /* HB_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-digest-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-digest-private.hh new file mode 100644 index 0000000000..e099a82641 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-set-digest-private.hh @@ -0,0 +1,179 @@ +/* + * Copyright © 2012 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 + */ + +#ifndef HB_SET_DIGEST_PRIVATE_HH +#define HB_SET_DIGEST_PRIVATE_HH + +#include "hb-private.hh" + +/* + * The set digests here implement various "filters" that support + * "approximate member query". Conceptually these are like Bloom + * Filter and Quotient Filter, however, much smaller, faster, and + * designed to fit the requirements of our uses for glyph coverage + * queries. + * + * Our filters are highly accurate if the lookup covers fairly local + * set of glyphs, but fully flooded and ineffective if coverage is + * all over the place. + * + * The frozen-set can be used instead of a digest, to trade more + * memory for 100% accuracy, but in practice, that doesn't look like + * an attractive trade-off. + */ + +template <typename mask_t, unsigned int shift> +struct hb_set_digest_lowest_bits_t +{ + ASSERT_POD (); + + static const unsigned int mask_bytes = sizeof (mask_t); + static const unsigned int mask_bits = sizeof (mask_t) * 8; + static const unsigned int num_bits = 0 + + (mask_bytes >= 1 ? 3 : 0) + + (mask_bytes >= 2 ? 1 : 0) + + (mask_bytes >= 4 ? 1 : 0) + + (mask_bytes >= 8 ? 1 : 0) + + (mask_bytes >= 16? 1 : 0) + + 0; + + static_assert ((shift < sizeof (hb_codepoint_t) * 8), ""); + static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), ""); + + inline void init (void) { + mask = 0; + } + + inline void add (hb_codepoint_t g) { + mask |= mask_for (g); + } + + inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) { + if ((b >> shift) - (a >> shift) >= mask_bits - 1) + mask = (mask_t) -1; + else { + mask_t ma = mask_for (a); + mask_t mb = mask_for (b); + mask |= mb + (mb - ma) - (mb < ma); + } + return true; + } + + template <typename T> + inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + for (unsigned int i = 0; i < count; i++) + { + add (*array); + array = (const T *) (stride + (const char *) array); + } + } + template <typename T> + inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + for (unsigned int i = 0; i < count; i++) + { + add (*array); + array = (const T *) (stride + (const char *) array); + } + return true; + } + + inline bool may_have (hb_codepoint_t g) const { + return !!(mask & mask_for (g)); + } + + private: + + static inline mask_t mask_for (hb_codepoint_t g) { + return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); + } + mask_t mask; +}; + +template <typename head_t, typename tail_t> +struct hb_set_digest_combiner_t +{ + ASSERT_POD (); + + inline void init (void) { + head.init (); + tail.init (); + } + + inline void add (hb_codepoint_t g) { + head.add (g); + tail.add (g); + } + + inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) { + head.add_range (a, b); + tail.add_range (a, b); + return true; + } + template <typename T> + inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + head.add_array (array, count, stride); + tail.add_array (array, count, stride); + } + template <typename T> + inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + head.add_sorted_array (array, count, stride); + tail.add_sorted_array (array, count, stride); + return true; + } + + inline bool may_have (hb_codepoint_t g) const { + return head.may_have (g) && tail.may_have (g); + } + + private: + head_t head; + tail_t tail; +}; + + +/* + * hb_set_digest_t + * + * This is a combination of digests that performs "best". + * There is not much science to this: it's a result of intuition + * and testing. + */ +typedef hb_set_digest_combiner_t +< + hb_set_digest_lowest_bits_t<unsigned long, 4>, + hb_set_digest_combiner_t + < + hb_set_digest_lowest_bits_t<unsigned long, 0>, + hb_set_digest_lowest_bits_t<unsigned long, 9> + > +> hb_set_digest_t; + + +#endif /* HB_SET_DIGEST_PRIVATE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh index e2010d7626..9c6f3ee37a 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-set-private.hh @@ -1,5 +1,5 @@ /* - * Copyright © 2012 Google, Inc. + * Copyright © 2012,2017 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -32,254 +32,462 @@ /* - * The set digests here implement various "filters" that support - * "approximate member query". Conceptually these are like Bloom - * Filter and Quotient Filter, however, much smaller, faster, and - * designed to fit the requirements of our uses for glyph coverage - * queries. - * - * Our filters are highly accurate if the lookup covers fairly local - * set of glyphs, but fully flooded and ineffective if coverage is - * all over the place. - * - * The frozen-set can be used instead of a digest, to trade more - * memory for 100% accuracy, but in practice, that doesn't look like - * an attractive trade-off. + * hb_set_t */ -template <typename mask_t, unsigned int shift> -struct hb_set_digest_lowest_bits_t -{ - ASSERT_POD (); - - static const unsigned int mask_bytes = sizeof (mask_t); - static const unsigned int mask_bits = sizeof (mask_t) * 8; - static const unsigned int num_bits = 0 - + (mask_bytes >= 1 ? 3 : 0) - + (mask_bytes >= 2 ? 1 : 0) - + (mask_bytes >= 4 ? 1 : 0) - + (mask_bytes >= 8 ? 1 : 0) - + (mask_bytes >= 16? 1 : 0) - + 0; - - ASSERT_STATIC (shift < sizeof (hb_codepoint_t) * 8); - ASSERT_STATIC (shift + num_bits <= sizeof (hb_codepoint_t) * 8); - - inline void init (void) { - mask = 0; - } +/* TODO Keep a free-list so we can free pages that are completely zeroed. At that + * point maybe also use a sentinel value for "all-1" pages? */ - inline void add (hb_codepoint_t g) { - mask |= mask_for (g); - } - - inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { - if ((b >> shift) - (a >> shift) >= mask_bits - 1) - mask = (mask_t) -1; - else { - mask_t ma = mask_for (a); - mask_t mb = mask_for (b); - mask |= mb + (mb - ma) - (mb < ma); - } - } +struct hb_set_t +{ + struct page_map_t + { + inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; } - inline bool may_have (hb_codepoint_t g) const { - return !!(mask & mask_for (g)); - } + uint32_t major; + uint32_t index; + }; - private: + struct page_t + { + inline void init0 (void) { memset (&v, 0, sizeof (v)); } + inline void init1 (void) { memset (&v, 0xff, sizeof (v)); } - static inline mask_t mask_for (hb_codepoint_t g) { - return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); - } - mask_t mask; -}; + inline unsigned int len (void) const + { return ARRAY_LENGTH_CONST (v); } -template <typename head_t, typename tail_t> -struct hb_set_digest_combiner_t -{ - ASSERT_POD (); - - inline void init (void) { - head.init (); - tail.init (); - } + inline bool is_empty (void) const + { + for (unsigned int i = 0; i < len (); i++) + if (v[i]) + return false; + return true; + } - inline void add (hb_codepoint_t g) { - head.add (g); - tail.add (g); - } + inline void add (hb_codepoint_t g) { elt (g) |= mask (g); } + inline void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } + inline bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); } - inline void add_range (hb_codepoint_t a, hb_codepoint_t b) { - head.add_range (a, b); - tail.add_range (a, b); - } + inline void add_range (hb_codepoint_t a, hb_codepoint_t b) + { + elt_t *la = &elt (a); + elt_t *lb = &elt (b); + if (la == lb) + *la |= (mask (b) << 1) - mask(a); + else + { + *la |= ~(mask (a) - 1); + la++; + + memset (la, 0xff, (char *) lb - (char *) la); + + *lb |= ((mask (b) << 1) - 1); + } + } - inline bool may_have (hb_codepoint_t g) const { - return head.may_have (g) && tail.may_have (g); - } + inline bool is_equal (const page_t *other) const + { + return 0 == memcmp (&v, &other->v, sizeof (v)); + } - private: - head_t head; - tail_t tail; -}; + inline unsigned int get_population (void) const + { + unsigned int pop = 0; + for (unsigned int i = 0; i < len (); i++) + pop += _hb_popcount (v[i]); + return pop; + } + inline bool next (hb_codepoint_t *codepoint) const + { + unsigned int m = (*codepoint + 1) & MASK; + if (!m) + { + *codepoint = INVALID; + return false; + } + unsigned int i = m / ELT_BITS; + unsigned int j = m & ELT_MASK; + + for (; j < ELT_BITS; j++) + if (v[i] & (elt_t (1) << j)) + goto found; + for (i++; i < len (); i++) + if (v[i]) + for (j = 0; j < ELT_BITS; j++) + if (v[i] & (elt_t (1) << j)) + goto found; + + *codepoint = INVALID; + return false; -/* - * hb_set_digest_t - * - * This is a combination of digests that performs "best". - * There is not much science to this: it's a result of intuition - * and testing. - */ -typedef hb_set_digest_combiner_t -< - hb_set_digest_lowest_bits_t<unsigned long, 4>, - hb_set_digest_combiner_t - < - hb_set_digest_lowest_bits_t<unsigned long, 0>, - hb_set_digest_lowest_bits_t<unsigned long, 9> - > -> hb_set_digest_t; + found: + *codepoint = i * ELT_BITS + j; + return true; + } + inline hb_codepoint_t get_min (void) const + { + for (unsigned int i = 0; i < len (); i++) + if (v[i]) + { + elt_t e = v[i]; + for (unsigned int j = 0; j < ELT_BITS; j++) + if (e & (elt_t (1) << j)) + return i * ELT_BITS + j; + } + return INVALID; + } + inline hb_codepoint_t get_max (void) const + { + for (int i = len () - 1; i >= 0; i--) + if (v[i]) + { + elt_t e = v[i]; + for (int j = ELT_BITS - 1; j >= 0; j--) + if (e & (elt_t (1) << j)) + return i * ELT_BITS + j; + } + return 0; + } + static const unsigned int PAGE_BITS = 8192; /* Use to tune. */ + static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, ""); + typedef uint64_t elt_t; -/* - * hb_set_t - */ +#if 0 && HAVE_VECTOR_SIZE + /* The vectorized version does not work with clang as non-const + * elt() errs "non-const reference cannot bind to vector element". */ + typedef elt_t vector_t __attribute__((vector_size (PAGE_BITS / 8))); +#else + typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t; +#endif + vector_t v; -/* TODO Make this faster and memmory efficient. */ + static const unsigned int ELT_BITS = sizeof (elt_t) * 8; + static const unsigned int ELT_MASK = ELT_BITS - 1; + static const unsigned int BITS = sizeof (vector_t) * 8; + static const unsigned int MASK = BITS - 1; + static_assert (PAGE_BITS == BITS, ""); -struct hb_set_t -{ - friend struct hb_frozen_set_t; + elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; } + elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; } + elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); } + }; + static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, ""); hb_object_header_t header; ASSERT_POD (); bool in_error; + hb_prealloced_array_t<page_map_t, 8> page_map; + hb_prealloced_array_t<page_t, 1> pages; - inline void init (void) { - hb_object_init (this); - clear (); + inline void init (void) + { + page_map.init (); + pages.init (); } - inline void fini (void) { + inline void finish (void) + { + page_map.finish (); + pages.finish (); + } + + inline bool resize (unsigned int count) + { + if (unlikely (in_error)) return false; + if (!pages.resize (count) || !page_map.resize (count)) + { + pages.resize (page_map.len); + in_error = true; + return false; + } + return true; } + inline void clear (void) { if (unlikely (hb_object_is_inert (this))) return; in_error = false; - memset (elts, 0, sizeof elts); + page_map.resize (0); + pages.resize (0); } inline bool is_empty (void) const { - for (unsigned int i = 0; i < ARRAY_LENGTH (elts); i++) - if (elts[i]) + unsigned int count = pages.len; + for (unsigned int i = 0; i < count; i++) + if (!pages[i].is_empty ()) return false; return true; } + inline void add (hb_codepoint_t g) { if (unlikely (in_error)) return; if (unlikely (g == INVALID)) return; - if (unlikely (g > MAX_G)) return; - elt (g) |= mask (g); + page_t *page = page_for_insert (g); if (unlikely (!page)) return; + page->add (g); } - inline void add_range (hb_codepoint_t a, hb_codepoint_t b) + inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */ + if (unlikely (a > b || a == INVALID || b == INVALID)) return false; + unsigned int ma = get_major (a); + unsigned int mb = get_major (b); + if (ma == mb) + { + page_t *page = page_for_insert (a); if (unlikely (!page)) return false; + page->add_range (a, b); + } + else + { + page_t *page = page_for_insert (a); if (unlikely (!page)) return false; + page->add_range (a, major_start (ma + 1) - 1); + + for (unsigned int m = ma + 1; m < mb; m++) + { + page = page_for_insert (major_start (m)); if (unlikely (!page)) return false; + page->init1 (); + } + + page = page_for_insert (b); if (unlikely (!page)) return false; + page->add_range (major_start (mb), b); + } + return true; + } + + template <typename T> + inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) { if (unlikely (in_error)) return; - /* TODO Speedup */ - for (unsigned int i = a; i < b + 1; i++) - add (i); + if (!count) return; + hb_codepoint_t g = *array; + while (count) + { + unsigned int m = get_major (g); + page_t *page = page_for_insert (g); if (unlikely (!page)) return; + unsigned int start = major_start (m); + unsigned int end = major_start (m + 1); + do + { + page->add (g); + + array++; + count--; + } + while (count && (g = *array, start <= g && g < end)); + } + } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template <typename T> + inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + if (unlikely (in_error)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */ + if (!count) return true; + hb_codepoint_t g = *array; + hb_codepoint_t last_g = g; + while (count) + { + unsigned int m = get_major (g); + page_t *page = page_for_insert (g); if (unlikely (!page)) return false; + unsigned int end = major_start (m + 1); + do + { + /* If we try harder we can change the following comparison to <=; + * Not sure if it's worth it. */ + if (g < last_g) return false; + last_g = g; + page->add (g); + + array++; + count--; + } + while (count && (g = *array, g < end)); + } + return true; } + inline void del (hb_codepoint_t g) { if (unlikely (in_error)) return; - if (unlikely (g > MAX_G)) return; - elt (g) &= ~mask (g); + page_t *p = page_for (g); + if (!p) + return; + p->del (g); } inline void del_range (hb_codepoint_t a, hb_codepoint_t b) { + /* TODO Optimize, like add_range(). */ if (unlikely (in_error)) return; - /* TODO Speedup */ for (unsigned int i = a; i < b + 1; i++) del (i); } inline bool has (hb_codepoint_t g) const { - if (unlikely (g > MAX_G)) return false; - return !!(elt (g) & mask (g)); + const page_t *p = page_for (g); + if (!p) + return false; + return p->has (g); } inline bool intersects (hb_codepoint_t first, hb_codepoint_t last) const { - if (unlikely (first > MAX_G)) return false; - if (unlikely (last > MAX_G)) last = MAX_G; - unsigned int end = last + 1; - for (hb_codepoint_t i = first; i < end; i++) - if (has (i)) - return true; - return false; + hb_codepoint_t c = first - 1; + return next (&c) && c <= last; + } + inline void set (const hb_set_t *other) + { + if (unlikely (in_error)) return; + unsigned int count = other->pages.len; + if (!resize (count)) + return; + + memcpy (pages.array, other->pages.array, count * sizeof (pages.array[0])); + memcpy (page_map.array, other->page_map.array, count * sizeof (page_map.array[0])); } + inline bool is_equal (const hb_set_t *other) const { - for (unsigned int i = 0; i < ELTS; i++) - if (elts[i] != other->elts[i]) + unsigned int na = pages.len; + unsigned int nb = other->pages.len; + + unsigned int a = 0, b = 0; + for (; a < na && b < nb; ) + { + if (page_at (a).is_empty ()) { a++; continue; } + if (other->page_at (b).is_empty ()) { b++; continue; } + if (page_map[a].major != other->page_map[b].major || + !page_at (a).is_equal (&other->page_at (b))) return false; + a++; + b++; + } + for (; a < na; a++) + if (!page_at (a).is_empty ()) { return false; } + for (; b < nb; b++) + if (!other->page_at (b).is_empty ()) { return false; } + return true; } - inline void set (const hb_set_t *other) + + template <class Op> + inline void process (const hb_set_t *other) { if (unlikely (in_error)) return; - for (unsigned int i = 0; i < ELTS; i++) - elts[i] = other->elts[i]; + + unsigned int na = pages.len; + unsigned int nb = other->pages.len; + + unsigned int count = 0; + unsigned int a = 0, b = 0; + for (; a < na && b < nb; ) + { + if (page_map[a].major == other->page_map[b].major) + { + count++; + a++; + b++; + } + else if (page_map[a].major < other->page_map[b].major) + { + if (Op::passthru_left) + count++; + a++; + } + else + { + if (Op::passthru_right) + count++; + b++; + } + } + if (Op::passthru_left) + count += na - a; + if (Op::passthru_right) + count += nb - b; + + if (!resize (count)) + return; + + /* Process in-place backward. */ + a = na; + b = nb; + for (; a && b; ) + { + if (page_map[a - 1].major == other->page_map[b - 1].major) + { + a--; + b--; + Op::process (page_at (--count).v, page_at (a).v, other->page_at (b).v); + } + else if (page_map[a - 1].major > other->page_map[b - 1].major) + { + a--; + if (Op::passthru_left) + page_at (--count).v = page_at (a).v; + } + else + { + b--; + if (Op::passthru_right) + page_at (--count).v = other->page_at (b).v; + } + } + if (Op::passthru_left) + while (a) + page_at (--count).v = page_at (--a).v; + if (Op::passthru_right) + while (b) + page_at (--count).v = other->page_at (--b).v; + assert (!count); } + inline void union_ (const hb_set_t *other) { - if (unlikely (in_error)) return; - for (unsigned int i = 0; i < ELTS; i++) - elts[i] |= other->elts[i]; + process<HbOpOr> (other); } inline void intersect (const hb_set_t *other) { - if (unlikely (in_error)) return; - for (unsigned int i = 0; i < ELTS; i++) - elts[i] &= other->elts[i]; + process<HbOpAnd> (other); } inline void subtract (const hb_set_t *other) { - if (unlikely (in_error)) return; - for (unsigned int i = 0; i < ELTS; i++) - elts[i] &= ~other->elts[i]; + process<HbOpMinus> (other); } inline void symmetric_difference (const hb_set_t *other) { - if (unlikely (in_error)) return; - for (unsigned int i = 0; i < ELTS; i++) - elts[i] ^= other->elts[i]; - } - inline void invert (void) - { - if (unlikely (in_error)) return; - for (unsigned int i = 0; i < ELTS; i++) - elts[i] = ~elts[i]; + process<HbOpXor> (other); } inline bool next (hb_codepoint_t *codepoint) const { if (unlikely (*codepoint == INVALID)) { - hb_codepoint_t i = get_min (); - if (i != INVALID) { - *codepoint = i; - return true; - } else { - *codepoint = INVALID; - return false; + *codepoint = get_min (); + return *codepoint != INVALID; + } + + page_map_t map = {get_major (*codepoint), 0}; + unsigned int i; + page_map.bfind (&map, &i); + if (i < page_map.len) + { + if (pages[page_map[i].index].next (codepoint)) + { + *codepoint += page_map[i].major * page_t::PAGE_BITS; + return true; } + i++; } - for (hb_codepoint_t i = *codepoint + 1; i < MAX_G + 1; i++) - if (has (i)) { - *codepoint = i; + for (; i < page_map.len; i++) + { + hb_codepoint_t m = pages[page_map[i].index].get_min (); + if (m != INVALID) + { + *codepoint = page_map[i].major * page_t::PAGE_BITS + m; return true; } + } *codepoint = INVALID; return false; } @@ -303,99 +511,66 @@ struct hb_set_t inline unsigned int get_population (void) const { - unsigned int count = 0; - for (unsigned int i = 0; i < ELTS; i++) - count += _hb_popcount32 (elts[i]); - return count; + unsigned int pop = 0; + unsigned int count = pages.len; + for (unsigned int i = 0; i < count; i++) + pop += pages[i].get_population (); + return pop; } inline hb_codepoint_t get_min (void) const { - for (unsigned int i = 0; i < ELTS; i++) - if (elts[i]) - for (unsigned int j = 0; j < BITS; j++) - if (elts[i] & (1u << j)) - return i * BITS + j; + unsigned int count = pages.len; + for (unsigned int i = 0; i < count; i++) + if (!page_at (i).is_empty ()) + return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min (); return INVALID; } inline hb_codepoint_t get_max (void) const { - for (unsigned int i = ELTS; i; i--) - if (elts[i - 1]) - for (unsigned int j = BITS; j; j--) - if (elts[i - 1] & (1u << (j - 1))) - return (i - 1) * BITS + (j - 1); + unsigned int count = pages.len; + for (int i = count - 1; i >= 0; i++) + if (!page_at (i).is_empty ()) + return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_max (); return INVALID; } - typedef uint32_t elt_t; - static const unsigned int MAX_G = 65536 - 1; /* XXX Fix this... */ - static const unsigned int SHIFT = 5; - static const unsigned int BITS = (1 << SHIFT); - static const unsigned int MASK = BITS - 1; - static const unsigned int ELTS = (MAX_G + 1 + (BITS - 1)) / BITS; static const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; - elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; } - elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } - elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } - - elt_t elts[ELTS]; /* XXX 8kb */ - - ASSERT_STATIC (sizeof (elt_t) * 8 == BITS); - ASSERT_STATIC (sizeof (elt_t) * 8 * ELTS > MAX_G); -}; - -struct hb_frozen_set_t -{ - static const unsigned int SHIFT = hb_set_t::SHIFT; - static const unsigned int BITS = hb_set_t::BITS; - static const unsigned int MASK = hb_set_t::MASK; - typedef hb_set_t::elt_t elt_t; - - inline void init (const hb_set_t &set) + inline page_t *page_for_insert (hb_codepoint_t g) { - start = count = 0; - elts = NULL; - - unsigned int max = set.get_max (); - if (max == set.INVALID) - return; - unsigned int min = set.get_min (); - const elt_t &min_elt = set.elt (min); - - start = min & ~MASK; - count = max - start + 1; - unsigned int num_elts = (count + BITS - 1) / BITS; - unsigned int elts_size = num_elts * sizeof (elt_t); - elts = (elt_t *) malloc (elts_size); - if (unlikely (!elts)) + page_map_t map = {get_major (g), pages.len}; + unsigned int i; + if (!page_map.bfind (&map, &i)) { - start = count = 0; - return; + if (!resize (pages.len + 1)) + return nullptr; + + pages[map.index].init0 (); + memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0])); + page_map[i] = map; } - memcpy (elts, &min_elt, elts_size); + return &pages[page_map[i].index]; } - - inline void fini (void) + inline page_t *page_for (hb_codepoint_t g) { - if (elts) - free (elts); + page_map_t key = {get_major (g)}; + const page_map_t *found = page_map.bsearch (&key); + if (found) + return &pages[found->index]; + return nullptr; } - - inline bool has (hb_codepoint_t g) const + inline const page_t *page_for (hb_codepoint_t g) const { - /* hb_codepoint_t is unsigned. */ - g -= start; - if (unlikely (g > count)) return false; - return !!(elt (g) & mask (g)); - } - - elt_t const &elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; } - elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); } - - private: - hb_codepoint_t start, count; - elt_t *elts; + page_map_t key = {get_major (g)}; + const page_map_t *found = page_map.bsearch (&key); + if (found) + return &pages[found->index]; + return nullptr; + } + inline page_t &page_at (unsigned int i) { return pages[page_map[i].index]; } + inline const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; } + inline unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; } + inline hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; } }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.cc b/src/3rdparty/harfbuzz-ng/src/hb-set.cc index cb7fcdbf64..0b4f871e85 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-set.cc @@ -45,7 +45,7 @@ hb_set_create (void) if (!(set = hb_object_create<hb_set_t> ())) return hb_set_get_empty (); - set->clear (); + set->init (); return set; } @@ -95,7 +95,7 @@ hb_set_destroy (hb_set_t *set) { if (!hb_object_destroy (set)) return; - set->fini (); + set->finish (); free (set); } @@ -105,7 +105,7 @@ hb_set_destroy (hb_set_t *set) * @set: a set. * @key: * @data: - * @destroy (closure data): + * @destroy: * @replace: * * Return value: @@ -376,11 +376,12 @@ hb_set_symmetric_difference (hb_set_t *set, * * * Since: 0.9.10 + * + * Deprecated: 1.6.1 **/ void hb_set_invert (hb_set_t *set) { - set->invert (); } /** diff --git a/src/3rdparty/harfbuzz-ng/src/hb-set.h b/src/3rdparty/harfbuzz-ng/src/hb-set.h index 2164c1a654..2ce406073c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-set.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-set.h @@ -126,9 +126,6 @@ HB_EXTERN void hb_set_symmetric_difference (hb_set_t *set, const hb_set_t *other); -HB_EXTERN void -hb_set_invert (hb_set_t *set); - HB_EXTERN unsigned int hb_set_get_population (const hb_set_t *set); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc index 600faaeb18..6eeba2b3d1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape-plan.cc @@ -24,24 +24,14 @@ * Google Author(s): Behdad Esfahbod */ +#include "hb-private.hh" +#include "hb-debug.hh" #include "hb-shape-plan-private.hh" #include "hb-shaper-private.hh" #include "hb-font-private.hh" #include "hb-buffer-private.hh" -#ifndef HB_DEBUG_SHAPE_PLAN -#define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0) -#endif - - -#define HB_SHAPER_IMPLEMENT(shaper) \ - HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \ - HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font) -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - - static void hb_shape_plan_plan (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, @@ -122,7 +112,7 @@ hb_shape_plan_create (hb_face_t *face, { return hb_shape_plan_create2 (face, props, user_features, num_user_features, - NULL, 0, + nullptr, 0, shaper_list); } @@ -135,7 +125,7 @@ hb_shape_plan_create2 (hb_face_t *face, unsigned int num_coords, const char * const *shaper_list) { - DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, + DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr, "face=%p num_features=%d num_coords=%d shaper_list=%p", face, num_user_features, @@ -143,8 +133,8 @@ hb_shape_plan_create2 (hb_face_t *face, shaper_list); hb_shape_plan_t *shape_plan; - hb_feature_t *features = NULL; - int *coords = NULL; + hb_feature_t *features = nullptr; + int *coords = nullptr; if (unlikely (!face)) face = hb_face_get_empty (); @@ -167,7 +157,7 @@ hb_shape_plan_create2 (hb_face_t *face, assert (props->direction != HB_DIRECTION_INVALID); hb_face_make_immutable (face); - shape_plan->default_shaper_list = shaper_list == NULL; + shape_plan->default_shaper_list = !shaper_list; shape_plan->face_unsafe = face; shape_plan->props = *props; shape_plan->num_user_features = num_user_features; @@ -203,16 +193,16 @@ hb_shape_plan_get_empty (void) HB_OBJECT_HEADER_STATIC, true, /* default_shaper_list */ - NULL, /* face */ + nullptr, /* face */ HB_SEGMENT_PROPERTIES_DEFAULT, /* props */ - NULL, /* shaper_func */ - NULL, /* shaper_name */ + nullptr, /* shaper_func */ + nullptr, /* shaper_name */ - NULL, /* user_features */ + nullptr, /* user_features */ 0, /* num_user_featurs */ - NULL, /* coords */ + nullptr, /* coords */ 0, /* num_coords */ { @@ -430,7 +420,7 @@ hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && hb_shape_plan_user_features_match (shape_plan, proposal) && hb_shape_plan_coords_match (shape_plan, proposal) && - ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || + ((shape_plan->default_shaper_list && !proposal->shaper_list) || (shape_plan->shaper_func == proposal->shaper_func)); } @@ -438,11 +428,12 @@ static inline hb_bool_t hb_non_global_user_features_present (const hb_feature_t *user_features, unsigned int num_user_features) { - while (num_user_features) + while (num_user_features) { if (user_features->start != 0 || user_features->end != (unsigned int) -1) return true; - else - num_user_features--, user_features++; + num_user_features--; + user_features++; + } return false; } @@ -476,7 +467,7 @@ hb_shape_plan_create_cached (hb_face_t *face, { return hb_shape_plan_create_cached2 (face, props, user_features, num_user_features, - NULL, 0, + nullptr, 0, shaper_list); } @@ -489,7 +480,7 @@ hb_shape_plan_create_cached2 (hb_face_t *face, unsigned int num_coords, const char * const *shaper_list) { - DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, + DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr, "face=%p num_features=%d shaper_list=%p", face, num_user_features, @@ -500,7 +491,7 @@ hb_shape_plan_create_cached2 (hb_face_t *face, shaper_list, user_features, num_user_features, - NULL + nullptr }; if (shaper_list) { @@ -526,15 +517,17 @@ hb_shape_plan_create_cached2 (hb_face_t *face, retry: hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans); - for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) - if (hb_shape_plan_matches (node->shape_plan, &proposal)) - { - DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); - return hb_shape_plan_reference (node->shape_plan); - } - /* Not found. */ + /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */ + if (!hb_coords_present (coords, num_coords)) + for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) + if (hb_shape_plan_matches (node->shape_plan, &proposal)) + { + DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); + return hb_shape_plan_reference (node->shape_plan); + } + /* Not found. */ hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, user_features, num_user_features, coords, num_coords, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc index 706f14420d..39355b337d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc @@ -45,254 +45,6 @@ * contains the output glyphs and their positions. **/ -static bool -parse_space (const char **pp, const char *end) -{ - while (*pp < end && ISSPACE (**pp)) - (*pp)++; - return true; -} - -static bool -parse_char (const char **pp, const char *end, char c) -{ - parse_space (pp, end); - - if (*pp == end || **pp != c) - return false; - - (*pp)++; - return true; -} - -static bool -parse_uint (const char **pp, const char *end, unsigned int *pv) -{ - char buf[32]; - unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp)); - strncpy (buf, *pp, len); - buf[len] = '\0'; - - char *p = buf; - char *pend = p; - unsigned int v; - - /* Intentionally use strtol instead of strtoul, such that - * -1 turns into "big number"... */ - errno = 0; - v = strtol (p, &pend, 0); - if (errno || p == pend) - return false; - - *pv = v; - *pp += pend - p; - return true; -} - -static bool -parse_bool (const char **pp, const char *end, unsigned int *pv) -{ - parse_space (pp, end); - - const char *p = *pp; - while (*pp < end && ISALPHA(**pp)) - (*pp)++; - - /* CSS allows on/off as aliases 1/0. */ - if (*pp - p == 2 || 0 == strncmp (p, "on", 2)) - *pv = 1; - else if (*pp - p == 3 || 0 == strncmp (p, "off", 2)) - *pv = 0; - else - return false; - - return true; -} - -static bool -parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature) -{ - if (parse_char (pp, end, '-')) - feature->value = 0; - else { - parse_char (pp, end, '+'); - feature->value = 1; - } - - return true; -} - -static bool -parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature) -{ - parse_space (pp, end); - - char quote = 0; - - if (*pp < end && (**pp == '\'' || **pp == '"')) - { - quote = **pp; - (*pp)++; - } - - const char *p = *pp; - while (*pp < end && ISALNUM(**pp)) - (*pp)++; - - if (p == *pp || *pp - p > 4) - return false; - - feature->tag = hb_tag_from_string (p, *pp - p); - - if (quote) - { - /* CSS expects exactly four bytes. And we only allow quotations for - * CSS compatibility. So, enforce the length. */ - if (*pp - p != 4) - return false; - if (*pp == end || **pp != quote) - return false; - (*pp)++; - } - - return true; -} - -static bool -parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature) -{ - parse_space (pp, end); - - bool has_start; - - feature->start = 0; - feature->end = (unsigned int) -1; - - if (!parse_char (pp, end, '[')) - return true; - - has_start = parse_uint (pp, end, &feature->start); - - if (parse_char (pp, end, ':')) { - parse_uint (pp, end, &feature->end); - } else { - if (has_start) - feature->end = feature->start + 1; - } - - return parse_char (pp, end, ']'); -} - -static bool -parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature) -{ - bool had_equal = parse_char (pp, end, '='); - bool had_value = parse_uint (pp, end, &feature->value) || - parse_bool (pp, end, &feature->value); - /* CSS doesn't use equal-sign between tag and value. - * If there was an equal-sign, then there *must* be a value. - * A value without an eqaul-sign is ok, but not required. */ - return !had_equal || had_value; -} - - -static bool -parse_one_feature (const char **pp, const char *end, hb_feature_t *feature) -{ - return parse_feature_value_prefix (pp, end, feature) && - parse_feature_tag (pp, end, feature) && - parse_feature_indices (pp, end, feature) && - parse_feature_value_postfix (pp, end, feature) && - parse_space (pp, end) && - *pp == end; -} - -/** - * hb_feature_from_string: - * @str: (array length=len) (element-type uint8_t): a string to parse - * @len: length of @str, or -1 if string is %NULL terminated - * @feature: (out): the #hb_feature_t to initialize with the parsed values - * - * Parses a string into a #hb_feature_t. - * - * TODO: document the syntax here. - * - * Return value: - * %true if @str is successfully parsed, %false otherwise. - * - * Since: 0.9.5 - **/ -hb_bool_t -hb_feature_from_string (const char *str, int len, - hb_feature_t *feature) -{ - hb_feature_t feat; - - if (len < 0) - len = strlen (str); - - if (likely (parse_one_feature (&str, str + len, &feat))) - { - if (feature) - *feature = feat; - return true; - } - - if (feature) - memset (feature, 0, sizeof (*feature)); - return false; -} - -/** - * hb_feature_to_string: - * @feature: an #hb_feature_t to convert - * @buf: (array length=size) (out): output string - * @size: the allocated size of @buf - * - * Converts a #hb_feature_t into a %NULL-terminated string in the format - * understood by hb_feature_from_string(). The client in responsible for - * allocating big enough size for @buf, 128 bytes is more than enough. - * - * Since: 0.9.5 - **/ -void -hb_feature_to_string (hb_feature_t *feature, - char *buf, unsigned int size) -{ - if (unlikely (!size)) return; - - char s[128]; - unsigned int len = 0; - if (feature->value == 0) - s[len++] = '-'; - hb_tag_to_string (feature->tag, s + len); - len += 4; - while (len && s[len - 1] == ' ') - len--; - if (feature->start != 0 || feature->end != (unsigned int) -1) - { - s[len++] = '['; - if (feature->start) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start)); - if (feature->end != feature->start + 1) { - s[len++] = ':'; - if (feature->end != (unsigned int) -1) - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end)); - } - s[len++] = ']'; - } - if (feature->value > 1) - { - s[len++] = '='; - len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value)); - } - assert (len < ARRAY_LENGTH (s)); - len = MIN (len, size - 1); - memcpy (buf, s, len); - buf[len] = '\0'; -} - - static const char **static_shaper_list; #ifdef HB_USE_ATEXIT @@ -324,7 +76,7 @@ retry: /* Not found; allocate one. */ shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *)); if (unlikely (!shaper_list)) { - static const char *nil_shaper_list[] = {NULL}; + static const char *nil_shaper_list[] = {nullptr}; return nil_shaper_list; } @@ -332,9 +84,9 @@ retry: unsigned int i; for (i = 0; i < HB_SHAPERS_COUNT; i++) shaper_list[i] = shapers[i].name; - shaper_list[i] = NULL; + shaper_list[i] = nullptr; - if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) { + if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) { free (shaper_list); goto retry; } @@ -362,7 +114,7 @@ retry: * shapers will be used in the given order, otherwise the default shapers list * will be used. * - * Return value: %FALSE if all shapers failed, %TRUE otherwise + * Return value: false if all shapers failed, true otherwise * * Since: 0.9.2 **/ @@ -405,5 +157,5 @@ hb_shape (hb_font_t *font, const hb_feature_t *features, unsigned int num_features) { - hb_shape_full (font, buffer, features, num_features, NULL); + hb_shape_full (font, buffer, features, num_features, nullptr); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.h b/src/3rdparty/harfbuzz-ng/src/hb-shape.h index 53bb845bf4..39507ff744 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.h @@ -40,22 +40,6 @@ HB_BEGIN_DECLS -typedef struct hb_feature_t { - hb_tag_t tag; - uint32_t value; - unsigned int start; - unsigned int end; -} hb_feature_t; - -HB_EXTERN hb_bool_t -hb_feature_from_string (const char *str, int len, - hb_feature_t *feature); - -HB_EXTERN void -hb_feature_to_string (hb_feature_t *feature, - char *buf, unsigned int size); - - HB_EXTERN void hb_shape (hb_font_t *font, hb_buffer_t *buffer, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shaper-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-shaper-private.hh index d1d1146dad..ce2d9f2839 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shaper-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-shaper-private.hh @@ -65,35 +65,51 @@ struct hb_shaper_data_t { #define HB_SHAPER_DATA_INVALID ((void *) -1) #define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID) -#define HB_SHAPER_DATA_TYPE(shaper, object) struct hb_##shaper##_shaper_##object##_data_t +#define HB_SHAPER_DATA_TYPE_NAME(shaper, object) hb_##shaper##_shaper_##object##_data_t +#define HB_SHAPER_DATA_TYPE(shaper, object) struct HB_SHAPER_DATA_TYPE_NAME(shaper, object) #define HB_SHAPER_DATA_INSTANCE(shaper, object, instance) (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper) -#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE (shaper, object, object) +#define HB_SHAPER_DATA(shaper, object) HB_SHAPER_DATA_INSTANCE(shaper, object, object) #define HB_SHAPER_DATA_CREATE_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_create #define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object) _hb_##shaper##_shaper_##object##_data_destroy +#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) hb_##shaper##_shaper_##object##_data_ensure #define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \ HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \ extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \ HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \ extern "C" HB_INTERNAL void \ - HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data) + HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \ + extern "C" HB_INTERNAL bool \ + HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object) #define HB_SHAPER_DATA_DESTROY(shaper, object) \ if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \ if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \ HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); -#define HB_SHAPER_DATA_ENSURE_DECLARE(shaper, object) \ -static inline bool \ -hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \ +#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \ + HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true) + +#define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \ +bool \ +HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \ {\ retry: \ HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \ + if (likely (data) && !(condition)) { \ + /* Drop and recreate. */ \ + /* If someone dropped it in the mean time, throw it away and don't touch it. \ + * Otherwise, destruct it. */ \ + if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, nullptr)) { \ + HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \ + } \ + goto retry; \ + } \ if (unlikely (!data)) { \ data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \ if (unlikely (!data)) \ data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \ - if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), NULL, data)) { \ + if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), nullptr, data)) { \ if (data && \ data != HB_SHAPER_DATA_INVALID && \ data != HB_SHAPER_DATA_SUCCEEDED) \ @@ -101,7 +117,7 @@ hb_##shaper##_shaper_##object##_data_ensure (hb_##object##_t *object) \ goto retry; \ } \ } \ - return data != NULL && !HB_SHAPER_DATA_IS_INVALID (data); \ + return data != nullptr && !HB_SHAPER_DATA_IS_INVALID (data); \ } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc b/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc index b25566d8a7..2c44cf2653 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shaper.cc @@ -59,14 +59,14 @@ retry: { char *env = getenv ("HB_SHAPER_LIST"); if (!env || !*env) { - (void) hb_atomic_ptr_cmpexch (&static_shapers, NULL, &all_shapers[0]); + (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]); return (const hb_shaper_pair_t *) all_shapers; } /* Not found; allocate one. */ shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers)); if (unlikely (!shapers)) { - (void) hb_atomic_ptr_cmpexch (&static_shapers, NULL, &all_shapers[0]); + (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]); return (const hb_shaper_pair_t *) all_shapers; } @@ -97,7 +97,7 @@ retry: p = end + 1; } - if (!hb_atomic_ptr_cmpexch (&static_shapers, NULL, shapers)) { + if (!hb_atomic_ptr_cmpexch (&static_shapers, nullptr, shapers)) { free (shapers); goto retry; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-string-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-string-array.hh new file mode 100644 index 0000000000..ba829b0cf0 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-string-array.hh @@ -0,0 +1,81 @@ +/* + * Copyright © 2017 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 + */ + +#ifndef HB_STRING_ARRAY_HH +#if 0 /* Make checks happy. */ +#define HB_STRING_ARRAY_HH +#endif + +#include "hb-private.hh" + +/* Based on Bruno Haible's code in Appendix B of Ulrich Drepper's dsohowto.pdf: + * https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf */ + +#define HB_STRING_ARRAY_TYPE_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr_t) +#define HB_STRING_ARRAY_POOL_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgstr) +#define HB_STRING_ARRAY_OFFS_NAME HB_PASTE(HB_STRING_ARRAY_NAME, _msgidx) + +static const union HB_STRING_ARRAY_TYPE_NAME { + struct { +/* I like to avoid storing the nul-termination byte since we don't need it, + * but C++ does not allow that. + * https://stackoverflow.com/questions/28433862/why-initializer-string-for-array-of-chars-is-too-long-compiles-fine-in-c-not + */ +#define _S(s) char HB_PASTE (str, __LINE__)[sizeof (s)]; +#include HB_STRING_ARRAY_LIST +#undef _S + } st; + char str[VAR]; +} +HB_STRING_ARRAY_POOL_NAME = +{ + { +#define _S(s) s, +#include HB_STRING_ARRAY_LIST +#undef _S + } +}; +static const unsigned int HB_STRING_ARRAY_OFFS_NAME[] = +{ +#define _S(s) offsetof (union HB_STRING_ARRAY_TYPE_NAME, st.HB_PASTE(str, __LINE__)), +#include HB_STRING_ARRAY_LIST +#undef _S + sizeof (HB_STRING_ARRAY_TYPE_NAME) +}; + +static inline hb_string_t +HB_STRING_ARRAY_NAME (unsigned int i) +{ + assert (i < ARRAY_LENGTH (HB_STRING_ARRAY_OFFS_NAME) - 1); + return hb_string_t (HB_STRING_ARRAY_POOL_NAME.str + HB_STRING_ARRAY_OFFS_NAME[i], + HB_STRING_ARRAY_OFFS_NAME[i + 1] - HB_STRING_ARRAY_OFFS_NAME[i] - 1); +} + +#undef HB_STRING_ARRAY_TYPE_NAME +#undef HB_STRING_ARRAY_POOL_NAME +#undef HB_STRING_ARRAY_OFFS_NAME + +#endif /* HB_STRING_ARRAY_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh index a4d118b6dc..82bb9a4ddc 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode-private.hh @@ -108,7 +108,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE /* XXX This hack belongs to the Myanmar shaper. */ if (unlikely (unicode == 0x1037u)) unicode = 0x103Au; - /* XXX This hack belongs to the SEA shaper (for Tai Tham): + /* XXX This hack belongs to the USE shaper (for Tai Tham): * Reorder SAKOT to ensure it comes after any tone marks. */ if (unlikely (unicode == 0x1A60u)) return 254; @@ -126,7 +126,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE { /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the * Arabic shaper. No need to match them here. */ - return unlikely (hb_in_ranges (unicode, + return unlikely (hb_in_ranges<hb_codepoint_t> (unicode, 0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */ 0xE0100u, 0xE01EFu)); /* VARIATION SELECTOR-17..256 */ } @@ -137,6 +137,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * we do NOT want to hide them, as the way Uniscribe has implemented them * is with regular spacing glyphs, and that's the way fonts are made to work. * As such, we make exceptions for those four. + * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503 * * Unicode 7.0: * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/' @@ -179,13 +180,13 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE case 0x00: return unlikely (ch == 0x00ADu); case 0x03: return unlikely (ch == 0x034Fu); case 0x06: return unlikely (ch == 0x061Cu); - case 0x17: return hb_in_range (ch, 0x17B4u, 0x17B5u); - case 0x18: return hb_in_range (ch, 0x180Bu, 0x180Eu); - case 0x20: return hb_in_ranges (ch, 0x200Bu, 0x200Fu, + case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u); + case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu); + case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu, 0x202Au, 0x202Eu, 0x2060u, 0x206Fu); - case 0xFE: return hb_in_range (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu; - case 0xFF: return hb_in_range (ch, 0xFFF0u, 0xFFF8u); + case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu; + case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u); default: return false; } } @@ -193,9 +194,8 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE { /* Other planes */ switch (plane) { - case 0x01: return hb_in_ranges (ch, 0x1BCA0u, 0x1BCA3u, - 0x1D173u, 0x1D17Au); - case 0x0E: return hb_in_range (ch, 0xE0000u, 0xE0FFFu); + case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au); + case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu); default: return false; } } @@ -346,23 +346,24 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil; #define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */ /* Tibetan - * Modify U+0F74 (ccc=132) to reorder before ccc=130 marks. + * + * In case of multiple vowel-signs, use u first (but after achung) + * this allows Dzongkha multi-vowel shortcuts to render correctly */ #define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */ -#define HB_MODIFIED_COMBINING_CLASS_CCC130 130 /* sign i */ -#define HB_MODIFIED_COMBINING_CLASS_CCC132 128 /* sign u */ - +#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */ +#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */ /* Misc */ #define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \ - (FLAG_SAFE (gen_cat) & \ + (FLAG_UNSAFE (gen_cat) & \ (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK))) #define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL(gen_cat) \ - (FLAG_SAFE (gen_cat) & \ + (FLAG_UNSAFE (gen_cat) & \ (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \ FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL))) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc index d553a7172f..726baeb0f1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-unicode.cc @@ -188,7 +188,7 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent) const hb_unicode_funcs_t _hb_unicode_funcs_nil = { HB_OBJECT_HEADER_STATIC, - NULL, /* parent */ + nullptr, /* parent */ true, /* immutable */ { #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil, @@ -365,7 +365,7 @@ hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \ } else { \ ufuncs->func.name = ufuncs->parent->func.name; \ ufuncs->user_data.name = ufuncs->parent->user_data.name; \ - ufuncs->destroy.name = NULL; \ + ufuncs->destroy.name = nullptr; \ } \ } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh index 74cf5d66a2..211eb4dc02 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-utf-private.hh @@ -48,7 +48,7 @@ struct hb_utf8_t if (c > 0x7Fu) { - if (hb_in_range (c, 0xC2u, 0xDFu)) /* Two-byte */ + if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */ { unsigned int t1; if (likely (text < end && @@ -60,7 +60,7 @@ struct hb_utf8_t else goto error; } - else if (hb_in_range (c, 0xE0u, 0xEFu)) /* Three-byte */ + else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */ { unsigned int t1, t2; if (likely (1 < end - text && @@ -68,14 +68,14 @@ struct hb_utf8_t (t2 = text[1] - 0x80u) <= 0x3Fu)) { c = ((c&0xFu)<<12) | (t1<<6) | t2; - if (unlikely (c < 0x0800u || hb_in_range (c, 0xD800u, 0xDFFFu))) + if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu))) goto error; text += 2; } else goto error; } - else if (hb_in_range (c, 0xF0u, 0xF4u)) /* Four-byte */ + else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */ { unsigned int t1, t2, t3; if (likely (2 < end - text && @@ -84,7 +84,7 @@ struct hb_utf8_t (t3 = text[2] - 0x80u) <= 0x3Fu)) { c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3; - if (unlikely (!hb_in_range (c, 0x10000u, 0x10FFFFu))) + if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu))) goto error; text += 3; } @@ -140,7 +140,7 @@ struct hb_utf16_t { hb_codepoint_t c = *text++; - if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu))) + if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu))) { *unicode = c; return text; @@ -150,7 +150,7 @@ struct hb_utf16_t { /* High-surrogate in c */ hb_codepoint_t l = *text; - if (likely (hb_in_range (l, 0xDC00u, 0xDFFFu))) + if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu))) { /* Low-surrogate in l */ *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u); @@ -172,7 +172,7 @@ struct hb_utf16_t { hb_codepoint_t c = *--text; - if (likely (!hb_in_range (c, 0xD800u, 0xDFFFu))) + if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu))) { *unicode = c; return text; @@ -182,7 +182,7 @@ struct hb_utf16_t { /* Low-surrogate in c */ hb_codepoint_t h = text[-1]; - if (likely (hb_in_range (h, 0xD800u, 0xDBFFu))) + if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu))) { /* High-surrogate in h */ *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h index 0cbe947062..fc81b66b40 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-version.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h @@ -37,10 +37,10 @@ HB_BEGIN_DECLS #define HB_VERSION_MAJOR 1 -#define HB_VERSION_MINOR 4 -#define HB_VERSION_MICRO 1 +#define HB_VERSION_MINOR 7 +#define HB_VERSION_MICRO 4 -#define HB_VERSION_STRING "1.4.1" +#define HB_VERSION_STRING "1.7.4" #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \ |