diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index e46cc6f3f4..da60213038 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -1379,7 +1379,7 @@ License: HarfBuzz Copyright (C) 2009 Keith Stribley Copyright (C) 2009 Martin Hosken and SIL International Copyright (C) 2007 Chris Wilson - Copyright (C) 2006 Behdad Esfahbod + Copyright (C) 2005,2006,2020,2021 Behdad Esfahbod Copyright (C) 2005 David Turner Copyright (C) 2004,2007,2008,2009,2010 Red Hat, Inc. Copyright (C) 1998-2004 David Turner and Werner Lemberg diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 6691f86e60..7cd4db6f67 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -64,6 +64,7 @@ if env["builtin_harfbuzz"]: #'src/hb-gobject-structs.cc', "src/hb-icu.cc", "src/hb-map.cc", + "src/hb-ms-feature-ranges.cc", "src/hb-number.cc", "src/hb-ot-cff1-table.cc", "src/hb-ot-cff2-table.cc", diff --git a/thirdparty/README.md b/thirdparty/README.md index 3b5ec77b73..081c18acae 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -192,13 +192,13 @@ Files extracted from upstream source: ## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 2.8.0 (03538e872a0610a65fad692b33d3646f387cf578, 2021) +- Version: 3.0.0 (9c387e20d65a7a366ac270d789f6ad266014c9e0, 2021) - License: MIT Files extracted from upstream source: - the `src` folder -- `AUTHORS`, `COPYING`, `NEWS`, `THANKS` +- `AUTHORS`, `COPYING`, `THANKS` ## icu4c diff --git a/thirdparty/harfbuzz/COPYING b/thirdparty/harfbuzz/COPYING index 57343164f2..48d1b30f90 100644 --- a/thirdparty/harfbuzz/COPYING +++ b/thirdparty/harfbuzz/COPYING @@ -4,14 +4,14 @@ files names COPYING in subdirectories where applicable. Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc. Copyright © 2018,2019,2020 Ebrahim Byagowi -Copyright © 2019,2020 Facebook, Inc. +Copyright © 2019,2020 Facebook, Inc. Copyright © 2012 Mozilla Foundation Copyright © 2011 Codethink Limited Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies) Copyright © 2009 Keith Stribley Copyright © 2009 Martin Hosken and SIL International Copyright © 2007 Chris Wilson -Copyright © 2006 Behdad Esfahbod +Copyright © 2005,2006,2020,2021 Behdad Esfahbod Copyright © 2005 David Turner Copyright © 2004,2007,2008,2009,2010 Red Hat, Inc. Copyright © 1998-2004 David Turner and Werner Lemberg diff --git a/thirdparty/harfbuzz/NEWS b/thirdparty/harfbuzz/NEWS deleted file mode 100644 index 321c550188..0000000000 --- a/thirdparty/harfbuzz/NEWS +++ /dev/null @@ -1,2457 +0,0 @@ -Overview of changes leading to 2.8.0 -Tuesday, March 16, 2021 -==================================== -- Shape joining scripts other than Arabic/Syriac using the Universal Shaping Engine. - Previously these were shaped using the generalized Arabic shaper. (David Corbett) -- Fix regression in shaping of U+0B55 ORIYA SIGN OVERLINE. (David Corbett) -- Update language tags. (David Corbett) -- Variations: reduce error: do not round each interpolated delta. (Just van Rossum) -- Documentation improvements. (Khaled Hosny, Nathan Willis) -- Subsetter improvements: subsets most, if not all, lookup types now. (Garret Rieger, Qunxin Liu) -- Fuzzer-found fixes and other improvements when memory failures happen. (Behdad) -- Removed most atomic implementations now that we have C++11 atomic impl. (Behdad) -- General codebase upkeep; using more C++11 features: constexpr constructors, etc. (Behdad) - - -Overview of changes leading to 2.7.4 -Sunday, December 27, 2020 -==================================== -- Fix missing --enable-introspection configure option from previous release - tarball. -- Documentation updates. - -Overview of changes leading to 2.7.3 -Wednesday, December 23, 2020 -==================================== -- Update USE shaper to 2020-08-13 specification, and other improvements. -- Don’t disable liga feature in myanmar shaper, to match Uniscribe. -- Improvements to language and script tags handling. -- Update language system tag registry to OpenType 1.8.4 -- Support for serializing and deserializing Unicode buffers. Serialized buffers - are now delimited with `<>` or `[]` based on whether it is a Unicode or - glyphs buffer. -- Increase buffer work limits to handle fonts with many complex lookups. -- Handle more shaping operations in trace output. -- Memory access fixes. -- More OOM fixes. -- Improved documentation. -- Build system improvements. -- New API: -+hb_buffer_has_positions() -+hb_buffer_serialize() -+hb_buffer_serialize_unicode() -+hb_buffer_deserialize_unicode() - - -Overview of changes leading to 2.7.2 -Saturday, August 29, 2020 -==================================== -- Fix a regression in the previous release that caused a crash with Kaithi. -- More OOM fixes. - - -Overview of changes leading to 2.7.1 -Thursday, August 13, 2020 -==================================== -- ot-funcs now handles variable empty glyphs better when hvar/vvar isn't present. -- Reverted a GDEF processing regression. -- A couple of fixes to handle OOM better. - - -Overview of changes leading to 2.7.0 -Saturday, July 25, 2020 -==================================== -- Use an implementation for round that always rounds up, some minor fluctuations - are expected on var font specially when hb-ot callback is used. -- Fix an AAT's `kerx` issue on broken rendering of Devanagari Sangam MN. -- Remove AAT's `lcar` table support from _get_ligature_carets API, not even much - use on macOS installed fonts (only two files). GDEF support is the recommended - one and expected to work properly after issues fixed two releases ago. -- Minor memory fixes to handle OOM better specially in hb-ft. -- Minor .so files versioning scheme change and remove stable/unstable scheme - differences, was never used in practice (always default to stable scheme). -- We are now suggesting careful packaging of the library using meson, - https://github.com/harfbuzz/harfbuzz/wiki/Notes-on-migration-to-meson - for more information. -- Distribution package URL is changed, either use GitHub generated tarballs, - `https://github.com/harfbuzz/harfbuzz/archive/$pkgver.tar.gz` - or, even more preferably use commit hash of the release and git checkouts like, - `git+https://github.com/harfbuzz/harfbuzz#commit=$commit` - - -Overview of changes leading to 2.6.8 -Monday, June 22, 2020 -==================================== -- New API to fetch glyph alternates from GSUB table. -- hb-coretext build fix for macOS < 10.10. -- Meson build fixes, cmake port removal is postponed but please prepare for - it and give us feedback. - Autotools is still our main build system however please consider - experimenting with meson also for packaging the library. -- New API: -+hb_ot_layout_lookup_get_glyph_alternates() - - -Overview of changes leading to 2.6.7 -Wednesday, June 3, 2020 -==================================== -- Update to Unicode 13.0.0. -- Fix hb_ot_layout_get_ligature_carets for fonts without lcar table, it was - completely broken for all the other fonts since 2.1.2. -- As a part of our migration to meson, this release will be the last one - to provide cmake port files but autotools still is our main build system. - There is a possibility that the next version or the after be released - using meson. - - -Overview of changes leading to 2.6.6 -Tuesday, May 12, 2020 -==================================== -- A fix in AAT kerning for Geeza Pro. -- Better support for resource fork fonts on macOS. - - -Overview of changes leading to 2.6.5 -Friday, April 17, 2020 -==================================== -- Add experimental meson build system. Autotools is still the primary - and supported build system. -- AAT is now always preferred for horizontal scripts when both AAT and OT - layout tables exist at the same time. -- Subsetter improvements. -- New API: -+hb_ft_font_lock_face() -+hb_ft_font_unlock_face() - - -Overview of changes leading to 2.6.4 -Monday, October 29, 2019 -==================================== -- Small bug fix. -- Build fixes. - - -Overview of changes leading to 2.6.3 -Monday, October 28, 2019 -==================================== -- Misc small fixes, mostly to build-related issues. -- New API: -+hb_font_get_nominal_glyphs() - - -Overview of changes leading to 2.6.2 -Monday, September 30, 2019 -==================================== -- Misc small fixes, mostly to build-related issues. - - -Overview of changes leading to 2.6.1 -Thursday, August 22, 2019 -==================================== -- Fix regression with hb_font_create_sub_font scaling introduced in 2.6.0. -- Change interpretation of font PTEM size / CoreText font size handling. - See https://github.com/harfbuzz/harfbuzz/pull/1484 -- hb-ot-font: Prefer symbol cmap subtable if present. -- Apply 'dist'/'abvm'/'blwm' features to all scripts. -- Drop experimental DirectWrite API. - - -Overview of changes leading to 2.6.0 -Tuesday, August 13, 2019 -==================================== -- New OpenType metrics, baseline, and metadata table access APIs. -- New API to set font variations to a named-instance. -- New hb-gdi.h header and API for creating hb_face_t from HFONT. -- Amalgam: Provide a single-file harfbuzz.cc file for easier alternate building. -- More size-reduction configurable options, enabled by HB_TINY. -- New API: -+hb_font_set_var_named_instance() -+hb_gdi_face_create() -+hb_ot_layout_baseline_tag_t -+hb_ot_layout_get_baseline() -+hb_ot_meta_tag_t -+hb_ot_meta_get_entry_tags() -+hb_ot_meta_reference_entry() -+hb_ot_metrics_tag_t -+hb_ot_metrics_get_position() -+hb_ot_metrics_get_variation() -+hb_ot_metrics_get_x_variation() -+hb_ot_metrics_get_y_variation() - - -Overview of changes leading to 2.5.3 -Wednesday, June 26, 2019 -==================================== -- Fix UCD script data for Unicode 10+ scripts. This was broken since 2.5.0. -- More optimizations for HB_TINY. - - -Overview of changes leading to 2.5.2 -Thursday, June 20, 2019 -==================================== -- More hb-config.hh facilities to shrink library size, namely when built as - HB_TINY. -- New documentation of custom configurations in CONFIG.md. -- Fix build on gcc 4.8. That's supported again. -- Universal Shaping Engine improvements thanks to David Corbett. -- API Changes: Undeprecate some horizontal-kerning API and re-enable in hb-ft, - such that Type1 fonts will continue kerning. - - -Overview of changes leading to 2.5.1 -Friday, May 31, 2019 -==================================== -- Fix build with various versions of Visual Studio. -- Improved documentation, thanks to Nathan Willis. -- Bugfix in subsetting glyf table. -- Improved scripts for cross-compiling for Windows using mingw. -- Rename HB_MATH_GLYPH_PART_FLAG_EXTENDER to HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER. - A deprecated macro is added for backwards-compatibility. - - -Overview of changes leading to 2.5.0 -Friday, May 24, 2019 -==================================== -- This release does not include much functional changes, but includes major internal - code-base changes. We now require C++11. Support for gcc 4.8 and earlier has been - dropped. -- New hb-config.hh facility for compiling smaller library for embedded and web usecases. -- New Unicode Character Databse implementation that is half the size of previously-used - UCDN. -- Subsetter improvements. -- Improved documentation, thanks to Nathan Willis. -- Misc shaping fixes. - - -Overview of changes leading to 2.4.0 -Monday, March 25, 2019 -==================================== -- Unicode 12. -- Misc fixes. -- Subsetter improvements. -- New API: -HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE -hb_directwrite_face_create() - - -Overview of changes leading to 2.3.1 -Wednesday, January 30, 2019 -==================================== -- AAT bug fixes. -- Misc internal housekeeping cleanup. - - -Overview of changes leading to 2.3.0 -Thursday, December 20, 2018 -==================================== -- Fix regression on big-endian architectures. Ouch! -- Misc bug and build fixes. -- Fix subsetting of simple GSUB/GDEF. -- Merge CFF / CFF2 support contributed by Adobe. This mostly involves - the subsetter, but also get_glyph_extents on CFF fonts. - -New API in hb-aat.h: -+hb_aat_layout_has_substitution() -+hb_aat_layout_has_positioning() -+hb_aat_layout_has_tracking() - - -Overview of changes leading to 2.2.0 -Thursday, November 29, 2018 -==================================== -- Misc shaping bug fixes. -- Add font variations named-instance API. -- Deprecate font variations axis enumeration API and add replacement. -- AAT shaping improvements: - o Fixed 'kern' table Format 2 implementation. - o Implement 'feat' table API for feature detection. - o Blacklist 'GSUB' table of fonts from 'MUTF' foundry that also have 'morx'. - -New API: -+hb_aat_layout_feature_type_t -+hb_aat_layout_feature_selector_t -+hb_aat_layout_get_feature_types() -+hb_aat_layout_feature_type_get_name_id -+hb_aat_layout_feature_selector_info_t -+HB_AAT_LAYOUT_NO_SELECTOR_INDEX -+hb_aat_layout_feature_type_get_selector_infos() -+hb_ot_var_axis_flags_t -+hb_ot_var_axis_info_t -+hb_ot_var_get_axis_infos() -+hb_ot_var_find_axis_info() -+hb_ot_var_get_named_instance_count() -+hb_ot_var_named_instance_get_subfamily_name_id() -+hb_ot_var_named_instance_get_postscript_name_id() -+hb_ot_var_named_instance_get_design_coords() - -Deprecated API: -+HB_OT_VAR_NO_AXIS_INDEX -+hb_ot_var_axis_t -+hb_ot_var_get_axes() -+hb_ot_var_find_axis() - - -Overview of changes leading to 2.1.3 -Friday, November 16, 2018 -==================================== -- Fix AAT 'mort' shaping, which was broken in 2.1.2 - - -Overview of changes leading to 2.1.2 -Friday, November 16, 2018 -==================================== -- Various internal changes. -- AAT shaping improvements: - o Implement kern table Format 1 state-machine-based kerning. - o Implement cross-stream kerning (cursive positioning, etc). - o Ignore emptyish GSUB tables (zero scripts) if morx present. - o Don't apply GPOS if morx is being applied. Matches Apple. - - --Overview of changes leading to 2.1.1 -Monday, November 5, 2018 -==================================== -- AAT improvements: - o Implement 'mort' table. - o Implement 'kern' subtables Format 1 and Format 3. - - -Overview of changes leading to 2.1.0 -Tuesday, October 30, 2018 -==================================== -- AAT shaping improvements: - o Allow user controlling AAT features, for whole buffer only currently. - o Several 'morx' fixes. - o Implement tuple-kerns in 'kerx'; Fixes kerning with Apple default - San Francisco fonts. -- Support for color fonts: - o COLR/CPAL API to fetch color layers. - o SVG table to fetch SVG documents. - o CBDT/sbix API to fetch PNG images. -- New 'name' table API. -- hb-ot-font now uses 'VORG' table to correctly position CFF glyphs - in vertical layout. -- Various fuzzer-found bug fixes. - -Changed API: - -A type and a macro added in 2.0.0 were renamed: - -hb_name_id_t -> hb_ot_name_id_t -HB_NAME_ID_INVALID -> HB_OT_NAME_ID_INVALID - -New API: - -+hb_color_t -+HB_COLOR -+hb_color_get_alpha() -+hb_color_get_red() -+hb_color_get_green() -+hb_color_get_blue() -+hb_ot_color_has_palettes() -+hb_ot_color_palette_get_count() -+hb_ot_color_palette_get_name_id() -+hb_ot_color_palette_color_get_name_id() -+hb_ot_color_palette_flags_t -+hb_ot_color_palette_get_flags() -+hb_ot_color_palette_get_colors() -+hb_ot_color_has_layers() -+hb_ot_color_layer_t -+hb_ot_color_glyph_get_layers() -+hb_ot_color_has_svg() -+hb_ot_color_glyph_reference_svg() -+hb_ot_color_has_png() -+hb_ot_color_glyph_reference_png() - -+hb_ot_name_id_t -+HB_OT_NAME_ID_INVALID -+HB_OT_NAME_ID_COPYRIGHT -+HB_OT_NAME_ID_FONT_FAMILY -+HB_OT_NAME_ID_FONT_SUBFAMILY -+HB_OT_NAME_ID_UNIQUE_ID -+HB_OT_NAME_ID_FULL_NAME -+HB_OT_NAME_ID_VERSION_STRING -+HB_OT_NAME_ID_POSTSCRIPT_NAME -+HB_OT_NAME_ID_TRADEMARK -+HB_OT_NAME_ID_MANUFACTURER -+HB_OT_NAME_ID_DESIGNER -+HB_OT_NAME_ID_DESCRIPTION -+HB_OT_NAME_ID_VENDOR_URL -+HB_OT_NAME_ID_DESIGNER_URL -+HB_OT_NAME_ID_LICENSE -+HB_OT_NAME_ID_LICENSE_URL -+HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY -+HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY -+HB_OT_NAME_ID_MAC_FULL_NAME -+HB_OT_NAME_ID_SAMPLE_TEXT -+HB_OT_NAME_ID_CID_FINDFONT_NAME -+HB_OT_NAME_ID_WWS_FAMILY -+HB_OT_NAME_ID_WWS_SUBFAMILY -+HB_OT_NAME_ID_LIGHT_BACKGROUND -+HB_OT_NAME_ID_DARK_BACKGROUND -+HB_OT_NAME_ID_VARIATIONS_PS_PREFIX -+hb_ot_name_entry_t -+hb_ot_name_list_names() -+hb_ot_name_get_utf8() -+hb_ot_name_get_utf16() -+hb_ot_name_get_utf32() - - -Overview of changes leading to 2.0.2 -Saturday, October 20, 2018 -==================================== -- Fix two minor memory access issues in AAT tables. - - -Overview of changes leading to 2.0.1 -Friday, October 19, 2018 -==================================== -- Fix hb-version.h reported release version that went wrong (1.8.0) - with previous release. -- Fix extrapolation in 'trak' table. -- Fix hb-font infinite-recursion issue with some font funcs and - subclassed fonts. -- Implement variation-kerning format in kerx table, although without - variation. -- Fix return value of hb_map_is_empty(). - - -Overview of changes leading to 2.0.0 -Thursday, October 18, 2018 -==================================== -- Added AAT shaping support (morx/kerx/trak). - Automatically used if GSUB/GPOS are not available respectively. - Set HB_OPTIONS=aat env var to have morx/kerx preferred over - GSUB/GPOS. -- Apply TrueType kern table internally, instead of relying on - hb_font_t callbacks. -- Khmer shaper significantly rewritten to better match Uniscribe. -- Indic3 tags ('dev3', etc) are passed to USE shaper. -- .dfont Mac font containers implemented. -- Script- and language-mapping revamped to better use BCP 47. -- Misc USE and Indic fixes. -- Misc everything fixes. -- Too many things to list. Biggest release since 0.9.1, with - over 500 commits in just over 5 weeks! Didn't intend it to - be a big release. Just happened to become. -- hb-ft now locks underlying FT_Face during use. - -API changes: - -- Newly-created hb_font_t's now have our internal "hb-ot-font" - callbacks set on them, so they should work out of the box - without any callbacks set. If callbacks are set, everything - is back to what it was before, the fallback callbacks are - null. If you to get the internal implementation modified, - sub_font it. - -- New hb_font_funcs_set_nominal_glyphs_func() allows speeding - up character to glyph mapping. - -New API: -+HB_FEATURE_GLOBAL_START -+HB_FEATURE_GLOBAL_END -+hb_buffer_set_invisible_glyph() -+hb_buffer_get_invisible_glyph() -+hb_font_funcs_set_nominal_glyphs_func() -+hb_ot_layout_table_select_script() -+hb_ot_layout_script_select_language() -+hb_ot_layout_feature_get_name_ids() -+hb_ot_layout_feature_get_characters() -+hb_name_id_t -+HB_NAME_ID_INVALID -+HB_OT_MAX_TAGS_PER_SCRIPT -+hb_ot_tags_from_script_and_language() -+hb_ot_tags_to_script_and_language() - -Deprecated API: --hb_font_funcs_set_glyph_func() --hb_unicode_eastasian_width_func_t --hb_unicode_funcs_set_eastasian_width_func() --hb_unicode_eastasian_width() --hb_unicode_decompose_compatibility_func_t --HB_UNICODE_MAX_DECOMPOSITION_LEN --hb_unicode_funcs_set_decompose_compatibility_func() --hb_unicode_decompose_compatibility() --hb_font_funcs_set_glyph_h_kerning_func() --hb_font_funcs_set_glyph_v_kerning_func() --hb_font_get_glyph_h_kerning() --hb_font_get_glyph_v_kerning() --hb_font_get_glyph_kerning_for_direction() --hb_ot_layout_table_choose_script() --hb_ot_layout_script_find_language() --hb_ot_tags_from_script() --hb_ot_tag_from_language() - - -Overview of changes leading to 1.9.0 -Monday, September 10, 2018 -==================================== -- Added 'cmap' API to hb_face_t. -- Face-builder API. -- hb-ot-font re-creation should be much leaner now, as the - font tables it uses are cached on hb_face_t now. -- Internal source header file name changes: - hb-*-private.hh is renamed to hb-*.hh. - -New API: -+HB_UNICODE_MAX -+hb_face_collect_unicodes() -+hb_face_collect_variation_selectors() -+hb_face_collect_variation_unicodes() -+hb_face_builder_create() -+hb_face_builder_add_table() - - -Overview of changes leading to 1.8.8 -Tuesday, August 14, 2018 -==================================== -- Fix hb-icu crash on architectures where compare_exchange_weak() can - fail falsely. This bug was introduced in 1.8.4. - https://bugs.chromium.org/p/chromium/issues/detail?id=873568 -- More internal refactoring of atomic operations and singletons. -- API changes: - The following functions do NOT reference their return value before - returning: - * hb_unicode_funcs_get_default() - * hb_glib_get_unicode_funcs() - * hb_icu_get_unicode_funcs() - This is consistent with their naming ("get", instead of "reference") - as well as how they are used in the wild (ie. no one calls destroy() - on their return value.) - - -Overview of changes leading to 1.8.7 -Wednesday, August 8, 2018 -==================================== -- Fix assertion failure with GDEF-blacklisted fonts. - - -Overview of changes leading to 1.8.6 -Tuesday, August 7, 2018 -==================================== -- Internal code shuffling. -- New API to speed up getting advance widths for implementations - that have heavy overhead in get_h_advance callback: -+hb_font_funcs_set_glyph_h_advances_func -+hb_font_funcs_set_glyph_v_advances_func -+hb_font_get_glyph_advances_for_direction -+hb_font_get_glyph_h_advances -+hb_font_get_glyph_h_advances_func_t -+hb_font_get_glyph_v_advances -+hb_font_get_glyph_v_advances_func_t - - -Overview of changes leading to 1.8.5 -Wednesday, August 1, 2018 -==================================== -- Major Khmer shaper improvements to better match Microsoft. -- Indic bug fixes. -- Internal improvements to atomic operations. - - -Overview of changes leading to 1.8.4 -Tuesday, July 17, 2018 -==================================== -- Fix build on non-C++11. -- Use C++-style GCC atomics and C++11 atomics. - - -Overview of changes leading to 1.8.3 -Wednesday, July 11, 2018 -==================================== -- A couple of Indic / USE bug fixes. -- Disable vectorization, as it was causing unaligned access bus error on - certain 32bit architectures. - - -Overview of changes leading to 1.8.2 -Tuesday, July 3, 2018 -==================================== -- Fix infinite loop in Khmer shaper. -- Improve hb_blob_create_from_file() for streams. - - -Overview of changes leading to 1.8.1 -Tuesday, June 12, 2018 -==================================== -- Fix hb-version.h file generation; last two releases went out with wrong ones. -- Add correctness bug in hb_set_t operations, introduced in 1.7.7. -- Remove HB_SUBSET_BUILTIN build option. Not necessary. - - -Overview of changes leading to 1.8.0 -Tuesday, June 5, 2018 -==================================== -- Update to Unicode 11.0.0. - - -Overview of changes leading to 1.7.7 -Tuesday, June 5, 2018 -==================================== -- Lots of internal changes, but not yet exposed externally. -- All HarfBuzz objects are significantly smaller in size now. -- Sinhala: Position repha on top of post-consonant, not base. - This better matches Windows 10 behavior, which was changed - from previous Windows versions. -- New build options: - o New cpp macro HB_NO_ATEXIT - o New cpp macro HB_SUBSET_BUILTIN -- Significant libharfbuzz-subset changes. API subject to change. -- New API in libharfbuzz: - -+hb_blob_create_from_file() -+hb_face_count() - -A hashmap implementation: -+hb-map.h -+HB_MAP_VALUE_INVALID -+hb_map_t -+hb_map_create() -+hb_map_get_empty() -+hb_map_reference() -+hb_map_destroy() -+hb_map_set_user_data() -+hb_map_get_user_data() -+hb_map_allocation_successful() -+hb_map_clear() -+hb_map_is_empty() -+hb_map_get_population() -+hb_map_set() -+hb_map_get() -+hb_map_del() -+hb_map_has() - - -Overview of changes leading to 1.7.6 -Wednesday, March 7, 2018 -==================================== - -- Fix to hb_set_t binary operations. Ouch. -- New experimental harfbuzz-subset library. All of hb-subset.h - is experimental right now and API WILL change. - -- New API: -hb_blob_copy_writable_or_fail() -HB_OT_TAG_BASE -hb_set_previous() -hb_set_previous_range() - - -Overview of changes leading to 1.7.5 -Tuesday, January 30, 2018 -==================================== - -- Separate Khmer shaper from Indic. -- First stab at AAT morx. Not hooked up. -- Misc bug fixes. - - -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 -==================================== - -- Always build and use UCDN for Unicode data by default. - Reduces dependence on version of Unicode data in glib, - specially in the Windows bundles we are shipping, which - have very old glib. - - -Overview of changes leading to 1.4.0 -Thursday, January 5, 2017 -==================================== - -- Merged "OpenType GX" branch which adds core of support for - OpenType 1.8 Font Variations. To that extent, the relevant - new API is: - -New API: -hb_font_set_var_coords_normalized() - - with supporting API: - -New API: -HB_OT_LAYOUT_NO_VARIATIONS_INDEX -hb_ot_layout_table_find_feature_variations() -hb_ot_layout_feature_with_variations_get_lookups() -hb_shape_plan_create2() -hb_shape_plan_create_cached2() - - Currently variations in GSUB/GPOS/GDEF are fully supported, - and no other tables are supported. In particular, fvar/avar - are NOT supported, hence the hb_font_set_var_coords_normalized() - taking normalized coordinates. API to take design coordinates - will be added in the future. - - HVAR/VVAR/MVAR support will also be added to hb-ot-font in the - future. - -- Fix regression in GDEF glyph class processing. -- Add decompositions for Chakma, Limbu, and Balinese in USE shaper. -- Misc fixes. - - -Overview of changes leading to 1.3.4 -Monday, December 5, 2016 -==================================== - -- Fix vertical glyph origin in hb-ot-font. -- Implement CBDT/CBLC color font glyph extents in hb-ot-font. - - -Overview of changes leading to 1.3.3 -Wednesday, September 28, 2016 -==================================== - -- Implement parsing of OpenType MATH table. -New API: -HB_OT_TAG_MATH -HB_OT_MATH_SCRIPT -hb_ot_math_constant_t -hb_ot_math_kern_t -hb_ot_math_glyph_variant_t -hb_ot_math_glyph_part_flags_t -hb_ot_math_glyph_part_t -hb_ot_math_has_data -hb_ot_math_get_constant -hb_ot_math_get_glyph_italics_correction -hb_ot_math_get_glyph_top_accent_attachment -hb_ot_math_get_glyph_kerning -hb_ot_math_is_glyph_extended_shape -hb_ot_math_get_glyph_variants -hb_ot_math_get_min_connector_overlap -hb_ot_math_get_glyph_assembly - - -Overview of changes leading to 1.3.2 -Wednesday, September 27, 2016 -==================================== - -- Fix build of hb-coretext on older OS X versions. - - -Overview of changes leading to 1.3.1 -Wednesday, September 7, 2016 -==================================== - -- Blacklist bad GDEF of more fonts (Padauk). -- More CoreText backend crash fixes with OS X 10.9.5. -- Misc fixes. - - -Overview of changes leading to 1.3.0 -Thursday, July 21, 2016 -==================================== - -- Update to Unicode 9.0.0 -- Move Javanese from Indic shaper to Universal Shaping Engine. -- Allow MultipleSubst to delete a glyph (matching Windows engine). -- Update Universal Shaping Engine to latest draft from Microsoft. -- DirectWrite backend improvements. Note: this backend is for testing ONLY. -- CoreText backend improvements with unreachable fonts. -- Implement symbol fonts (cmap 3.0.0) in hb-ft and hb-ot-font. -- Blacklist bad GDEF of more fonts (Tahoma & others). -- Misc fixes. - - -Overview of changes leading to 1.2.7 -Monday, May 2, 2016 -==================================== - -- Blacklist another version of Times New Roman (Bold) Italic from Windows 7. -- Fix Mongolian Free Variation Selectors shaping with certain fonts. -- Fix Tibetan shorthand contractions shaping. -- Improved list of language tag mappings. -- Unbreak build on Windows CE. -- Make 'glyf' table loading lazy in hb-ot-font. - - -Overview of changes leading to 1.2.6 -Friday, April 8, 2016 -==================================== - -- Blacklist GDEF table of another set of Times New Roman (Bold) Italic. -- DirectWrite backend improvements. Note: DirectWrite backend is - exclusively for our internal testing and should NOT be used in any - production system whatsoever. - - -Overview of changes leading to 1.2.5 -Monday, April 4, 2016 -==================================== - -- Fix GDEF mark-filtering-set, which was broken in 1.2.3. - - -Overview of changes leading to 1.2.4 -Thursday, March 17, 2016 -==================================== - -- Synthesize GDEF glyph class for any glyph that does not have one in GDEF. - I really hope we don't discover broken fonts that shape badly with this - change. -- Misc build and other minor fixes. -- API changes: - - Added HB_NDEBUG. It's fine for production systems to define this to - disable high-overhead debugging checks. However, I also reduced the - overhead of those checks, so it's a non-issue right now. You can - forget it. Just not defining anything at all is fine. - - -Overview of changes leading to 1.2.3 -Thursday, February 25, 2016 -==================================== - -- Blacklist GDEF table of certain versions of Times New Roman (Bold) Italic, - due to bug in glyph class of ASCII double-quote character. This should - address "regression" introduced in 1.2.0 when we switched mark zeroing - in most shapers from BY_UNICODE_LATE to BY_GDEF_LATE. - This fourth release in a week should finally stablize things... - -- hb-ot-font's get_glyph() implementation saw some optimizations. Though, - might be really hard to measure in real-world situations. - -- Also, two rather small API changes: - -We now disable some time-consuming internal bookkeeping if built with NDEBUG -defined. This is a first time that we use NDEBUG to disable debug code. If -there exist production systems that do NOT want to enable NDEBUG, please let -me know and I'll add HB_NDEBUG. - -Added get_nominal_glyph() and get_variation_glyph() instead of get_glyph() - -New API: -- hb_font_get_nominal_glyph_func_t -- hb_font_get_variation_glyph_func_t -- hb_font_funcs_set_nominal_glyph_func() -- hb_font_funcs_set_variation_glyph_func() -- hb_font_get_nominal_glyph() -- hb_font_get_variation_glyph() - -Deprecated API: -- hb_font_get_glyph_func_t -- hb_font_funcs_set_glyph_func() - -Clients that implement their own font-funcs are encouraged to replace -their get_glyph() implementation with a get_nominal_glyph() and -get_variation_glyph() pair. The variation version can assume that -variation_selector argument is not zero. Old (deprecated) functions -will continue working indefinitely using internal gymnastics; it is -just more efficient to use the new functions. - - -Overview of changes leading to 1.2.2 -Wednesday, February 24, 2016 -==================================== - -- Fix regression with mark positioning with fonts that have - non-zero mark advances. This was introduced in 1.2.0 while - trying to make mark and cursive attachments to work together. - I have partially reverted that, so this version is much more - like what we had before. All clients who updated to 1.2.0 - should update to this version. - - -Overview of changes leading to 1.2.1 -Tuesday, February 23, 2016 -==================================== - -- CoreText: Fix bug with wrong scale if font scale was changed later. - https://github.com/libass/libass/issues/212 -- CoreText: Drastically speed up font initialization. -- CoreText: Fix tiny leak. -- Group ZWJ/ZWNJ with previous syllable under cluster-level=0. - https://github.com/harfbuzz/harfbuzz/issues/217 -- Add test/shaping/README.md about how to add tests to the suite. - - -Overview of changes leading to 1.2.0 -Friday, February 19, 2016 -==================================== - -- Fix various issues (hangs mostly) in case of memory allocation failure. -- Change mark zeroing types of most shapers from BY_UNICODE_LATE to - BY_GDEF_LATE. This seems to be what Uniscribe does. -- Change mark zeroing of USE shaper from NONE to BY_GDEF_EARLY. That's - what Windows does. -- 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/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. -- Misc. improvements. - - -Overview of changes leading to 1.1.3 -Monday, January 11, 2016 -==================================== - -- Ported Indic shaper to Unicode 8.0 data. -- Universal Shaping Engine fixes. -- Speed up CoreText shaper when font fallback happens in CoreText. -- Documentation improvements, thanks to Khaled Hosny. -- Very rough directwrite shaper for testing, thanks to Ebrahim Byagowi. -- Misc bug fixes. -- New API: - - * Font extents: - hb_font_extents_t - hb_font_get_font_extents_func_t - hb_font_get_font_h_extents_func_t - hb_font_get_font_v_extents_func_t - hb_font_funcs_set_font_h_extents_func - hb_font_funcs_set_font_v_extents_func - hb_font_get_h_extents - hb_font_get_v_extents - hb_font_get_extents_for_direction - - * Buffer message (aka debug): - hb_buffer_message_func_t - hb_buffer_set_message_func() - Actual message protocol to be fleshed out later. - - -Overview of changes leading to 1.1.2 -Wednesday, November 26, 2015 -==================================== - -- Fix badly-broken fallback shaper that affected terminology. - 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) - implies horizontal origin at 0,0. Ie, the nil callback returns - true instead of false. As such, implementations that have a - glyph_h_origin() that simply returns true, can remove that function - with HarfBuzz >= 1.1.2. This results in a tiny speedup. - - -Overview of changes leading to 1.1.1 -Wednesday, November 24, 2015 -==================================== - -- Build fixes, specially for hb-coretext. - - -Overview of changes leading to 1.1.0 -Wednesday, November 18, 2015 -==================================== - -- Implement 'stch' stretch feature for Syriac Abbreviation Mark. - 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/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: - * Reject font tables that need more than 8 edits, - * Bound buffer growth during shaping to 32x, - * Fix assertions and other issues at OOM / buffer max-growth. -- Misc fixes and optimizations. -- API changes: - * All fonts created with hb_font_create() now inherit from - (ie. have parent) hb_font_get_empty(). - - -Overview of changes leading to 1.0.6 -Thursday, October 15, 2015 -==================================== - -- Reduce max nesting level in OT lookups from 8 to 6. - Should not affect any real font as far as I know. -- Fix memory access issue in ot-font. -- 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/harfbuzz/harfbuzz/issues/143 - - -Overview of changes leading to 1.0.5 -Tuesday, October 13, 2015 -==================================== - -- Fix multiple memory access bugs discovered using libFuzzer. - 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. -- Misc fixes. - -- New API: - * hb_font_set_parent(). - * hb_ft_font_[sg]et_load_flags() - The default flags for fonts created using hb_ft_font_create() - has changed to default to FT_LOAD_DEFAULT now. Previously it - was defaulting to FT_LOAD_DFEAULT|FT_LOAD_NO_HINTING. - -- API changes: - * Fonts now default to units-per-EM as their scale, instead of 0. - * hb_font_create_sub_font() does NOT make parent font immutable - anymore. hb_font_make_immutable() does. - - -Overview of changes leading to 1.0.4 -Wednesday, September 30, 2015 -==================================== - -- Fix minor out-of-bounds read error. - - -Overview of changes leading to 1.0.3 -Tuesday, September 1, 2015 -==================================== - -- Start of user documentation, from Simon Cozens! -- Implement glyph_extents() for TrueType fonts in hb-ot-font. -- Improve GPOS cursive attachments with conflicting lookups. -- More fixes for cluster-level = 1. -- Uniscribe positioning fix. - - -Overview of changes leading to 1.0.2 -Wednesday, August 19, 2015 -==================================== - -- Fix shaping with cluster-level > 0. -- Fix Uniscribe backend font-size scaling. -- Declare dependencies in harfbuzz.pc. - FreeType is not declared though, to avoid bugs in pkg-config - 0.26 with recursive dependencies. -- Slightly improved debug infrastructure. More to come later. -- Misc build fixes. - - -Overview of changes leading to 1.0.1 -Monday, July 27, 2015 -==================================== - -- Fix out-of-bounds access in USE shaper. - - -Overview of changes leading to 1.0.0 -Sunday, July 26, 2015 -==================================== - -- Implement Universal Shaping Engine: - https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm - http://blogs.windows.com/bloggingwindows/2015/02/23/windows-shapes-the-worlds-languages/ -- Bump version to 1.0.0. The soname was NOT bumped. - - -Overview of changes leading to 0.9.42 -Thursday, July 26, 2015 -===================================== - -- New API to allow for retrieving finer-grained cluster - mappings if the client desires to handle them. Default - behavior is unchanged. -- Fix cluster merging when removing default-ignorables. -- Update to Unicode 8.0 -- hb-graphite2 fixes. -- Misc fixes. -- Removed HB_NO_MERGE_CLUSTERS hack. -- New API: - hb_buffer_cluster_level_t enum - hb_buffer_get_cluster_level() - hb_buffer_set_cluster_level() - hb-shape / hb-view --cluster-level - - -Overview of changes leading to 0.9.41 -Thursday, June 18, 2015 -===================================== - -- Fix hb-coretext with trailing whitespace in right-to-left. -- New API: hb_buffer_reverse_range(). -- Allow implementing atomic ops in config.h. -- Fix hb_language_t in language bindings. -- Misc fixes. - - -Overview of changes leading to 0.9.40 -Friday, March 20, 2015 -===================================== - -- Another hb-coretext crasher fix. Ouch! -- Happy Norouz! - - -Overview of changes leading to 0.9.39 -Wednesday, March 4, 2015 -===================================== - -- Critical hb-coretext fixes. -- Optimizations and refactoring; no functional change - expected. -- Misc build fixes. - - -Overview of changes leading to 0.9.38 -Friday, January 23, 2015 -===================================== - -- Fix minor out-of-bounds access in Indic shaper. -- Change New Tai Lue shaping engine from South-East Asian to default, - reflecting change in Unicode encoding model. -- Add hb-shape --font-size. Can take up to two numbers for separate - x / y size. -- Fix CoreText and FreeType scale issues with negative scales. -- Reject blobs larger than 2GB. This might break some icu-le-hb clients - that need security fixes. See: - http://www.icu-project.org/trac/ticket/11450 -- Avoid accessing font tables during face destruction, in casce rogue - clients released face data already. -- Fix up gobject-introspection a bit. Python bindings kinda working. - See README.python. -- Misc fixes. -- API additions: - hb_ft_face_create_referenced() - hb_ft_font_create_referenced() - - -Overview of changes leading to 0.9.37 -Wednesday, December 17, 2014 -===================================== - -- Fix out-of-bounds access in Context lookup format 3. -- Indic: Allow ZWJ/ZWNJ before syllable modifiers. - - -Overview of changes leading to 0.9.36 -Thursday, November 20, 2014 -===================================== - -- First time that three months went by without a release since - 0.9.2 was released on August 10, 2012! -- Fix performance bug in hb_ot_collect_glyphs(): - https://bugzilla.mozilla.org/show_bug.cgi?id=1090869 -- Add basic vertical-text support to hb-ot-font. -- Misc build fixes. - - -Overview of changes leading to 0.9.35 -Saturday, August 13, 2014 -===================================== - -- Fix major shape-plan caching bug when more than one shaper were - provided to hb_shape_full() (as exercised by XeTeX). - http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1246370.html -- Fix Arabic fallback shaping regression. This was broken in 0.9.32. -- Major hb-coretext fixes. That backend is complete now, including - respecing buffer direction and language, down to vertical writing. -- Build fixes for Windows CE. Should build fine now. -- Misc fixes: - Use atexit() only if it's safe to call from shared library - https://bugs.freedesktop.org/show_bug.cgi?id=82246 - Mandaic had errors in its Unicode Joining_Type - https://bugs.freedesktop.org/show_bug.cgi?id=82306 -- API changes: - - * hb_buffer_clear_contents() does not reset buffer flags now. - - After 763e5466c0a03a7c27020e1e2598e488612529a7, one doesn't - need to set flags for different pieces of text. The flags now - are something the client sets up once, depending on how it - actually uses the buffer. As such, don't clear it in - clear_contents(). - - I don't expect any changes to be needed to any existing client. - - -Overview of changes leading to 0.9.34 -Saturday, August 2, 2014 -===================================== - -- hb_feature_from_string() now accepts CSS font-feature-settings format. -- As a result, hb-shape / hb-view --features also accept CSS-style strings. - Eg, "'liga' off" is accepted now. -- Add old-spec Myanmar shaper: - https://bugs.freedesktop.org/show_bug.cgi?id=81775 -- Don't apply 'calt' in Hangul shaper. -- Fix mark advance zeroing for Hebrew shaper: - https://bugs.freedesktop.org/show_bug.cgi?id=76767 -- Implement Windows-1256 custom Arabic shaping. Only built on Windows, - and requires help from get_glyph(). Used by Firefox. - https://bugzilla.mozilla.org/show_bug.cgi?id=1045139 -- Disable 'liga' in vertical text. -- Build fixes. -- API changes: - - * Make HB_BUFFER_FLAG_BOT/EOT easier to use. - - Previously, we expected users to provide BOT/EOT flags when the - text *segment* was at paragraph boundaries. This meant that for - clients that provide full paragraph to HarfBuzz (eg. Pango), they - had code like this: - - hb_buffer_set_flags (hb_buffer, - (item_offset == 0 ? HB_BUFFER_FLAG_BOT : 0) | - (item_offset + item_length == paragraph_length ? - HB_BUFFER_FLAG_EOT : 0)); - - hb_buffer_add_utf8 (hb_buffer, - paragraph_text, paragraph_length, - item_offset, item_length); - - After this change such clients can simply say: - - hb_buffer_set_flags (hb_buffer, - HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT); - - hb_buffer_add_utf8 (hb_buffer, - paragraph_text, paragraph_length, - item_offset, item_length); - - Ie, HarfBuzz itself checks whether the segment is at the beginning/end - of the paragraph. Clients that only pass item-at-a-time to HarfBuzz - continue not setting any flags whatsoever. - - Another way to put it is: if there's pre-context text in the buffer, - HarfBuzz ignores the BOT flag. If there's post-context, it ignores - EOT flag. - - -Overview of changes leading to 0.9.33 -Tuesday, July 22, 2014 -===================================== - -- Turn off ARabic 'cswh' feature that was accidentally turned on. -- Add HB_TAG_MAX_SIGNED. -- Make hb_face_make_immutable() really make face immutable! -- Windows build fixes. - - -Overview of changes leading to 0.9.32 -Thursday, July 17, 2014 -===================================== - -- Apply Arabic shaping features in spec order exactly. -- Another fix for Mongolian free variation selectors. -- For non-Arabic scripts in Arabic shaper apply 'rlig' and 'calt' - together. -- Minor adjustment to U+FFFD logic. -- Fix hb-coretext build. - - -Overview of changes leading to 0.9.31 -Wednesday, July 16, 2014 -===================================== - -- Only accept valid UTF-8/16/32; we missed many cases before. -- Better shaping of invalid UTF-8/16/32. Falls back to - 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 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() - now uses these instead of private tags. -- Build fixes. -- New API: - * hb_buffer_add_codepoints(). This does what hb_buffer_add_utf32() - used to do, ie. no validity check on the input at all. add_utf32 - now replaces invalid Unicode codepoints with the replacement - character (see below). - * hb_buffer_set_replacement_codepoint() - * hb_buffer_get_replacement_codepoint() - Previously, in hb_buffer_add_utf8 and hb_buffer_add_utf16, when - we detected broken input, we replaced that with (hb_codepoint_t)-1. - This has changed to use U+FFFD now, but can be changed using these - new API. - - -Overview of changes leading to 0.9.30 -Wednesday, July 9, 2014 -===================================== - -- Update to Unicode 7.0.0: - * New scripts Manichaean and Psalter Pahlavi are shaped using - Arabic shaper. - * All the other new scripts to through the generic shaper for - now. -- Minor Indic improvements. -- Fix graphite2 backend cluster mapping [crasher!] -- API changes: - * New HB_SCRIPT_* values for Unicode 7.0 scripts. - * New function hb_ot_layout_language_get_required_feature(). -- Build fixes. - - -Overview of changes leading to 0.9.29 -Thursday, May 29, 2014 -===================================== - -- Implement cmap in hb-ot-font.h. No variation-selectors yet. -- Myanmar: Allow MedialYa+Asat. -- Various Indic fixes: - * Support most characters in Extended Devanagary and Vedic - Unicode blocks. - * Allow digits and a some punctuation as consonant placeholders. -- Build fixes. - - -Overview of changes leading to 0.9.28 -Monday, April 28, 2014 -===================================== - -- Unbreak old-spec Indic shaping. (bug 76705) -- Fix shaping of U+17DD and U+0FC6. -- Add HB_NO_MERGE_CLUSTERS build option. NOT to be enabled by default - for shipping libraries. It's an option for further experimentation - right now. When we are sure how to do it properly, we will add - public run-time API for the functionality. -- Build fixes. - - -Overview of changes leading to 0.9.27 -Tuesday, March 18, 2014 -===================================== - -- Don't use "register" storage class specifier -- Wrap definition of free_langs() with HAVE_ATEXIT -- Add coretext_aat shaper and hb_coretext_face_create() constructor -- If HAVE_ICU_BUILTIN is defined, use hb-icu Unicode callbacks -- Add Myanmar test case from OpenType Myanmar spec -- Only do fallback Hebrew composition if no GPOS 'mark' available -- Allow bootstrapping without gtk-doc -- Use AM_MISSING_PROG for ragel and git -- Typo in ucdn's Makefile.am -- Improve MemoryBarrier() implementation - - -Overview of changes leading to 0.9.26 -Thursday, January 30, 2014 -===================================== - -- Misc fixes. -- Fix application of 'rtlm' feature. -- Automatically apply frac/numr/dnom around U+2044 FRACTION SLASH. -- New header: hb-ot-shape.h -- Uniscribe: fix scratch-buffer accounting. -- Reorder Tai Tham SAKOT to after tone-marks. -- Add Hangul shaper. -- New files: - hb-ot-shape-complex-hangul.cc - hb-ot-shape-complex-hebrew.cc - hb-ot-shape-complex-tibetan.cc -- Disable 'cswh' feature in Arabic shaper. -- Coretext: better handle surrogate pairs. -- Add HB_TAG_MAX and _HB_SCRIPT_MAX_VALUE. - - -Overview of changes leading to 0.9.25 -Wednesday, December 4, 2013 -===================================== - -- Myanmar shaper improvements. -- Avoid font fallback in CoreText backend. -- Additional OpenType language tag mappiongs. -- More aggressive shape-plan caching. -- Build with / require automake 1.13. -- Build with libtool 2.4.2.418 alpha to support ppc64le. - - -Overview of changes leading to 0.9.24 -Tuesday, November 13, 2013 -===================================== - -- Misc compiler warning fixes with clang. -- No functional changes. - - -Overview of changes leading to 0.9.23 -Monday, October 28, 2013 -===================================== - -- "Udupi HarfBuzz Hackfest", Paris, October 14..18 2013. -- Fix (Chain)Context recursion with non-monotone lookup positions. -- Misc Indic bug fixes. -- New Javanese / Buginese shaping, similar to Windows 8.1. - - -Overview of changes leading to 0.9.22 -Thursday, October 3, 2013 -===================================== - -- Fix use-after-end-of-scope in hb_language_from_string(). -- Fix hiding of default_ignorables if font doesn't have space glyph. -- Protect against out-of-range lookup indices. - -- API Changes: - - * Added hb_ot_layout_table_get_lookup_count() - - -Overview of changes leading to 0.9.21 -Monday, September 16, 2013 -===================================== - -- Rename gobject-introspection library name from harfbuzz to HarfBuzz. -- Remove (long disabled) hb-old and hb-icu-le test shapers. -- Misc gtk-doc and gobject-introspection annotations. -- Misc fixes. -- API changes: - - * Add HB_SET_VALUE_INVALID - -Overview of changes leading to 0.9.20 -Thursday, August 29, 2013 -===================================== - -General: -- Misc substitute_closure() fixes. -- Build fixes. - -Documentation: -- gtk-doc boilerplate integrated. Docs are built now, but - contain no contents. By next release hopefully we have - some content in. Enable using --enable-gtk-doc. - -GObject and Introspection: -- Added harfbuzz-gobject library (hb-gobject.h) that has type - bindings for all HarfBuzz objects and enums. Enable using - --with-gobject. -- Added gobject-introspection boilerplate. Nothing useful - right now. Work in progress. Gets enabled automatically if - --with-gobject is used. Override with --disable-introspection. - -OpenType shaper: -- Apply 'mark' in Myanmar shaper. -- Don't apply 'dlig' by default. - -Uniscribe shaper: -- Support user features. -- Fix loading of fonts that are also installed on the system. -- Fix shaping of Arabic Presentation Forms. -- Fix build with wide chars. - -CoreText shaper: -- Support user features. - -Source changes: -- hb_face_t code moved to hb-face.h / hb-face.cc. -- Added hb-deprecated.h. - -API changes: -- Added HB_DISABLE_DEPRECATED. -- Deprecated HB_SCRIPT_CANADIAN_ABORIGINAL; replaced by - HB_SCRIPT_CANADIAN_SYLLABICS. -- Deprecated HB_BUFFER_FLAGS_DEFAULT; replaced by - HB_BUFFER_FLAG_DEFAULT. -- Deprecated HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; replaced by - HB_BUFFER_SERIALIZE_FLAG_DEFAULT. - - -Overview of changes leading to 0.9.19 -Tuesday, July 16, 2013 -===================================== - -- Build fixes. -- Better handling of multiple variation selectors in a row. -- Pass on variation selector to GSUB if not consumed by cmap. -- Fix undefined memory access. -- Add Javanese config to Indic shaper. -- Misc bug fixes. - -Overview of changes leading to 0.9.18 -Tuesday, May 28, 2013 -===================================== - -New build system: - -- All unneeded code is all disabled by default, - -- Uniscribe and CoreText shapers can be enabled with their --with options, - -- icu_le and old shapers cannot be enabled for now, - -- glib, freetype, and cairo will be detected automatically. - They can be force on/off'ed with their --with options, - -- icu and graphite2 are default off, can be enabled with their --with - options, - -Moreover, ICU support is now build into a separate library: -libharfbuzz-icu.so, and a new harfbuzz-icu.pc is shipped for it. -Distros can enable ICU now without every application on earth -getting linked to via libharfbuzz.so. - -For distros I recommend that they make sure they are building --with-glib ---with-freetype --with-cairo, --with-icu, and optionally --with-graphite2; -And package harfbuzz and harfbuzz-icu separately. - - -Overview of changes leading to 0.9.17 -Monday, May 20, 2013 -===================================== - -- Build fixes. -- Fix bug in hb_set_get_min(). -- Fix regression with Arabic mark positioning / width-zeroing. - -Overview of changes leading to 0.9.16 -Friday, April 19, 2013 -===================================== - -- Major speedup in OpenType lookup processing. With the Amiri - Arabic font, this release is over 3x faster than previous - release. All scripts / languages should see this speedup. - -- New --num-iterations option for hb-shape / hb-view; useful for - profiling. - -Overview of changes leading to 0.9.15 -Friday, April 05, 2013 -===================================== - -- Build fixes. -- Fix crasher in graphite2 shaper. -- Fix Arabic mark width zeroing regression. -- Don't compose Hangul jamo into Unicode syllables. - - -Overview of changes leading to 0.9.14 -Thursday, March 21, 2013 -===================================== - -- Build fixes. -- Fix time-consuming sanitize with malicious fonts. -- Implement hb_buffer_deserialize_glyphs() for both json and text. -- Do not ignore Hangul filler characters. -- Indic fixes: - * Fix Malayalam pre-base reordering interaction with post-forms. - * Further adjust ZWJ handling. Should fix known regressions from - 0.9.13. - - -Overview of changes leading to 0.9.13 -Thursday, February 25, 2013 -===================================== - -- Build fixes. -- Ngapi HarfBuzz Hackfest in London (February 2013): - * Fixed all known Indic bugs, - * New Win8-style Myanmar shaper, - * New South-East Asian shaper for Tai Tham, Cham, and New Tai Lue, - * Smartly ignore Default_Ignorable characters (joiners, etc) wheb - matching GSUB/GPOS lookups, - * Fix 'Phags-Pa U+A872 shaping, - * Fix partial disabling of default-on features, - * Allow disabling of TrueType kerning. -- Fix possible crasher with broken fonts with overlapping tables. -- Removed generated files from git again. So, one needs ragel to - bootstrap from the git tree. - -API changes: -- hb_shape() and related APIs now abort if buffer direction is - HB_DIRECTION_INVALID. Previously, hb_shape() was calling - hb_buffer_guess_segment_properties() on the buffer before - shaping. The heuristics in that function are fragile. If the - user really wants the old behvaior, they can call that function - right before calling hb_shape() to get the old behavior. -- hb_blob_create_sub_blob() always creates sub-blob with - HB_MEMORY_MODE_READONLY. See comments for the reason. - - -Overview of changes leading to 0.9.12 -Thursday, January 18, 2013 -===================================== - -- Build fixes for Sun compiler. -- Minor bug fix. - -Overview of changes leading to 0.9.11 -Thursday, January 10, 2013 -===================================== - -- Build fixes. -- Fix GPOS mark attachment with null Anchor offsets. -- [Indic] Fix old-spec reordering of viramas if sequence ends in one. -- Fix multi-threaded shaper data creation crash. -- Add atomic ops for Solaris. - -API changes: -- Rename hb_buffer_clear() to hb_buffer_clear_contents(). - - -Overview of changes leading to 0.9.10 -Thursday, January 3, 2013 -===================================== - -- [Indic] Fixed rendering of Malayalam dot-reph -- Updated OT language tags. -- Updated graphite2 backend. -- Improved hb_ot_layout_get_size_params() logic. -- Improve hb-shape/hb-view help output. -- Fixed hb-set.h implementation to not crash. -- Fixed various issues with hb_ot_layout_collect_lookups(). -- Various build fixes. - -New API: - -hb_graphite2_face_get_gr_face() -hb_graphite2_font_get_gr_font() -hb_coretext_face_get_cg_font() - -Modified API: - -hb_ot_layout_get_size_params() - - -Overview of changes leading to 0.9.9 -Wednesday, December 5, 2012 -==================================== - -- Fix build on Windows. -- Minor improvements. - - -Overview of changes leading to 0.9.8 -Tuesday, December 4, 2012 -==================================== - - -- Actually implement hb_shape_plan_get_shaper (). -- Make UCDB data tables const. -- Lots of internal refactoring in OTLayout tables. -- Flesh out hb_ot_layout_lookup_collect_glyphs(). - -New API: - -hb_ot_layout_collect_lookups() -hb_ot_layout_get_size_params() - - -Overview of changes leading to 0.9.7 -Sunday, November 21, 2012 -==================================== - - -HarfBuzz "All-You-Can-Eat-Sushi" (aka Vancouver) Hackfest and follow-on fixes. - -- Fix Arabic contextual joining using pre-context text. -- Fix Sinhala "split matra" mess. -- Fix Khmer shaping with broken fonts. -- Implement Thai "PUA" shaping for old fonts. -- Do NOT route Kharoshthi script through the Indic shaper. -- Disable fallback positioning for Indic and Thai shapers. -- Misc fixes. - - -hb-shape / hb-view changes: - -- Add --text-before and --text-after -- Add --bot / --eot / --preserve-default-ignorables -- hb-shape --output-format=json - - -New API: - -hb_buffer_clear() - -hb_buffer_flags_t - -HB_BUFFER_FLAGS_DEFAULT -HB_BUFFER_FLAG_BOT -HB_BUFFER_FLAG_EOT -HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES - -hb_buffer_set_flags() -hb_buffer_get_flags() - -HB_BUFFER_SERIALIZE_FLAGS -hb_buffer_serialize_glyphs() -hb_buffer_deserialize_glyphs() -hb_buffer_serialize_list_formats() - -hb_set_add_range() -hb_set_del_range() -hb_set_get_population() -hb_set_next_range() - -hb_face_[sg]et_glyph_count() - -hb_segment_properties_t -HB_SEGMENT_PROPERTIES_DEFAULT -hb_segment_properties_equal() -hb_segment_properties_hash() - -hb_buffer_set_segment_properties() -hb_buffer_get_segment_properties() - -hb_ot_layout_glyph_class_t -hb_ot_layout_get_glyph_class() -hb_ot_layout_get_glyphs_in_class() - -hb_shape_plan_t -hb_shape_plan_create() -hb_shape_plan_create_cached() -hb_shape_plan_get_empty() -hb_shape_plan_reference() -hb_shape_plan_destroy() -hb_shape_plan_set_user_data() -hb_shape_plan_get_user_data() -hb_shape_plan_execute() -hb_shape_plan_get_shaper() - -hb_ot_shape_plan_collect_lookups() - - -API changes: - -- Remove "mask" parameter from hb_buffer_add(). -- Rename hb_ot_layout_would_substitute_lookup() and hb_ot_layout_substitute_closure_lookup(). -- hb-set.h API const correction. -- Renamed hb_set_min/max() to hb_set_get_min/max(). -- Rename hb_ot_layout_feature_get_lookup_indexes() to hb_ot_layout_feature_get_lookups(). -- Rename hb_buffer_guess_properties() to hb_buffer_guess_segment_properties(). - - - -Overview of changes leading to 0.9.6 -Sunday, November 13, 2012 -==================================== - -- Don't clear pre-context text if no new context is provided. -- Fix ReverseChainingSubstLookup, which was totally borked. -- Adjust output format of hb-shape a bit. -- Include config.h.in in-tree. Makes it easier for alternate build systems. -- Fix hb_buffer_set_length(buffer, 0) invalid memory allocation. -- Use ICU LayoutEngine's C API instead of C++. Avoids much headache. -- Drop glyphs for all of Unicode Default_Ignorable characters. -- Misc build fixes. - -Arabic shaper: -- Enable 'dlig' and 'mset' features in Arabic shaper. -- Implement 'Phags-pa shaping, improve Mongolian. - -Indic shaper: -- Decompose Sinhala split matras the way old HarfBuzz / Pango did. -- Initial support for Consonant Medials. -- Start adding new-style Myanmar shaping. -- Make reph and 'pref' logic introspect the font. -- Route Meetei-Mayek through the Indic shaper. -- Don't apply 'liga' in Indic shaper. -- Improve Malayalam pre-base reordering Ra interaction with Chillus. - - - -Overview of changes leading to 0.9.5 -Sunday, October 14, 2012 -==================================== - -- Synthetic-GSUB Arabic fallback shaping. - -- Misc Indic improvements. - -- Add build system support for pthread. - -- Imported UCDN for in-tree Unicode callbacks implementation. - -- Context-aware Arabic joining. - -- Misc other fixes. - -- New API: - - hb_feature_to/from-string() - hb_buffer_[sg]et_content_type() - - - -Overview of changes leading to 0.9.4 -Tuesday, Sep 03, 2012 -==================================== - -- Indic improvements with old-spec Malayalam. - -- Better fallback glyph positioning, specially with Thai / Lao marks. - -- Implement dotted-circle insertion. - -- Better Arabic fallback shaping / ligation. - -- Added ICU LayoutEngine backend for testing. Call it by the 'icu_le' name. - -- Misc fixes. - - - -Overview of changes leading to 0.9.3 -Friday, Aug 18, 2012 -==================================== - -- Fixed fallback mark positioning for left-to-right text. - -- Improve mark positioning for the remaining combining classes. - -- Unbreak Thai and fallback Arabic shaping. - -- Port Arabic shaper to shape-plan caching. - -- Use new ICU normalizer functions. - - - -Overview of changes leading to 0.9.2 -Friday, Aug 10, 2012 -==================================== - -- Over a thousand commits! This is the first major release of HarfBuzz. - -- HarfBuzz is feature-complete now! It should be in par, or better, than - both Pango's shapers and old HarfBuzz / Qt shapers. - -- New Indic shaper, supporting main Indic scripts, Sinhala, and Khmer. - -- Improved Arabic shaper, with fallback Arabic shaping, supporting Arabic, - Sinhala, N'ko, Mongolian, and Mandaic. - -- New Thai / Lao shaper. - -- Tibetan / Hangul support in the generic shaper. - -- Synthetic GDEF support for fonts without a GDEF table. - -- Fallback mark positioning for fonts without a GPOS table. - -- Unicode normalization shaping heuristic during glyph mapping. - -- New experimental Graphite2 backend. - -- New Uniscribe backend (primarily for testing). - -- New CoreText backend (primarily for testing). - -- Major optimization and speedup. - -- Test suites and testing infrastructure (work in progress). - -- Greatly improved hb-view cmdline tool. - -- hb-shape cmdline tool. - -- Unicode 6.1 support. - -Summary of API changes: - -o Changed API: - - - Users are expected to only include main header files now (ie. hb.h, - hb-glib.h, hb-ft.h, ...) - - - All struct tag names had their initial underscore removed. - Ie. "struct _hb_buffer_t" is "struct hb_buffer_t" now. - - - All set_user_data() functions now take a "replace" boolean parameter. - - - hb_buffer_create() takes zero arguments now. - Use hb_buffer_pre_allocate() to pre-allocate. - - - hb_buffer_add_utf*() now accept -1 for length parameteres, - meaning "nul-terminated". - - - hb_direction_t enum values changed. - - - All *_from_string() APIs now take a length parameter to allow for - non-nul-terminated strings. A -1 length means "nul-terminated". - - - Typedef for hb_language_t changed. - - - hb_get_table_func_t renamed to hb_reference_table_func_t. - - - hb_ot_layout_table_choose_script() - - - Various renames in hb-unicode.h. - -o New API: - - - hb_buffer_guess_properties() - Automatically called by hb_shape(). - - - hb_buffer_normalize_glyphs() - - - hb_tag_from_string() - - - hb-coretext.h - - - hb-uniscribe.h - - - hb_face_reference_blob() - - hb_face_[sg]et_index() - - hb_face_set_upem() - - - hb_font_get_glyph_name_func_t - hb_font_get_glyph_from_name_func_t - hb_font_funcs_set_glyph_name_func() - hb_font_funcs_set_glyph_from_name_func() - hb_font_get_glyph_name() - hb_font_get_glyph_from_name() - hb_font_glyph_to_string() - hb_font_glyph_from_string() - - - hb_font_set_funcs_data() - - - hb_ft_font_set_funcs() - - hb_ft_font_get_face() - - - hb-gobject.h (work in progress) - - - hb_ot_shape_glyphs_closure() - hb_ot_layout_substitute_closure_lookup() - - - hb-set.h - - - hb_shape_full() - - - hb_unicode_combining_class_t - - - hb_unicode_compose_func_t - hb_unicode_decompose_func_t - hb_unicode_decompose_compatibility_func_t - hb_unicode_funcs_set_compose_func() - hb_unicode_funcs_set_decompose_func() - hb_unicode_funcs_set_decompose_compatibility_func() - hb_unicode_compose() - hb_unicode_decompose() - hb_unicode_decompose_compatibility() - -o Removed API: - - - hb_ft_get_font_funcs() - - - hb_ot_layout_substitute_start() - hb_ot_layout_substitute_lookup() - hb_ot_layout_substitute_finish() - hb_ot_layout_position_start() - hb_ot_layout_position_lookup() - hb_ot_layout_position_finish() - - - -Overview of changes leading to 0.6.0 -Friday, May 27, 2011 -==================================== - -- Vertical text support in GPOS -- Almost all API entries have unit tests now, under test/ -- All thread-safety issues are fixed - -Summary of API changes follows. - - -* Simple Types API: - - o New API: - HB_LANGUAGE_INVALID - hb_language_get_default() - hb_direction_to_string() - hb_direction_from_string() - hb_script_get_horizontal_direction() - HB_UNTAG() - - o Renamed API: - hb_category_t renamed to hb_unicode_general_category_t - - o Changed API: - hb_language_t is a typed pointers now - - o Removed API: - HB_TAG_STR() - - -* Use ISO 15924 tags for hb_script_t: - - o New API: - hb_script_from_iso15924_tag() - hb_script_to_iso15924_tag() - hb_script_from_string() - - o Changed API: - HB_SCRIPT_* enum members changed value. - - -* Buffer API streamlined: - - o New API: - hb_buffer_reset() - hb_buffer_set_length() - hb_buffer_allocation_successful() - - o Renamed API: - hb_buffer_ensure() renamed to hb_buffer_pre_allocate() - hb_buffer_add_glyph() renamed to hb_buffer_add() - - o Removed API: - hb_buffer_clear() - hb_buffer_clear_positions() - - o Changed API: - hb_buffer_get_glyph_infos() takes an out length parameter now - hb_buffer_get_glyph_positions() takes an out length parameter now - - -* Blob API streamlined: - - o New API: - hb_blob_get_data() - hb_blob_get_data_writable() - - o Renamed API: - hb_blob_create_empty() renamed to hb_blob_get_empty() - - o Removed API: - hb_blob_lock() - hb_blob_unlock() - hb_blob_is_writable() - hb_blob_try_writable() - - o Changed API: - hb_blob_create() takes user_data before destroy now - - -* Unicode functions API: - - o Unicode function vectors can subclass other unicode function vectors now. - Unimplemented callbacks in the subclass automatically chainup to the parent. - - o All hb_unicode_funcs_t callbacks take a user_data now. Their setters - take a user_data and its respective destroy callback. - - o New API: - hb_unicode_funcs_get_empty() - hb_unicode_funcs_get_default() - hb_unicode_funcs_get_parent() - - o Changed API: - hb_unicode_funcs_create() now takes a parent_funcs. - - o Removed func getter functions: - hb_unicode_funcs_get_mirroring_func() - hb_unicode_funcs_get_general_category_func() - hb_unicode_funcs_get_script_func() - hb_unicode_funcs_get_combining_class_func() - hb_unicode_funcs_get_eastasian_width_func() - - -* Face API: - - o Renamed API: - hb_face_get_table() renamed to hb_face_reference_table() - hb_face_create_for_data() renamed to hb_face_create() - - o Changed API: - hb_face_create_for_tables() takes user_data before destroy now - hb_face_reference_table() returns empty blob instead of NULL - hb_get_table_func_t accepts the face as first parameter now - -* Font API: - - o Fonts can subclass other fonts now. Unimplemented callbacks in the - subclass automatically chainup to the parent. When chaining up, - scale is adjusted if the parent font has a different scale. - - o All hb_font_funcs_t callbacks take a user_data now. Their setters - take a user_data and its respective destroy callback. - - o New API: - hb_font_get_parent() - hb_font_funcs_get_empty() - hb_font_create_sub_font() - - o Removed API: - hb_font_funcs_copy() - hb_font_unset_funcs() - - o Removed func getter functions: - hb_font_funcs_get_glyph_func() - hb_font_funcs_get_glyph_advance_func() - hb_font_funcs_get_glyph_extents_func() - hb_font_funcs_get_contour_point_func() - hb_font_funcs_get_kerning_func() - - o Changed API: - hb_font_create() takes a face and references it now - hb_font_set_funcs() takes user_data before destroy now - hb_font_set_scale() accepts signed integers now - hb_font_get_contour_point_func_t now takes glyph first, then point_index - hb_font_get_glyph_func_t returns a success boolean now - - -* Changed object model: - - o All object types have a _get_empty() now: - hb_blob_get_empty() - hb_buffer_get_empty() - hb_face_get_empty() - hb_font_get_empty() - hb_font_funcs_get_empty() - hb_unicode_funcs_get_empty() - - o Added _set_user_data() and _get_user_data() for all object types: - hb_blob_get_user_data() - hb_blob_set_user_data() - hb_buffer_get_user_data() - hb_buffer_set_user_data() - hb_face_get_user_data() - hb_face_set_user_data() - hb_font_funcs_get_user_data() - hb_font_funcs_set_user_data() - hb_font_get_user_data() - hb_font_set_user_data() - hb_unicode_funcs_get_user_data() - hb_unicode_funcs_set_user_data() - - o Removed the _get_reference_count() from all object types: - hb_blob_get_reference_count() - hb_buffer_get_reference_count() - hb_face_get_reference_count() - hb_font_funcs_get_reference_count() - hb_font_get_reference_count() - hb_unicode_funcs_get_reference_count() - - o Added _make_immutable() and _is_immutable() for all object types except for buffer: - hb_blob_make_immutable() - hb_blob_is_immutable() - hb_face_make_immutable() - hb_face_is_immutable() - - -* Changed API for vertical text support - - o The following callbacks where removed: - hb_font_get_glyph_advance_func_t - hb_font_get_kerning_func_t - - o The following new callbacks added instead: - hb_font_get_glyph_h_advance_func_t - hb_font_get_glyph_v_advance_func_t - hb_font_get_glyph_h_origin_func_t - hb_font_get_glyph_v_origin_func_t - hb_font_get_glyph_h_kerning_func_t - hb_font_get_glyph_v_kerning_func_t - - o The following API removed as such: - hb_font_funcs_set_glyph_advance_func() - hb_font_funcs_set_kerning_func() - hb_font_get_glyph_advance() - hb_font_get_kerning() - - o New API added instead: - hb_font_funcs_set_glyph_h_advance_func() - hb_font_funcs_set_glyph_v_advance_func() - hb_font_funcs_set_glyph_h_origin_func() - hb_font_funcs_set_glyph_v_origin_func() - hb_font_funcs_set_glyph_h_kerning_func() - hb_font_funcs_set_glyph_v_kerning_func() - hb_font_get_glyph_h_advance() - hb_font_get_glyph_v_advance() - hb_font_get_glyph_h_origin() - hb_font_get_glyph_v_origin() - hb_font_get_glyph_h_kerning() - hb_font_get_glyph_v_kerning() - - o The following higher-leve API added for convenience: - hb_font_get_glyph_advance_for_direction() - hb_font_get_glyph_origin_for_direction() - hb_font_add_glyph_origin_for_direction() - hb_font_subtract_glyph_origin_for_direction() - hb_font_get_glyph_kerning_for_direction() - hb_font_get_glyph_extents_for_origin() - hb_font_get_glyph_contour_point_for_origin() - - -* OpenType Layout API: - - o New API: - hb_ot_layout_position_start() - hb_ot_layout_substitute_start() - hb_ot_layout_substitute_finish() - - -* Glue code: - - o New API: - hb_glib_script_to_script() - hb_glib_script_from_script() - hb_icu_script_to_script() - hb_icu_script_from_script() - - -* Version API added: - - o New API: - HB_VERSION_MAJOR - HB_VERSION_MINOR - HB_VERSION_MICRO - HB_VERSION_STRING - HB_VERSION_CHECK() - hb_version() - hb_version_string() - hb_version_check() - - diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-ankr-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-ankr-table.hh index f2785a6f58..63fac84524 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-ankr-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-ankr-table.hh @@ -54,7 +54,7 @@ struct Anchor DEFINE_SIZE_STATIC (4); }; -typedef LArrayOf GlyphAnchors; +typedef Array32Of GlyphAnchors; struct ankr { @@ -64,7 +64,7 @@ struct ankr unsigned int i, unsigned int num_glyphs) const { - const NNOffsetTo *offset = (this+lookupTable).get_value (glyph_id, num_glyphs); + const NNOffset16To *offset = (this+lookupTable).get_value (glyph_id, num_glyphs); if (!offset) return Null (Anchor); const GlyphAnchors &anchors = &(this+anchorData) + *offset; @@ -83,9 +83,9 @@ struct ankr protected: HBUINT16 version; /* Version number (set to zero) */ HBUINT16 flags; /* Flags (currently unused; set to zero) */ - LOffsetTo>> + Offset32To>> lookupTable; /* Offset to the table's lookup table */ - LNNOffsetTo + NNOffset32To anchorData; /* Offset to the glyph data table */ public: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh index 98ed20d8eb..e70ce97174 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh @@ -30,6 +30,9 @@ #include "hb-aat-layout.hh" #include "hb-open-type.hh" +namespace OT { +struct GDEF; +}; namespace AAT { @@ -164,7 +167,7 @@ struct LookupSegmentArray HBGlyphID last; /* Last GlyphID in this segment */ HBGlyphID first; /* First GlyphID in this segment */ - NNOffsetTo> + NNOffset16To> valuesZ; /* A 16-bit offset from the start of * the table to the data. */ public: @@ -659,7 +662,7 @@ struct ClassTable } protected: HBGlyphID firstGlyph; /* First glyph index included in the trimmed array. */ - ArrayOf classArray; /* The class codes (indexed by glyph index minus + Array16Of classArray; /* The class codes (indexed by glyph index minus * firstGlyph). */ public: DEFINE_SIZE_ARRAY (4, classArray); @@ -678,7 +681,8 @@ struct ObsoleteTypes const void *base, const T *array) { - return (offset - ((const char *) array - (const char *) base)) / T::static_size; + /* https://github.com/harfbuzz/harfbuzz/issues/2816 */ + return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size; } template static unsigned int byteOffsetToIndex (unsigned int offset, @@ -862,6 +866,7 @@ struct hb_aat_apply_context_t : hb_buffer_t *buffer; hb_sanitize_context_t sanitizer; const ankr *ankr_table; + const OT::GDEF *gdef_table; /* Unused. For debug tracing only. */ unsigned int lookup_index; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh index 359e859cfc..573f0cf9f6 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh @@ -144,7 +144,7 @@ struct FeatureName protected: HBUINT16 feature; /* Feature type. */ HBUINT16 nSettings; /* The number of records in the setting name array. */ - LNNOffsetTo> + NNOffset32To> settingTableZ; /* Offset in bytes from the beginning of this table to * this feature's setting name array. The actual type of * record this offset refers to will depend on the diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh index 49506e9f5a..556d4ad75b 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh @@ -79,7 +79,7 @@ struct DecompositionAction * to decompose before more frequent ones. The ligatures * on the line of text will decompose in increasing * value of this field. */ - ArrayOf + Array16Of decomposedglyphs; /* Number of 16-bit glyph indexes that follow; * the ligature will be decomposed into these glyphs. @@ -310,7 +310,7 @@ struct WidthDeltaPair DEFINE_SIZE_STATIC (24); }; -typedef OT::LArrayOf WidthDeltaCluster; +typedef OT::Array32Of WidthDeltaCluster; struct JustificationCategory { @@ -358,20 +358,20 @@ struct JustificationHeader } protected: - OffsetTo + Offset16To justClassTable; /* Offset to the justification category state table. */ - OffsetTo + Offset16To wdcTable; /* Offset from start of justification table to start * of the subtable containing the width delta factors * for the glyphs in your font. * * The width delta clusters table. */ - OffsetTo + Offset16To pcTable; /* Offset from start of justification table to start * of postcompensation subtable (set to zero if none). * * The postcompensation subtable, if present in the font. */ - Lookup> + Lookup> lookupTable; /* Lookup table associating glyphs with width delta * clusters. See the description of Width Delta Clusters * table for details on how to interpret the lookup values. */ @@ -398,13 +398,13 @@ struct just FixedVersion<>version; /* Version of the justification table * (0x00010000u for version 1.0). */ HBUINT16 format; /* Format of the justification table (set to 0). */ - OffsetTo + Offset16To horizData; /* Byte offset from the start of the justification table * to the header for tables that contain justification * information for horizontal text. * If you are not including this information, * store 0. */ - OffsetTo + Offset16To vertData; /* ditto, vertical */ public: diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh index 1cd412164e..d0eacf0e61 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh @@ -710,18 +710,18 @@ struct KerxSubTableFormat6 { struct Long { - LNNOffsetTo> rowIndexTable; - LNNOffsetTo> columnIndexTable; - LNNOffsetTo> array; + NNOffset32To> rowIndexTable; + NNOffset32To> columnIndexTable; + NNOffset32To> array; } l; struct Short { - LNNOffsetTo> rowIndexTable; - LNNOffsetTo> columnIndexTable; - LNNOffsetTo> array; + NNOffset32To> rowIndexTable; + NNOffset32To> columnIndexTable; + NNOffset32To> array; } s; } u; - LNNOffsetTo> vector; + NNOffset32To> vector; public: DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24); }; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index e3bc268d26..a807bdcfc5 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" #include "hb-ot-layout-common.hh" +#include "hb-ot-layout-gdef-table.hh" #include "hb-aat-map.hh" /* @@ -215,7 +216,9 @@ struct ContextualSubtable hb_aat_apply_context_t *c_) : ret (false), c (c_), + gdef (*c->gdef_table), mark_set (false), + has_glyph_classes (gdef.has_glyph_classes ()), mark (0), table (table_), subs (table+table->substitutionTables) {} @@ -263,6 +266,9 @@ struct ContextualSubtable { buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len)); buffer->info[mark].codepoint = *replacement; + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->info[mark], + gdef.get_glyph_props (*replacement)); ret = true; } @@ -287,6 +293,9 @@ struct ContextualSubtable if (replacement) { buffer->info[idx].codepoint = *replacement; + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&buffer->info[idx], + gdef.get_glyph_props (*replacement)); ret = true; } @@ -301,10 +310,12 @@ struct ContextualSubtable bool ret; private: hb_aat_apply_context_t *c; + const OT::GDEF &gdef; bool mark_set; + bool has_glyph_classes; unsigned int mark; const ContextualSubtable *table; - const UnsizedOffsetListOf, HBUINT, false> &subs; + const UnsizedListOfOffset16To, HBUINT, false> &subs; }; bool apply (hb_aat_apply_context_t *c) const @@ -348,7 +359,7 @@ struct ContextualSubtable protected: StateTable machine; - NNOffsetTo, HBUINT, false>, HBUINT> + NNOffsetTo, HBUINT, false>, HBUINT> substitutionTables; public: DEFINE_SIZE_STATIC (20); @@ -599,6 +610,9 @@ struct NoncontextualSubtable { TRACE_APPLY (this); + const OT::GDEF &gdef (*c->gdef_table); + bool has_glyph_classes = gdef.has_glyph_classes (); + bool ret = false; unsigned int num_glyphs = c->face->get_num_glyphs (); @@ -610,6 +624,9 @@ struct NoncontextualSubtable if (replacement) { info[i].codepoint = *replacement; + if (has_glyph_classes) + _hb_glyph_info_set_glyph_props (&info[i], + gdef.get_glyph_props (*replacement)); ret = true; } } diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh index 8c04a6482f..b1a1512821 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh @@ -58,7 +58,7 @@ struct opbdFormat0 bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id, hb_glyph_extents_t *extents, const void *base) const { - const OffsetTo *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); + const Offset16To *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); if (!bounds_offset) return false; const OpticalBounds &bounds = base+*bounds_offset; @@ -79,7 +79,7 @@ struct opbdFormat0 } protected: - Lookup> + Lookup> lookupTable; /* Lookup table associating glyphs with the four * int16 values for the left-side, top-side, * right-side, and bottom-side optical bounds. */ @@ -92,7 +92,7 @@ struct opbdFormat1 bool get_bounds (hb_font_t *font, hb_codepoint_t glyph_id, hb_glyph_extents_t *extents, const void *base) const { - const OffsetTo *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); + const Offset16To *bounds_offset = lookupTable.get_value (glyph_id, font->face->get_num_glyphs ()); if (!bounds_offset) return false; const OpticalBounds &bounds = base+*bounds_offset; @@ -116,7 +116,7 @@ struct opbdFormat1 } protected: - Lookup> + Lookup> lookupTable; /* Lookup table associating glyphs with the four * int16 values for the left-side, top-side, * right-side, and bottom-side optical bounds. */ diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh index baa1c72020..68bcb2396f 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-trak-table.hh @@ -66,7 +66,7 @@ struct TrackTableEntry NameID trackNameID; /* The 'name' table index for this track. * (a short word or phrase like "loose" * or "very tight") */ - NNOffsetTo> + NNOffset16To> valuesZ; /* Offset from start of tracking table to * per-size tracking values for this track. */ @@ -141,7 +141,7 @@ struct TrackData protected: HBUINT16 nTracks; /* Number of separate tracks included in this table. */ HBUINT16 nSizes; /* Number of point sizes included in this table. */ - LNNOffsetTo> + NNOffset32To> sizeTable; /* Offset from start of the tracking table to * Array[nSizes] of size values.. */ UnsizedArrayOf @@ -212,10 +212,10 @@ struct trak FixedVersion<>version; /* Version of the tracking table * (0x00010000u for version 1.0). */ HBUINT16 format; /* Format of the tracking table (set to 0). */ - OffsetTo + Offset16To horizData; /* Offset from start of tracking table to TrackData * for horizontal text (or 0 if none). */ - OffsetTo + Offset16To vertData; /* Offset from start of tracking table to TrackData * for vertical text (or 0 if none). */ HBUINT16 reserved; /* Reserved. Set to 0. */ diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc index 0e9f2b4954..e2d4de2ccd 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout.cc +++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc @@ -55,6 +55,7 @@ AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *p buffer (buffer_), sanitizer (), ankr_table (&Null (AAT::ankr)), + gdef_table (face->table.GDEF->table), lookup_index (0) { sanitizer.init (blob); @@ -79,7 +80,7 @@ AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_) * @short_description: Apple Advanced Typography Layout * @include: hb-aat.h * - * Functions for querying AAT Layout features in the font face. + * Functions for querying AAT Layout features in the font face. * * HarfBuzz supports all of the AAT tables used to implement shaping. Other * AAT tables and their associated features are not supported. @@ -172,13 +173,13 @@ static const hb_aat_feature_mapping_t feature_mappings[] = {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF}, }; -/** +/** * hb_aat_layout_find_feature_mapping: * @tag: The requested #hb_tag_t feature tag * * Fetches the AAT feature-and-selector combination that corresponds * to a given OpenType feature tag. - * + * * Return value: the AAT features and selectors corresponding to the * OpenType feature tag queried * @@ -248,7 +249,9 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, if (morx.has_data ()) { AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob); + if (!buffer->message (font, "start table morx")) return; morx.apply (&c); + (void) buffer->message (font, "end table morx"); return; } @@ -257,7 +260,9 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, if (mort.has_data ()) { AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob); + if (!buffer->message (font, "start table mort")) return; mort.apply (&c); + (void) buffer->message (font, "end table mort"); return; } } @@ -313,8 +318,10 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, const AAT::kerx& kerx = *kerx_blob->as (); AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob); + if (!buffer->message (font, "start table kerx")) return; c.set_ankr_table (font->face->table.ankr.get ()); kerx.apply (&c); + (void) buffer->message (font, "end table kerx"); } diff --git a/thirdparty/harfbuzz/src/hb-aat-ltag-table.hh b/thirdparty/harfbuzz/src/hb-aat-ltag-table.hh index 711f9aa6c1..6d771e1513 100644 --- a/thirdparty/harfbuzz/src/hb-aat-ltag-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-ltag-table.hh @@ -50,7 +50,7 @@ struct FTStringRange } protected: - NNOffsetTo> + NNOffset16To> tag; /* Offset from the start of the table to * the beginning of the string */ HBUINT16 length; /* String length (in bytes) */ @@ -80,7 +80,7 @@ struct ltag protected: HBUINT32 version; /* Table version; currently 1 */ HBUINT32 flags; /* Table flags; currently none defined */ - LArrayOf + Array32Of tagRanges; /* Range for each tag's string */ public: DEFINE_SIZE_ARRAY (12, tagRanges); diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index bc170b0546..bbe097fe01 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -760,6 +760,14 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; } #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) +static inline void * +hb_memcpy (void *__restrict dst, const void *__restrict src, size_t len) +{ + /* It's illegal to pass 0 as size to memcpy. */ + if (unlikely (!len)) return dst; + return memcpy (dst, src, len); +} + static inline int hb_memcmp (const void *a, const void *b, unsigned int len) { @@ -1151,30 +1159,48 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o /* Operators. */ -struct hb_bitwise_and +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) } HB_FUNCOBJ (hb_bitwise_and); -struct hb_bitwise_or +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) } HB_FUNCOBJ (hb_bitwise_or); -struct hb_bitwise_xor +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) } HB_FUNCOBJ (hb_bitwise_xor); -struct hb_bitwise_sub +struct +{ HB_PARTIALIZE(2); + template constexpr auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a & b) +} +HB_FUNCOBJ (hb_bitwise_lt); +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) } -HB_FUNCOBJ (hb_bitwise_sub); +HB_FUNCOBJ (hb_bitwise_gt); // aka sub +struct +{ HB_PARTIALIZE(2); + template constexpr auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (~a | b) +} +HB_FUNCOBJ (hb_bitwise_le); +struct +{ HB_PARTIALIZE(2); + template constexpr auto + operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | ~b) +} +HB_FUNCOBJ (hb_bitwise_ge); struct { template constexpr auto @@ -1195,6 +1221,12 @@ struct } HB_FUNCOBJ (hb_sub); struct +{ HB_PARTIALIZE(2); + template constexpr auto + operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (b - a) +} +HB_FUNCOBJ (hb_rsub); +struct { HB_PARTIALIZE(2); template constexpr auto operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b) diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh index 02bd8d81c2..ab0dd6ebe3 100644 --- a/thirdparty/harfbuzz/src/hb-array.hh +++ b/thirdparty/harfbuzz/src/hb-array.hh @@ -36,6 +36,14 @@ template struct hb_sorted_array_t; +enum hb_not_found_t +{ + HB_NOT_FOUND_DONT_STORE, + HB_NOT_FOUND_STORE, + HB_NOT_FOUND_STORE_CLOSEST, +}; + + template struct hb_array_t : hb_iter_with_fallback_t, Type&> { @@ -139,7 +147,9 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> return lfind (x, &i) ? &this->arrayZ[i] : not_found; } template - bool lfind (const T &x, unsigned *pos = nullptr) const + bool lfind (const T &x, unsigned *pos = nullptr, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const { for (unsigned i = 0; i < length; ++i) if (hb_equal (x, this->arrayZ[i])) @@ -149,6 +159,22 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> return true; } + if (pos) + { + switch (not_found) + { + case HB_NOT_FOUND_DONT_STORE: + break; + + case HB_NOT_FOUND_STORE: + *pos = to_store; + break; + + case HB_NOT_FOUND_STORE_CLOSEST: + *pos = length; + break; + } + } return false; } @@ -219,7 +245,7 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> unsigned P = sizeof (Type), hb_enable_if (P == 1)> const T *as () const - { return length < hb_null_size (T) ? &Null (T) : reinterpret_cast (arrayZ); } + { return length < hb_min_size (T) ? &Null (T) : reinterpret_cast (arrayZ); } template , Type&> && (unsigned int) (arrayZ + length - (const char *) p) >= size; } - /* Only call if you allocated the underlying array using malloc() or similar. */ - void free () - { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; } + /* Only call if you allocated the underlying array using hb_malloc() or similar. */ + void fini () + { hb_free ((void *) arrayZ); arrayZ = nullptr; length = 0; } template hb_array_t copy (hb_serialize_context_t *c) const @@ -266,13 +292,6 @@ template inline hb_array_t hb_array (T (&array_)[length_]) { return hb_array_t (array_); } -enum hb_bfind_not_found_t -{ - HB_BFIND_NOT_FOUND_DONT_STORE, - HB_BFIND_NOT_FOUND_STORE, - HB_BFIND_NOT_FOUND_STORE_CLOSEST, -}; - template struct hb_sorted_array_t : hb_iter_t, Type&>, @@ -323,7 +342,7 @@ struct hb_sorted_array_t : } template bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, unsigned int to_store = (unsigned int) -1) const { unsigned pos; @@ -339,14 +358,14 @@ struct hb_sorted_array_t : { switch (not_found) { - case HB_BFIND_NOT_FOUND_DONT_STORE: + case HB_NOT_FOUND_DONT_STORE: break; - case HB_BFIND_NOT_FOUND_STORE: + case HB_NOT_FOUND_STORE: *i = to_store; break; - case HB_BFIND_NOT_FOUND_STORE_CLOSEST: + case HB_NOT_FOUND_STORE_CLOSEST: *i = pos; break; } diff --git a/thirdparty/harfbuzz/src/hb-bimap.hh b/thirdparty/harfbuzz/src/hb-bimap.hh index e9f3a6a52d..d409880751 100644 --- a/thirdparty/harfbuzz/src/hb-bimap.hh +++ b/thirdparty/harfbuzz/src/hb-bimap.hh @@ -58,10 +58,15 @@ struct hb_bimap_t void set (hb_codepoint_t lhs, hb_codepoint_t rhs) { + if (in_error ()) return; if (unlikely (lhs == HB_MAP_VALUE_INVALID)) return; if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; } + forw_map.set (lhs, rhs); + if (in_error ()) return; + back_map.set (rhs, lhs); + if (in_error ()) forw_map.del (lhs); } hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); } diff --git a/thirdparty/harfbuzz/src/hb-bit-page.hh b/thirdparty/harfbuzz/src/hb-bit-page.hh new file mode 100644 index 0000000000..263be3d044 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-bit-page.hh @@ -0,0 +1,203 @@ +/* + * Copyright © 2012,2017 Google, Inc. + * Copyright © 2021 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_PAGE_HH +#define HB_BIT_PAGE_HH + +#include "hb.hh" + +struct hb_bit_page_t +{ + void init0 () { v.clear (); } + void init1 () { v.clear (0xFF); } + + constexpr unsigned len () const + { return ARRAY_LENGTH_CONST (v); } + + bool is_empty () const + { + for (unsigned int i = 0; i < len (); i++) + if (v[i]) + return false; + return true; + } + + void add (hb_codepoint_t g) { elt (g) |= mask (g); } + void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } + void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); } + bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } + + 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); + } + } + void del_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, 0, (char *) lb - (char *) la); + + *lb &= ~((mask (b) << 1) - 1); + } + } + void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v) + { if (v) add_range (a, b); else del_range (a, b); } + + bool is_equal (const hb_bit_page_t &other) const + { + return 0 == hb_memcmp (&v, &other.v, sizeof (v)); + } + bool is_subset (const hb_bit_page_t &larger_page) const + { + for (unsigned i = 0; i < len (); i++) + if (~larger_page.v[i] & v[i]) + return false; + return true; + } + + unsigned int get_population () const + { + unsigned int pop = 0; + for (unsigned int i = 0; i < len (); i++) + pop += hb_popcount (v[i]); + return pop; + } + + 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; + + const elt_t vv = v[i] & ~((elt_t (1) << j) - 1); + for (const elt_t *p = &vv; i < len (); p = &v[++i]) + if (*p) + { + *codepoint = i * ELT_BITS + elt_get_min (*p); + return true; + } + + *codepoint = INVALID; + return false; + } + bool previous (hb_codepoint_t *codepoint) const + { + unsigned int m = (*codepoint - 1) & MASK; + if (m == MASK) + { + *codepoint = INVALID; + return false; + } + unsigned int i = m / ELT_BITS; + unsigned int j = m & ELT_MASK; + + /* Fancy mask to avoid shifting by elt_t bitsize, which is undefined. */ + const elt_t mask = j < 8 * sizeof (elt_t) - 1 ? + ((elt_t (1) << (j + 1)) - 1) : + (elt_t) -1; + const elt_t vv = v[i] & mask; + const elt_t *p = &vv; + while (true) + { + if (*p) + { + *codepoint = i * ELT_BITS + elt_get_max (*p); + return true; + } + if ((int) i <= 0) break; + p = &v[--i]; + } + + *codepoint = INVALID; + return false; + } + hb_codepoint_t get_min () const + { + for (unsigned int i = 0; i < len (); i++) + if (v[i]) + return i * ELT_BITS + elt_get_min (v[i]); + return INVALID; + } + hb_codepoint_t get_max () const + { + for (int i = len () - 1; i >= 0; i--) + if (v[i]) + return i * ELT_BITS + elt_get_max (v[i]); + return 0; + } + + static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID; + + typedef unsigned long long elt_t; + static constexpr unsigned PAGE_BITS = 512; + static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, ""); + + static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); } + static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; } + + typedef hb_vector_size_t vector_t; + + static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8; + static constexpr unsigned ELT_MASK = ELT_BITS - 1; + static constexpr unsigned BITS = sizeof (vector_t) * 8; + static constexpr unsigned MASK = BITS - 1; + static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, ""); + + elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; } + const elt_t& elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; } + static constexpr elt_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); } + + vector_t v; +}; +static_assert (hb_bit_page_t::PAGE_BITS == sizeof (hb_bit_page_t) * 8, ""); + + +#endif /* HB_BIT_PAGE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh new file mode 100644 index 0000000000..f48b72fe63 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh @@ -0,0 +1,354 @@ +/* + * Copyright © 2012,2017 Google, Inc. + * Copyright © 2021 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_SET_INVERTIBLE_HH +#define HB_BIT_SET_INVERTIBLE_HH + +#include "hb.hh" +#include "hb-bit-set.hh" + + +struct hb_bit_set_invertible_t +{ + hb_bit_set_t s; + bool inverted; + + hb_bit_set_invertible_t () { init (); } + ~hb_bit_set_invertible_t () { fini (); } + + void init () { s.init (); inverted = false; } + void fini () { s.fini (); } + void err () { s.err (); } + bool in_error () const { return s.in_error (); } + explicit operator bool () const { return !is_empty (); } + + void reset () + { + s.reset (); + inverted = false; + } + void clear () + { + s.clear (); + if (likely (s.successful)) + inverted = false; + } + void invert () + { + if (likely (s.successful)) + inverted = !inverted; + } + + bool is_empty () const + { + hb_codepoint_t v = INVALID; + next (&v); + return v == INVALID; + } + hb_codepoint_t get_min () const + { + hb_codepoint_t v = INVALID; + next (&v); + return v; + } + hb_codepoint_t get_max () const + { + hb_codepoint_t v = INVALID; + previous (&v); + return v; + } + unsigned int get_population () const + { return inverted ? INVALID - s.get_population () : s.get_population (); } + + + void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); } + bool add_range (hb_codepoint_t a, hb_codepoint_t b) + { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); } + + template + void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); } + template + void add_array (const hb_array_t& arr) { add_array (&arr, arr.len ()); } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template + bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); } + template + bool add_sorted_array (const hb_sorted_array_t& arr) { return add_sorted_array (&arr, arr.len ()); } + + void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); } + void del_range (hb_codepoint_t a, hb_codepoint_t b) + { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); } + + bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; } + + /* Has interface. */ + static constexpr bool SENTINEL = false; + typedef bool value_t; + value_t operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + /* Predicate. */ + bool operator () (hb_codepoint_t k) const { return has (k); } + + /* Sink interface. */ + hb_bit_set_invertible_t& operator << (hb_codepoint_t v) + { add (v); return *this; } + hb_bit_set_invertible_t& operator << (const hb_pair_t& range) + { add_range (range.first, range.second); return *this; } + + bool intersects (hb_codepoint_t first, hb_codepoint_t last) const + { + hb_codepoint_t c = first - 1; + return next (&c) && c <= last; + } + + void set (const hb_bit_set_invertible_t &other) + { + s.set (other.s); + if (likely (s.successful)) + inverted = other.inverted; + } + + bool is_equal (const hb_bit_set_invertible_t &other) const + { + if (likely (inverted == other.inverted)) + return s.is_equal (other.s); + else + { + /* TODO Add iter_ranges() and use here. */ + auto it1 = iter (); + auto it2 = other.iter (); + return hb_all (+ hb_zip (it1, it2) + | hb_map ([](hb_pair_t _) { return _.first == _.second; })); + } + } + + bool is_subset (const hb_bit_set_invertible_t &larger_set) const + { + if (unlikely (inverted != larger_set.inverted)) + return hb_all (hb_iter (s) | hb_map (larger_set.s)); + else + return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s); + } + + protected: + template + void process (const Op& op, const hb_bit_set_invertible_t &other) + { s.process (op, other.s); } + public: + void union_ (const hb_bit_set_invertible_t &other) + { + if (likely (inverted == other.inverted)) + { + if (unlikely (inverted)) + process (hb_bitwise_and, other); + else + process (hb_bitwise_or, other); /* Main branch. */ + } + else + { + if (unlikely (inverted)) + process (hb_bitwise_gt, other); + else + process (hb_bitwise_lt, other); + } + if (likely (s.successful)) + inverted = inverted || other.inverted; + } + void intersect (const hb_bit_set_invertible_t &other) + { + if (likely (inverted == other.inverted)) + { + if (unlikely (inverted)) + process (hb_bitwise_or, other); + else + process (hb_bitwise_and, other); /* Main branch. */ + } + else + { + if (unlikely (inverted)) + process (hb_bitwise_lt, other); + else + process (hb_bitwise_gt, other); + } + if (likely (s.successful)) + inverted = inverted && other.inverted; + } + void subtract (const hb_bit_set_invertible_t &other) + { + if (likely (inverted == other.inverted)) + { + if (unlikely (inverted)) + process (hb_bitwise_lt, other); + else + process (hb_bitwise_gt, other); /* Main branch. */ + } + else + { + if (unlikely (inverted)) + process (hb_bitwise_or, other); + else + process (hb_bitwise_and, other); + } + if (likely (s.successful)) + inverted = inverted && !other.inverted; + } + void symmetric_difference (const hb_bit_set_invertible_t &other) + { + process (hb_bitwise_xor, other); + if (likely (s.successful)) + inverted = inverted ^ other.inverted; + } + + bool next (hb_codepoint_t *codepoint) const + { + if (likely (!inverted)) + return s.next (codepoint); + + auto old = *codepoint; + if (unlikely (old + 1 == INVALID)) + { + *codepoint = INVALID; + return false; + } + + auto v = old; + s.next (&v); + if (old + 1 < v) + { + *codepoint = old + 1; + return true; + } + + v = old; + s.next_range (&old, &v); + + *codepoint = v + 1; + return *codepoint != INVALID; + } + bool previous (hb_codepoint_t *codepoint) const + { + if (likely (!inverted)) + return s.previous (codepoint); + + auto old = *codepoint; + if (unlikely (old - 1 == INVALID)) + { + *codepoint = INVALID; + return false; + } + + auto v = old; + s.previous (&v); + + if (old - 1 > v || v == INVALID) + { + *codepoint = old - 1; + return true; + } + + v = old; + s.previous_range (&v, &old); + + *codepoint = v - 1; + return *codepoint != INVALID; + } + bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + if (likely (!inverted)) + return s.next_range (first, last); + + if (!next (last)) + { + *last = *first = INVALID; + return false; + } + + *first = *last; + s.next (last); + --*last; + return true; + } + bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + if (likely (!inverted)) + return s.previous_range (first, last); + + if (!previous (first)) + { + *last = *first = INVALID; + return false; + } + + *last = *first; + s.previous (first); + ++*first; + return true; + } + + static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID; + + /* + * Iterator implementation. + */ + struct iter_t : hb_iter_with_fallback_t + { + static constexpr bool is_sorted_iterator = true; + iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t), + bool init = true) : s (&s_), v (INVALID), l(0) + { + if (init) + { + l = s->get_population () + 1; + __next__ (); + } + } + + typedef hb_codepoint_t __item_t__; + hb_codepoint_t __item__ () const { return v; } + bool __more__ () const { return v != INVALID; } + void __next__ () { s->next (&v); if (l) l--; } + void __prev__ () { s->previous (&v); } + unsigned __len__ () const { return l; } + iter_t end () const { return iter_t (*s, false); } + bool operator != (const iter_t& o) const + { return s != o.s || v != o.v; } + + protected: + const hb_bit_set_invertible_t *s; + hb_codepoint_t v; + unsigned l; + }; + iter_t iter () const { return iter_t (*this); } + operator iter_t () const { return iter (); } +}; + + +#endif /* HB_BIT_SET_INVERTIBLE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh new file mode 100644 index 0000000000..c21778d88e --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-bit-set.hh @@ -0,0 +1,808 @@ +/* + * Copyright © 2012,2017 Google, Inc. + * Copyright © 2021 Behdad Esfahbod + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_BIT_SET_HH +#define HB_BIT_SET_HH + +#include "hb.hh" +#include "hb-bit-page.hh" +#include "hb-machinery.hh" + + +struct hb_bit_set_t +{ + hb_bit_set_t () { init (); } + ~hb_bit_set_t () { fini (); } + + hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); } + void operator= (const hb_bit_set_t& other) { set (other); } + // TODO Add move construtor/assign + // TODO Add constructor for Iterator; with specialization for (sorted) vector / array? + + void init () + { + successful = true; + population = 0; + last_page_lookup = 0; + page_map.init (); + pages.init (); + } + void fini () + { + page_map.fini (); + pages.fini (); + } + + using page_t = hb_bit_page_t; + struct page_map_t + { + int cmp (const page_map_t &o) const { return cmp (o.major); } + int cmp (uint32_t o_major) const { return (int) o_major - (int) major; } + + uint32_t major; + uint32_t index; + }; + + bool successful; /* Allocations successful */ + mutable unsigned int population; + mutable unsigned int last_page_lookup; + hb_sorted_vector_t page_map; + hb_vector_t pages; + + void err () { if (successful) successful = false; } /* TODO Remove */ + bool in_error () const { return !successful; } + + bool resize (unsigned int count) + { + if (unlikely (!successful)) return false; + if (unlikely (!pages.resize (count) || !page_map.resize (count))) + { + pages.resize (page_map.length); + successful = false; + return false; + } + return true; + } + + void reset () + { + successful = true; + clear (); + } + + void clear () + { + resize (0); + if (likely (successful)) + population = 0; + } + bool is_empty () const + { + unsigned int count = pages.length; + for (unsigned int i = 0; i < count; i++) + if (!pages[i].is_empty ()) + return false; + return true; + } + explicit operator bool () const { return !is_empty (); } + + private: + void dirty () { population = UINT_MAX; } + public: + + void add (hb_codepoint_t g) + { + if (unlikely (!successful)) return; + if (unlikely (g == INVALID)) return; + dirty (); + page_t *page = page_for (g, true); if (unlikely (!page)) return; + page->add (g); + } + bool add_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */ + if (unlikely (a > b || a == INVALID || b == INVALID)) return false; + dirty (); + unsigned int ma = get_major (a); + unsigned int mb = get_major (b); + if (ma == mb) + { + page_t *page = page_for (a, true); if (unlikely (!page)) return false; + page->add_range (a, b); + } + else + { + page_t *page = page_for (a, true); 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 (major_start (m), true); if (unlikely (!page)) return false; + page->init1 (); + } + + page = page_for (b, true); if (unlikely (!page)) return false; + page->add_range (major_start (mb), b); + } + return true; + } + + template + void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + if (unlikely (!successful)) return; + if (!count) return; + dirty (); + hb_codepoint_t g = *array; + while (count) + { + unsigned int m = get_major (g); + page_t *page = page_for (g, v); if (unlikely (v && !page)) return; + unsigned int start = major_start (m); + unsigned int end = major_start (m + 1); + do + { + if (v || page) /* The v check is to optimize out the page check if v is true. */ + page->set (g, v); + + array = &StructAtOffsetUnaligned (array, stride); + count--; + } + while (count && (g = *array, start <= g && g < end)); + } + } + + template + void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { set_array (true, array, count, stride); } + template + void add_array (const hb_array_t& arr) { add_array (&arr, arr.len ()); } + + template + void del_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { set_array (false, array, count, stride); } + template + void del_array (const hb_array_t& arr) { del_array (&arr, arr.len ()); } + + /* Might return false if array looks unsorted. + * Used for faster rejection of corrupt data. */ + template + bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { + if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */ + if (!count) return true; + dirty (); + hb_codepoint_t g = *array; + hb_codepoint_t last_g = g; + while (count) + { + unsigned int m = get_major (g); + page_t *page = page_for (g, v); if (unlikely (v && !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; + + if (v || page) /* The v check is to optimize out the page check if v is true. */ + page->add (g); + + array = (const T *) ((const char *) array + stride); + count--; + } + while (count && (g = *array, g < end)); + } + return true; + } + + template + bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { return set_sorted_array (true, array, count, stride); } + template + bool add_sorted_array (const hb_sorted_array_t& arr) { return add_sorted_array (&arr, arr.len ()); } + + template + bool del_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) + { return set_sorted_array (false, array, count, stride); } + template + bool del_sorted_array (const hb_sorted_array_t& arr) { return del_sorted_array (&arr, arr.len ()); } + + void del (hb_codepoint_t g) + { + if (unlikely (!successful)) return; + page_t *page = page_for (g); + if (!page) + return; + dirty (); + page->del (g); + } + + private: + void del_pages (int ds, int de) + { + if (ds <= de) + { + // Pre-allocate the workspace that compact() will need so we can bail on allocation failure + // before attempting to rewrite the page map. + hb_vector_t compact_workspace; + if (unlikely (!allocate_compact_workspace (compact_workspace))) return; + + unsigned int write_index = 0; + for (unsigned int i = 0; i < page_map.length; i++) + { + int m = (int) page_map[i].major; + if (m < ds || de < m) + page_map[write_index++] = page_map[i]; + } + compact (compact_workspace, write_index); + resize (write_index); + } + } + + + public: + void del_range (hb_codepoint_t a, hb_codepoint_t b) + { + if (unlikely (!successful)) return; + if (unlikely (a > b || a == INVALID)) return; + dirty (); + unsigned int ma = get_major (a); + unsigned int mb = get_major (b); + /* Delete pages from ds through de if ds <= de. */ + int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1); + int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1); + if (ds > de || (int) ma < ds) + { + page_t *page = page_for (a); + if (page) + { + if (ma == mb) + page->del_range (a, b); + else + page->del_range (a, major_start (ma + 1) - 1); + } + } + if (de < (int) mb && ma != mb) + { + page_t *page = page_for (b); + if (page) + page->del_range (major_start (mb), b); + } + del_pages (ds, de); + } + + bool get (hb_codepoint_t g) const + { + const page_t *page = page_for (g); + if (!page) + return false; + return page->get (g); + } + + /* Has interface. */ + static constexpr bool SENTINEL = false; + typedef bool value_t; + value_t operator [] (hb_codepoint_t k) const { return get (k); } + bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } + /* Predicate. */ + bool operator () (hb_codepoint_t k) const { return has (k); } + + /* Sink interface. */ + hb_bit_set_t& operator << (hb_codepoint_t v) + { add (v); return *this; } + hb_bit_set_t& operator << (const hb_pair_t& range) + { add_range (range.first, range.second); return *this; } + + bool intersects (hb_codepoint_t first, hb_codepoint_t last) const + { + hb_codepoint_t c = first - 1; + return next (&c) && c <= last; + } + void set (const hb_bit_set_t &other) + { + if (unlikely (!successful)) return; + unsigned int count = other.pages.length; + if (unlikely (!resize (count))) + return; + population = other.population; + + /* TODO switch to vector operator =. */ + hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size); + hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size); + } + + bool is_equal (const hb_bit_set_t &other) const + { + if (has_population () && other.has_population () && + get_population () != other.get_population ()) + return false; + + unsigned int na = pages.length; + unsigned int nb = other.pages.length; + + 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; + } + + bool is_subset (const hb_bit_set_t &larger_set) const + { + if (has_population () && larger_set.has_population () && + get_population () != larger_set.get_population ()) + return false; + + uint32_t spi = 0; + for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++) + { + uint32_t spm = page_map[spi].major; + uint32_t lpm = larger_set.page_map[lpi].major; + auto sp = page_at (spi); + auto lp = larger_set.page_at (lpi); + + if (spm < lpm && !sp.is_empty ()) + return false; + + if (lpm < spm) + continue; + + if (!sp.is_subset (lp)) + return false; + + spi++; + } + + while (spi < page_map.length) + if (!page_at (spi++).is_empty ()) + return false; + + return true; + } + + private: + bool allocate_compact_workspace (hb_vector_t& workspace) + { + if (unlikely (!workspace.resize (pages.length))) + { + successful = false; + return false; + } + + return true; + } + + /* + * workspace should be a pre-sized vector allocated to hold at exactly pages.length + * elements. + */ + void compact (hb_vector_t& workspace, + unsigned int length) + { + assert(workspace.length == pages.length); + hb_vector_t& old_index_to_page_map_index = workspace; + + hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF); + for (unsigned i = 0; i < length; i++) + old_index_to_page_map_index[page_map[i].index] = i; + + compact_pages (old_index_to_page_map_index); + } + void compact_pages (const hb_vector_t& old_index_to_page_map_index) + { + unsigned int write_index = 0; + for (unsigned int i = 0; i < pages.length; i++) + { + if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue; + + if (write_index < i) + pages[write_index] = pages[i]; + + page_map[old_index_to_page_map_index[i]].index = write_index; + write_index++; + } + } + public: + + template + void process (const Op& op, const hb_bit_set_t &other) + { + const bool passthru_left = op (1, 0); + const bool passthru_right = op (0, 1); + + if (unlikely (!successful)) return; + + dirty (); + + unsigned int na = pages.length; + unsigned int nb = other.pages.length; + unsigned int next_page = na; + + unsigned int count = 0, newCount = 0; + unsigned int a = 0, b = 0; + unsigned int write_index = 0; + + // Pre-allocate the workspace that compact() will need so we can bail on allocation failure + // before attempting to rewrite the page map. + hb_vector_t compact_workspace; + if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return; + + for (; a < na && b < nb; ) + { + if (page_map[a].major == other.page_map[b].major) + { + if (!passthru_left) + { + // Move page_map entries that we're keeping from the left side set + // to the front of the page_map vector. This isn't necessary if + // passthru_left is set since no left side pages will be removed + // in that case. + if (write_index < a) + page_map[write_index] = page_map[a]; + write_index++; + } + + count++; + a++; + b++; + } + else if (page_map[a].major < other.page_map[b].major) + { + if (passthru_left) + count++; + a++; + } + else + { + if (passthru_right) + count++; + b++; + } + } + if (passthru_left) + count += na - a; + if (passthru_right) + count += nb - b; + + if (!passthru_left) + { + na = write_index; + next_page = write_index; + compact (compact_workspace, write_index); + } + + if (unlikely (!resize (count))) + return; + + newCount = count; + + /* 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--; + count--; + page_map[count] = page_map[a]; + page_at (count).v = op (page_at (a).v, other.page_at (b).v); + } + else if (page_map[a - 1].major > other.page_map[b - 1].major) + { + a--; + if (passthru_left) + { + count--; + page_map[count] = page_map[a]; + } + } + else + { + b--; + if (passthru_right) + { + count--; + page_map[count].major = other.page_map[b].major; + page_map[count].index = next_page++; + page_at (count).v = other.page_at (b).v; + } + } + } + if (passthru_left) + while (a) + { + a--; + count--; + page_map[count] = page_map [a]; + } + if (passthru_right) + while (b) + { + b--; + count--; + page_map[count].major = other.page_map[b].major; + page_map[count].index = next_page++; + page_at (count).v = other.page_at (b).v; + } + assert (!count); + resize (newCount); + } + + void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); } + void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); } + void subtract (const hb_bit_set_t &other) { process (hb_bitwise_gt, other); } + void symmetric_difference (const hb_bit_set_t &other) { process (hb_bitwise_xor, other); } + + bool next (hb_codepoint_t *codepoint) const + { + // TODO: this should be merged with prev() as both implementations + // are very similar. + if (unlikely (*codepoint == INVALID)) { + *codepoint = get_min (); + return *codepoint != INVALID; + } + + const auto* page_map_array = page_map.arrayZ; + unsigned int major = get_major (*codepoint); + unsigned int i = last_page_lookup; + + if (unlikely (i >= page_map.length || page_map_array[i].major != major)) + { + page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (i >= page_map.length) { + *codepoint = INVALID; + return false; + } + } + + const auto* pages_array = pages.arrayZ; + const page_map_t ¤t = page_map_array[i]; + if (likely (current.major == major)) + { + if (pages_array[current.index].next (codepoint)) + { + *codepoint += current.major * page_t::PAGE_BITS; + last_page_lookup = i; + return true; + } + i++; + } + + for (; i < page_map.length; i++) + { + const page_map_t ¤t = page_map.arrayZ[i]; + hb_codepoint_t m = pages_array[current.index].get_min (); + if (m != INVALID) + { + *codepoint = current.major * page_t::PAGE_BITS + m; + last_page_lookup = i; + return true; + } + } + last_page_lookup = 0; + *codepoint = INVALID; + return false; + } + bool previous (hb_codepoint_t *codepoint) const + { + if (unlikely (*codepoint == INVALID)) { + *codepoint = get_max (); + return *codepoint != INVALID; + } + + page_map_t map = {get_major (*codepoint), 0}; + unsigned int i; + page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST); + if (i < page_map.length && page_map[i].major == map.major) + { + if (pages[page_map[i].index].previous (codepoint)) + { + *codepoint += page_map[i].major * page_t::PAGE_BITS; + return true; + } + } + i--; + for (; (int) i >= 0; i--) + { + hb_codepoint_t m = pages[page_map[i].index].get_max (); + if (m != INVALID) + { + *codepoint = page_map[i].major * page_t::PAGE_BITS + m; + return true; + } + } + *codepoint = INVALID; + return false; + } + bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + hb_codepoint_t i; + + i = *last; + if (!next (&i)) + { + *last = *first = INVALID; + return false; + } + + /* TODO Speed up. */ + *last = *first = i; + while (next (&i) && i == *last + 1) + (*last)++; + + return true; + } + bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const + { + hb_codepoint_t i; + + i = *first; + if (!previous (&i)) + { + *last = *first = INVALID; + return false; + } + + /* TODO Speed up. */ + *last = *first = i; + while (previous (&i) && i == *first - 1) + (*first)--; + + return true; + } + + bool has_population () const { return population != UINT_MAX; } + unsigned int get_population () const + { + if (has_population ()) + return population; + + unsigned int pop = 0; + unsigned int count = pages.length; + for (unsigned int i = 0; i < count; i++) + pop += pages[i].get_population (); + + population = pop; + return pop; + } + hb_codepoint_t get_min () const + { + unsigned count = pages.length; + for (unsigned i = 0; i < count; i++) + { + const auto& map = page_map[i]; + const auto& page = pages[map.index]; + + if (!page.is_empty ()) + return map.major * page_t::PAGE_BITS + page.get_min (); + } + return INVALID; + } + hb_codepoint_t get_max () const + { + unsigned count = pages.length; + for (signed i = count - 1; i >= 0; i--) + { + const auto& map = page_map[(unsigned) i]; + const auto& page = pages[map.index]; + + if (!page.is_empty ()) + return map.major * page_t::PAGE_BITS + page.get_max (); + } + return INVALID; + } + + static constexpr hb_codepoint_t INVALID = page_t::INVALID; + + /* + * Iterator implementation. + */ + struct iter_t : hb_iter_with_fallback_t + { + static constexpr bool is_sorted_iterator = true; + iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t), + bool init = true) : s (&s_), v (INVALID), l(0) + { + if (init) + { + l = s->get_population () + 1; + __next__ (); + } + } + + typedef hb_codepoint_t __item_t__; + hb_codepoint_t __item__ () const { return v; } + bool __more__ () const { return v != INVALID; } + void __next__ () { s->next (&v); if (l) l--; } + void __prev__ () { s->previous (&v); } + unsigned __len__ () const { return l; } + iter_t end () const { return iter_t (*s, false); } + bool operator != (const iter_t& o) const + { return s != o.s || v != o.v; } + + protected: + const hb_bit_set_t *s; + hb_codepoint_t v; + unsigned l; + }; + iter_t iter () const { return iter_t (*this); } + operator iter_t () const { return iter (); } + + protected: + + page_t *page_for (hb_codepoint_t g, bool insert = false) + { + page_map_t map = {get_major (g), pages.length}; + unsigned int i; + if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST)) + { + if (!insert) + return nullptr; + + if (unlikely (!resize (pages.length + 1))) + return nullptr; + + pages[map.index].init0 (); + memmove (page_map + i + 1, + page_map + i, + (page_map.length - 1 - i) * page_map.item_size); + page_map[i] = map; + } + return &pages[page_map[i].index]; + } + const page_t *page_for (hb_codepoint_t g) const + { + page_map_t key = {get_major (g)}; + const page_map_t *found = page_map.bsearch (key); + if (found) + return &pages[found->index]; + return nullptr; + } + page_t &page_at (unsigned int i) { return pages[page_map[i].index]; } + const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; } + unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; } + hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; } +}; + + +#endif /* HB_BIT_SET_HH */ diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc index 71b1b1fc4f..f120002d17 100644 --- a/thirdparty/harfbuzz/src/hb-blob.cc +++ b/thirdparty/harfbuzz/src/hb-blob.cc @@ -72,16 +72,54 @@ hb_blob_create (const char *data, void *user_data, hb_destroy_func_t destroy) { - hb_blob_t *blob; - - if (!length || - length >= 1u << 31 || - !(blob = hb_object_create ())) { + if (!length) + { if (destroy) destroy (user_data); return hb_blob_get_empty (); } + hb_blob_t *blob = hb_blob_create_or_fail (data, length, mode, + user_data, destroy); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_or_fail: (skip) + * @data: Pointer to blob data. + * @length: Length of @data in bytes. + * @mode: Memory mode for @data. + * @user_data: Data parameter to pass to @destroy. + * @destroy: (nullable): Callback to call when @data is not needed anymore. + * + * Creates a new "blob" object wrapping @data. The @mode parameter is used + * to negotiate ownership and lifecycle of @data. + * + * Note that this function returns a freshly-allocated empty blob even if @length + * is zero. This is in contrast to hb_blob_create(), which returns the singleton + * empty blob (as returned by hb_blob_get_empty()) if @length is zero. + * + * Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy(). + * + * Since: 2.8.2 + **/ +hb_blob_t * +hb_blob_create_or_fail (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy) +{ + hb_blob_t *blob; + + if (length >= 1u << 31 || + !(blob = hb_object_create ())) + { + if (destroy) + destroy (user_data); + return nullptr; + } + blob->data = data; blob->length = length; blob->mode = mode; @@ -91,9 +129,10 @@ hb_blob_create (const char *data, if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { blob->mode = HB_MEMORY_MODE_READONLY; - if (!blob->try_make_writable ()) { + if (!blob->try_make_writable ()) + { hb_blob_destroy (blob); - return hb_blob_get_empty (); + return nullptr; } } @@ -226,7 +265,7 @@ hb_blob_destroy (hb_blob_t *blob) blob->fini_shallow (); - free (blob); + hb_free (blob); } /** @@ -452,7 +491,7 @@ hb_blob_t::try_make_writable () char *new_data; - new_data = (char *) malloc (this->length); + new_data = (char *) hb_malloc (this->length); if (unlikely (!new_data)) return false; @@ -463,7 +502,7 @@ hb_blob_t::try_make_writable () this->mode = HB_MEMORY_MODE_WRITABLE; this->data = new_data; this->user_data = new_data; - this->destroy = free; + this->destroy = hb_free; return true; } @@ -517,7 +556,7 @@ _hb_mapped_file_destroy (void *file_) assert (0); // If we don't have mmap we shouldn't reach here #endif - free (file); + hb_free (file); } #endif @@ -528,7 +567,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file) size_t name_len = strlen (file_name); size_t len = name_len + sizeof (_PATH_RSRCFORKSPEC); - char *rsrc_name = (char *) malloc (len); + char *rsrc_name = (char *) hb_malloc (len); if (unlikely (!rsrc_name)) return -1; strncpy (rsrc_name, file_name, name_len); @@ -536,7 +575,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file) sizeof (_PATH_RSRCFORKSPEC) - 1); int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0); - free (rsrc_name); + hb_free (rsrc_name); if (fd != -1) { @@ -561,17 +600,37 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file) * Creates a new blob containing the data from the * specified binary font file. * - * Returns: An #hb_blob_t pointer with the content of the file + * Returns: An #hb_blob_t pointer with the content of the file, + * or hb_blob_get_empty() if failed. * * Since: 1.7.7 **/ hb_blob_t * hb_blob_create_from_file (const char *file_name) +{ + hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name); + return likely (blob) ? blob : hb_blob_get_empty (); +} + +/** + * hb_blob_create_from_file_or_fail: + * @file_name: A font filename + * + * Creates a new blob containing the data from the + * specified binary font file. + * + * Returns: An #hb_blob_t pointer with the content of the file, + * or %NULL if failed. + * + * Since: 2.8.2 + **/ +hb_blob_t * +hb_blob_create_from_file_or_fail (const char *file_name) { /* Adopted from glib's gmappedfile.c with Matthias Clasen and Allison Lortie permission but changed a lot to suit our need. */ #if defined(HAVE_MMAP) && !defined(HB_NO_MMAP) - hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); + hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); if (unlikely (!file)) return hb_blob_get_empty (); int fd = open (file_name, O_RDONLY | O_BINARY, 0); @@ -601,22 +660,22 @@ hb_blob_create_from_file (const char *file_name) close (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: close (fd); fail_without_close: - free (file); + hb_free (file); #elif defined(_WIN32) && !defined(HB_NO_MMAP) - hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); + hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t)); if (unlikely (!file)) return hb_blob_get_empty (); HANDLE fd; unsigned int size = strlen (file_name) + 1; - wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size); + wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size); if (unlikely (!wchar_file_name)) goto fail_without_close; mbstowcs (wchar_file_name, file_name, size); #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -636,7 +695,7 @@ fail_without_close: OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, nullptr); #endif - free (wchar_file_name); + hb_free (wchar_file_name); if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close; @@ -661,22 +720,22 @@ fail_without_close: if (unlikely (!file->contents)) goto fail; CloseHandle (fd); - return hb_blob_create (file->contents, file->length, - HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, - (hb_destroy_func_t) _hb_mapped_file_destroy); + return hb_blob_create_or_fail (file->contents, file->length, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, (void *) file, + (hb_destroy_func_t) _hb_mapped_file_destroy); fail: CloseHandle (fd); fail_without_close: - free (file); + hb_free (file); #endif /* The following tries to read a file without knowing its size beforehand It's used as a fallback for systems without mmap or to read from pipes */ unsigned long len = 0, allocated = BUFSIZ * 16; - char *data = (char *) malloc (allocated); - if (unlikely (!data)) return hb_blob_get_empty (); + char *data = (char *) hb_malloc (allocated); + if (unlikely (!data)) return nullptr; FILE *fp = fopen (file_name, "rb"); if (unlikely (!fp)) goto fread_fail_without_close; @@ -689,7 +748,7 @@ fail_without_close: /* Don't allocate and go more than ~536MB, our mmap reader still can cover files like that but lets limit our fallback reader */ if (unlikely (allocated > (2 << 28))) goto fread_fail; - char *new_data = (char *) realloc (data, allocated); + char *new_data = (char *) hb_realloc (data, allocated); if (unlikely (!new_data)) goto fread_fail; data = new_data; } @@ -706,13 +765,13 @@ fail_without_close: } fclose (fp); - return hb_blob_create (data, len, HB_MEMORY_MODE_WRITABLE, data, - (hb_destroy_func_t) free); + return hb_blob_create_or_fail (data, len, HB_MEMORY_MODE_WRITABLE, data, + (hb_destroy_func_t) hb_free); fread_fail: fclose (fp); fread_fail_without_close: - free (data); - return hb_blob_get_empty (); + hb_free (data); + return nullptr; } #endif /* !HB_NO_OPEN */ diff --git a/thirdparty/harfbuzz/src/hb-blob.h b/thirdparty/harfbuzz/src/hb-blob.h index 86f12788d2..203f9e19dd 100644 --- a/thirdparty/harfbuzz/src/hb-blob.h +++ b/thirdparty/harfbuzz/src/hb-blob.h @@ -90,9 +90,19 @@ hb_blob_create (const char *data, void *user_data, hb_destroy_func_t destroy); +HB_EXTERN hb_blob_t * +hb_blob_create_or_fail (const char *data, + unsigned int length, + hb_memory_mode_t mode, + void *user_data, + hb_destroy_func_t destroy); + HB_EXTERN hb_blob_t * hb_blob_create_from_file (const char *file_name); +HB_EXTERN hb_blob_t * +hb_blob_create_from_file_or_fail (const char *file_name); + /* Always creates with MEMORY_MODE_READONLY. * Even if the parent blob is writable, we don't * want the user of the sub-blob to be able to diff --git a/thirdparty/harfbuzz/src/hb-blob.hh b/thirdparty/harfbuzz/src/hb-blob.hh index b03dfc1380..a3683a681e 100644 --- a/thirdparty/harfbuzz/src/hb-blob.hh +++ b/thirdparty/harfbuzz/src/hb-blob.hh @@ -88,7 +88,7 @@ struct hb_blob_ptr_t const T * get () const { return b->as (); } hb_blob_t * get_blob () const { return b.get_raw (); } unsigned int get_length () const { return b.get ()->length; } - void destroy () { hb_blob_destroy (b.get ()); b = nullptr; } + void destroy () { hb_blob_destroy (b.get_raw ()); b = nullptr; } private: hb_nonnull_ptr_t b; diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh index 01db295498..e80cfea6e7 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh +++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh @@ -1,29 +1,30 @@ + #line 1 "hb-buffer-deserialize-json.rl" /* -* Copyright © 2013 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 -*/ + * Copyright © 2013 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_BUFFER_DESERIALIZE_JSON_HH #define HB_BUFFER_DESERIALIZE_JSON_HH @@ -31,158 +32,446 @@ #include "hb.hh" -#line 35 "hb-buffer-deserialize-json.hh" +#line 36 "hb-buffer-deserialize-json.hh" static const unsigned char _deserialize_json_trans_keys[] = { - 1u, 0u, 0u, 18u, 0u, 2u, 10u, 15u, - 16u, 17u, 2u, 2u, 0u, 7u, 0u, 6u, - 5u, 6u, 0u, 19u, 0u, 19u, 0u, 19u, - 2u, 2u, 0u, 7u, 0u, 6u, 5u, 6u, - 0u, 19u, 0u, 19u, 14u, 14u, 2u, 2u, - 0u, 7u, 0u, 6u, 0u, 19u, 0u, 19u, - 16u, 17u, 2u, 2u, 0u, 7u, 0u, 6u, - 5u, 6u, 0u, 19u, 0u, 19u, 2u, 2u, - 0u, 7u, 0u, 6u, 5u, 6u, 0u, 19u, - 0u, 19u, 2u, 2u, 0u, 7u, 0u, 6u, - 2u, 8u, 0u, 19u, 2u, 8u, 0u, 19u, - 0u, 19u, 2u, 2u, 0u, 7u, 0u, 6u, - 0u, 19u, 0u, 9u, 0u, 18u, 1u, 0u, - 0u + 0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, + 48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, + 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u, + 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, + 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, + 34u, 92u, 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, + 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0 }; -static const signed char _deserialize_json_char_class[] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, - 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 4, 1, 1, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 7, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 8, 9, 1, 1, 1, - 10, 1, 11, 12, 1, 1, 13, 1, - 1, 1, 1, 14, 1, 1, 1, 1, - 1, 1, 1, 1, 15, 1, 1, 16, - 17, 1, 18, 1, 19, 0 +static const char _deserialize_json_key_spans[] = { + 0, 115, 26, 21, 2, 1, 50, 49, + 10, 117, 117, 117, 1, 50, 49, 10, + 117, 117, 1, 1, 50, 49, 117, 117, + 2, 1, 50, 49, 10, 117, 117, 1, + 50, 49, 10, 117, 117, 1, 50, 49, + 59, 117, 59, 117, 117, 1, 50, 49, + 117, 85, 115, 0 }; static const short _deserialize_json_index_offsets[] = { - 0, 0, 19, 22, 28, 30, 31, 39, - 46, 48, 68, 88, 108, 109, 117, 124, - 126, 146, 166, 167, 168, 176, 183, 203, - 223, 225, 226, 234, 241, 243, 263, 283, - 284, 292, 299, 301, 321, 341, 342, 350, - 357, 364, 384, 391, 411, 431, 432, 440, - 447, 467, 477, 496, 0 + 0, 0, 116, 143, 165, 168, 170, 221, + 271, 282, 400, 518, 636, 638, 689, 739, + 750, 868, 986, 988, 990, 1041, 1091, 1209, + 1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680, + 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2083, + 2133, 2193, 2311, 2371, 2489, 2607, 2609, 2660, + 2710, 2828, 2914, 3030 }; -static const signed char _deserialize_json_indicies[] = { - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 3, 0, 4, 5, 6, - 7, 8, 0, 9, 10, 11, 12, 12, - 0, 0, 0, 0, 0, 0, 13, 13, - 0, 0, 0, 14, 15, 16, 18, 19, - 20, 0, 0, 21, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 22, 23, 0, 0, 3, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 24, - 20, 0, 0, 21, 0, 19, 19, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 22, 25, 25, 0, 0, - 0, 0, 0, 0, 26, 26, 0, 0, - 0, 27, 28, 29, 31, 32, 33, 0, - 0, 34, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 35, 33, 0, 0, 34, 0, 32, - 32, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 35, 36, 37, - 37, 0, 0, 0, 0, 0, 0, 38, - 38, 0, 0, 0, 0, 39, 40, 42, - 0, 0, 43, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 44, 42, 0, 0, 43, 0, - 45, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 44, 46, - 47, 48, 48, 0, 0, 0, 0, 0, - 0, 49, 49, 0, 0, 0, 50, 51, - 52, 54, 55, 56, 0, 0, 57, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 58, 56, - 0, 0, 57, 0, 55, 55, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 58, 59, 59, 0, 0, 0, - 0, 0, 0, 60, 60, 0, 0, 0, - 61, 62, 63, 65, 66, 67, 0, 0, - 68, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 69, 67, 0, 0, 68, 0, 66, 66, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 69, 70, 70, 0, - 0, 0, 0, 0, 0, 71, 71, 0, - 72, 0, 0, 73, 74, 76, 75, 75, - 75, 75, 75, 77, 79, 0, 0, 80, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 81, - 75, 0, 0, 0, 0, 0, 75, 83, - 0, 0, 84, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 85, 83, 0, 0, 84, 0, - 87, 87, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 85, 88, - 88, 0, 0, 0, 0, 0, 0, 89, - 89, 0, 0, 0, 0, 90, 91, 83, - 0, 0, 84, 0, 93, 93, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 85, 94, 0, 0, 95, 0, - 0, 0, 0, 0, 96, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, +static const char _deserialize_json_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 1, 3, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 4, 1, + 5, 1, 6, 7, 1, 1, 8, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 9, 1, 10, 11, + 1, 12, 1, 12, 12, 12, 12, 12, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 12, 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, 13, 1, 13, 13, + 13, 13, 13, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 13, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 14, 1, 1, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 1, + 17, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 1, 19, 19, 19, 19, 19, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 19, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 20, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 21, + 1, 22, 22, 22, 22, 22, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 22, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 23, 1, 19, + 19, 19, 19, 19, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 19, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 20, 1, 1, 1, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 21, 1, 24, 1, 24, + 24, 24, 24, 24, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 24, 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, + 25, 1, 25, 25, 25, 25, 25, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 25, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 26, 1, + 1, 27, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 1, 29, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 1, 31, + 31, 31, 31, 31, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 31, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 32, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 33, 1, 31, 31, 31, + 31, 31, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 31, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 32, 1, 1, 1, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 33, 1, 34, 1, 35, 1, 35, + 35, 35, 35, 35, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 35, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 36, 1, 36, 36, 36, 36, 36, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 36, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 37, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 1, 39, 39, 39, 39, + 39, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 39, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 40, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 41, 1, 39, 39, 39, 39, 39, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 40, 1, 1, + 1, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 41, 1, + 43, 44, 1, 45, 1, 45, 45, 45, + 45, 45, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 45, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 46, 1, + 46, 46, 46, 46, 46, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 46, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 47, 1, 1, 48, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 1, 50, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 1, 52, 52, 52, + 52, 52, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 52, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 53, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 54, 1, 52, 52, 52, 52, 52, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 52, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 53, 1, + 1, 1, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 54, + 1, 55, 1, 55, 55, 55, 55, 55, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 55, 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, 56, 1, 56, 56, + 56, 56, 56, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 56, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 57, 1, 1, 58, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 1, + 60, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 1, 62, 62, 62, 62, 62, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 62, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 63, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 64, + 1, 62, 62, 62, 62, 62, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 62, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 63, 1, 1, 1, + 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 64, 1, 65, + 1, 65, 65, 65, 65, 65, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 65, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 66, 1, 66, 66, 66, 66, + 66, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 66, 1, 67, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 68, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 1, 71, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 72, 70, 73, 73, 73, 73, 73, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 73, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 74, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 75, 1, + 70, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 70, 1, 76, 76, 76, 76, + 76, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 76, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 77, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 78, 1, 76, 76, 76, 76, 76, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 76, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 77, 1, 1, + 1, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 78, 1, + 80, 1, 80, 80, 80, 80, 80, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 80, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 81, 1, 81, 81, 81, + 81, 81, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 81, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 82, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 1, 76, + 76, 76, 76, 76, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 76, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 77, 1, 1, 1, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 78, 1, 85, 85, 85, + 85, 85, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 85, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 86, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 87, 1, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 0 }; -static const signed char _deserialize_json_index_defaults[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 75, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 +static const char _deserialize_json_trans_targs[] = { + 1, 0, 2, 2, 3, 4, 18, 24, + 37, 45, 5, 12, 6, 7, 8, 9, + 11, 9, 11, 10, 2, 49, 10, 49, + 13, 14, 15, 16, 17, 16, 17, 10, + 2, 49, 19, 20, 21, 22, 23, 10, + 2, 49, 23, 25, 31, 26, 27, 28, + 29, 30, 29, 30, 10, 2, 49, 32, + 33, 34, 35, 36, 35, 36, 10, 2, + 49, 38, 39, 40, 43, 44, 40, 41, + 42, 10, 2, 49, 10, 2, 49, 44, + 46, 47, 43, 48, 48, 49, 50, 51 }; -static const signed char _deserialize_json_cond_targs[] = { - 0, 1, 2, 2, 3, 4, 18, 24, - 37, 45, 5, 12, 6, 7, 8, 9, - 11, 8, 9, 11, 10, 2, 49, 10, - 49, 13, 14, 15, 16, 17, 15, 16, - 17, 10, 2, 49, 19, 20, 21, 22, - 23, 22, 10, 2, 49, 23, 25, 31, - 26, 27, 28, 29, 30, 28, 29, 30, - 10, 2, 49, 32, 33, 34, 35, 36, - 34, 35, 36, 10, 2, 49, 38, 39, - 40, 43, 44, 40, 41, 42, 41, 10, - 2, 49, 43, 10, 2, 49, 44, 44, - 46, 47, 43, 48, 48, 48, 49, 50, - 51, 0 -}; - -static const signed char _deserialize_json_cond_actions[] = { - 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2, 2, - 2, 0, 0, 0, 3, 3, 4, 0, - 5, 0, 0, 2, 2, 2, 0, 0, - 0, 6, 6, 7, 0, 0, 0, 2, - 2, 0, 8, 8, 9, 0, 0, 0, - 0, 0, 2, 2, 2, 0, 0, 0, - 10, 10, 11, 0, 0, 2, 2, 2, - 0, 0, 0, 12, 12, 13, 0, 0, - 2, 14, 14, 0, 15, 0, 0, 16, - 16, 17, 0, 18, 18, 19, 0, 15, - 0, 0, 20, 20, 0, 21, 0, 0, - 0, 0 +static const char _deserialize_json_trans_actions[] = { + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, + 2, 0, 0, 3, 3, 4, 0, 5, + 0, 0, 2, 2, 2, 0, 0, 6, + 6, 7, 0, 0, 0, 2, 2, 8, + 8, 9, 0, 0, 0, 0, 0, 2, + 2, 2, 0, 0, 10, 10, 11, 0, + 0, 2, 2, 2, 0, 0, 12, 12, + 13, 0, 0, 2, 14, 14, 0, 15, + 0, 16, 16, 17, 18, 18, 19, 15, + 0, 0, 20, 20, 21, 0, 0, 0 }; static const int deserialize_json_start = 1; @@ -197,411 +486,247 @@ static const int deserialize_json_en_main = 1; static hb_bool_t _hb_buffer_deserialize_json (hb_buffer_t *buffer, -const char *buf, -unsigned int buf_len, -const char **end_ptr, -hb_font_t *font) + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len; - - /* Ensure we have positions. */ - (void) hb_buffer_get_glyph_positions (buffer, nullptr); - - while (p < pe && ISSPACE (*p)) - p++; - if (p < pe && *p == (buffer->len ? ',' : '[')) - { - *end_ptr = ++p; - } - - const char *tok = nullptr; - int cs; - hb_glyph_info_t info = {0}; - hb_glyph_position_t pos = {0}; - -#line 223 "hb-buffer-deserialize-json.hh" + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, nullptr); + + while (p < pe && ISSPACE (*p)) + p++; + if (p < pe && *p == (buffer->len ? ',' : '[')) + { + *end_ptr = ++p; + } + + const char *tok = nullptr; + int cs; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; + +#line 512 "hb-buffer-deserialize-json.hh" { - cs = (int)deserialize_json_start; + cs = deserialize_json_start; } - -#line 228 "hb-buffer-deserialize-json.hh" + +#line 517 "hb-buffer-deserialize-json.hh" { - unsigned int _trans = 0; - const unsigned char * _keys; - const signed char * _inds; - int _ic; - _resume: {} - if ( p == pe ) - goto _out; - _keys = ( _deserialize_json_trans_keys + ((cs<<1))); - _inds = ( _deserialize_json_indicies + (_deserialize_json_index_offsets[cs])); - - if ( ( (*( p))) <= 125 && ( (*( p))) >= 9 ) { - _ic = (int)_deserialize_json_char_class[(int)( (*( p))) - 9]; - if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) ) - _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); - else - _trans = (unsigned int)_deserialize_json_index_defaults[cs]; - } - else { - _trans = (unsigned int)_deserialize_json_index_defaults[cs]; - } - - cs = (int)_deserialize_json_cond_targs[_trans]; - - if ( _deserialize_json_cond_actions[_trans] != 0 ) { - - switch ( _deserialize_json_cond_actions[_trans] ) { - case 1: { - { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_json_trans_keys + (cs<<1); + _inds = _deserialize_json_indicies + _deserialize_json_index_offsets[cs]; + + _slen = _deserialize_json_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_json_trans_targs[_trans]; + + if ( _deserialize_json_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_json_trans_actions[_trans] ) { + case 1: #line 38 "hb-buffer-deserialize-json.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 264 "hb-buffer-deserialize-json.hh" - - - break; - } - case 5: { - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + break; + case 5: #line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 280 "hb-buffer-deserialize-json.hh" - - - break; - } - case 2: { - { -#line 51 "hb-buffer-deserialize-json.rl" - - tok = p; - } - -#line 292 "hb-buffer-deserialize-json.hh" - - - break; - } - case 15: { - { -#line 55 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 302 "hb-buffer-deserialize-json.hh" - - - break; - } - case 21: { - { -#line 56 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 312 "hb-buffer-deserialize-json.hh" - - - break; - } - case 16: { - { -#line 58 "hb-buffer-deserialize-json.rl" - - /* TODO Unescape \" and \\ if found. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 328 "hb-buffer-deserialize-json.hh" - - - break; - } - case 18: { - { -#line 66 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.codepoint)) return false; } - -#line 338 "hb-buffer-deserialize-json.hh" - - - break; - } - case 8: { - { -#line 67 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 348 "hb-buffer-deserialize-json.hh" - - - break; - } - case 10: { - { -#line 68 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_offset )) return false; } - -#line 358 "hb-buffer-deserialize-json.hh" - - - break; - } - case 12: { - { -#line 69 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 368 "hb-buffer-deserialize-json.hh" - - - break; - } - case 3: { - { -#line 70 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 378 "hb-buffer-deserialize-json.hh" - - - break; - } - case 6: { - { -#line 71 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_advance)) return false; } - -#line 388 "hb-buffer-deserialize-json.hh" - - - break; - } - case 14: { - { -#line 51 "hb-buffer-deserialize-json.rl" - - tok = p; - } - -#line 400 "hb-buffer-deserialize-json.hh" - - { -#line 55 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 406 "hb-buffer-deserialize-json.hh" - - - break; - } - case 20: { - { -#line 51 "hb-buffer-deserialize-json.rl" - - tok = p; - } - -#line 418 "hb-buffer-deserialize-json.hh" - - { -#line 56 "hb-buffer-deserialize-json.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 424 "hb-buffer-deserialize-json.hh" - - - break; - } - case 17: { - { -#line 58 "hb-buffer-deserialize-json.rl" - - /* TODO Unescape \" and \\ if found. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 440 "hb-buffer-deserialize-json.hh" - - { -#line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 452 "hb-buffer-deserialize-json.hh" - - - break; - } - case 19: { - { -#line 66 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.codepoint)) return false; } - -#line 462 "hb-buffer-deserialize-json.hh" - - { -#line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 474 "hb-buffer-deserialize-json.hh" - - - break; - } - case 9: { - { -#line 67 "hb-buffer-deserialize-json.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 484 "hb-buffer-deserialize-json.hh" - - { -#line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 496 "hb-buffer-deserialize-json.hh" - - - break; - } - case 11: { - { -#line 68 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_offset )) return false; } - -#line 506 "hb-buffer-deserialize-json.hh" - - { -#line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 518 "hb-buffer-deserialize-json.hh" - - - break; - } - case 13: { - { -#line 69 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 528 "hb-buffer-deserialize-json.hh" - - { -#line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 540 "hb-buffer-deserialize-json.hh" - - - break; - } - case 4: { - { -#line 70 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 550 "hb-buffer-deserialize-json.hh" - - { -#line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 562 "hb-buffer-deserialize-json.hh" - - - break; - } - case 7: { - { -#line 71 "hb-buffer-deserialize-json.rl" - if (!parse_int (tok, p, &pos.y_advance)) return false; } - -#line 572 "hb-buffer-deserialize-json.hh" - - { -#line 43 "hb-buffer-deserialize-json.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 584 "hb-buffer-deserialize-json.hh" - - - break; - } - } - - } - - if ( cs != 0 ) { - p += 1; - goto _resume; - } - _out: {} - } - -#line 136 "hb-buffer-deserialize-json.rl" - - + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; *end_ptr = p; - - return p == pe && *(p-1) != ']'; +} + break; + case 2: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} + break; + case 15: +#line 55 "hb-buffer-deserialize-json.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 21: +#line 56 "hb-buffer-deserialize-json.rl" + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 16: +#line 58 "hb-buffer-deserialize-json.rl" + { + /* TODO Unescape \" and \\ if found. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 18: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } + break; + case 8: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 10: +#line 68 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 12: +#line 69 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 3: +#line 70 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 6: +#line 71 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } + break; + case 14: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} +#line 55 "hb-buffer-deserialize-json.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 20: +#line 51 "hb-buffer-deserialize-json.rl" + { + tok = p; +} +#line 56 "hb-buffer-deserialize-json.rl" + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 17: +#line 58 "hb-buffer-deserialize-json.rl" + { + /* TODO Unescape \" and \\ if found. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 19: +#line 66 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.codepoint)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 9: +#line 67 "hb-buffer-deserialize-json.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 68 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 13: +#line 69 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 4: +#line 70 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: +#line 71 "hb-buffer-deserialize-json.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-json.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 713 "hb-buffer-deserialize-json.hh" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + _out: {} + } + +#line 136 "hb-buffer-deserialize-json.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; } #endif /* HB_BUFFER_DESERIALIZE_JSON_HH */ diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh index fb36f56015..b599e9667c 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh +++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh @@ -1,29 +1,30 @@ + #line 1 "hb-buffer-deserialize-text.rl" /* -* Copyright © 2013 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 -*/ + * Copyright © 2013 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_BUFFER_DESERIALIZE_TEXT_HH #define HB_BUFFER_DESERIALIZE_TEXT_HH @@ -31,143 +32,366 @@ #include "hb.hh" -#line 35 "hb-buffer-deserialize-text.hh" +#line 36 "hb-buffer-deserialize-text.hh" static const unsigned char _deserialize_text_trans_keys[] = { - 1u, 0u, 0u, 13u, 12u, 12u, 2u, 2u, - 5u, 11u, 0u, 12u, 5u, 6u, 4u, 6u, - 5u, 6u, 5u, 6u, 4u, 6u, 5u, 6u, - 3u, 3u, 4u, 6u, 5u, 6u, 3u, 6u, - 2u, 16u, 4u, 6u, 5u, 6u, 0u, 16u, - 0u, 16u, 1u, 0u, 0u, 12u, 0u, 16u, - 0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u, - 0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u, - 0u, 16u, 0u, 16u, 0u, 16u, 0u, 16u, - 0u, 16u, 0u + 0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u, + 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u, + 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, + 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 0 }; -static const signed char _deserialize_text_char_class[] = { - 0, 0, 0, 0, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 3, 4, 1, 1, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 1, 1, 7, 8, 9, 1, 10, - 11, 11, 11, 11, 11, 11, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 12, 1, 1, 1, - 1, 1, 13, 14, 15, 1, 1, 1, - 11, 11, 11, 11, 11, 11, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 16, 0 +static const char _deserialize_text_key_spans[] = { + 0, 83, 1, 1, 55, 77, 10, 13, + 10, 10, 13, 10, 1, 13, 10, 14, + 82, 13, 10, 116, 116, 0, 77, 116, + 116, 116, 116, 116, 116, 116, 116, 116, + 116, 116, 116, 116, 116 }; static const short _deserialize_text_index_offsets[] = { - 0, 0, 14, 15, 16, 23, 36, 38, - 41, 43, 45, 48, 50, 51, 54, 56, - 60, 75, 78, 80, 97, 114, 114, 127, - 144, 161, 178, 195, 212, 229, 246, 263, - 280, 297, 314, 331, 348, 0 + 0, 0, 84, 86, 88, 144, 222, 233, + 247, 258, 269, 283, 294, 296, 310, 321, + 336, 419, 433, 444, 561, 678, 679, 757, + 874, 991, 1108, 1225, 1342, 1459, 1576, 1693, + 1810, 1927, 2044, 2161, 2278 }; -static const signed char _deserialize_text_indicies[] = { - 1, 0, 0, 0, 0, 0, 0, 2, - 0, 0, 0, 0, 0, 3, 4, 6, - 7, 7, 0, 0, 0, 0, 7, 8, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 4, 10, 11, 13, 14, - 15, 17, 18, 20, 21, 23, 24, 25, - 27, 28, 29, 31, 32, 33, 35, 36, - 29, 0, 28, 28, 38, 38, 0, 0, - 0, 0, 38, 0, 38, 0, 0, 0, - 38, 38, 38, 40, 41, 42, 44, 45, - 47, 0, 0, 0, 0, 48, 48, 0, - 49, 50, 0, 48, 0, 0, 0, 0, - 51, 52, 0, 0, 0, 0, 0, 0, - 0, 0, 53, 0, 0, 0, 0, 0, - 0, 54, 8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 4, 56, - 0, 0, 0, 0, 0, 0, 0, 0, - 57, 0, 0, 0, 0, 0, 0, 58, - 56, 0, 0, 0, 0, 60, 60, 0, - 0, 57, 0, 0, 0, 0, 0, 0, - 58, 63, 62, 64, 0, 62, 62, 62, - 62, 65, 62, 66, 62, 62, 62, 67, - 68, 69, 71, 38, 72, 0, 38, 38, - 38, 38, 73, 38, 74, 38, 38, 38, - 37, 75, 76, 78, 0, 0, 79, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 80, 81, 82, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 53, 83, 84, 62, 64, - 0, 62, 62, 62, 62, 65, 62, 66, - 62, 62, 62, 67, 68, 69, 86, 0, - 87, 0, 0, 0, 0, 0, 0, 0, - 88, 0, 0, 0, 0, 57, 89, 91, - 0, 92, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 93, 94, - 91, 0, 92, 0, 0, 36, 36, 0, - 0, 0, 0, 0, 0, 0, 0, 93, - 94, 86, 0, 87, 0, 0, 97, 97, - 0, 0, 0, 88, 0, 0, 0, 0, - 57, 89, 99, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 100, 101, 99, 0, 0, 0, 0, - 45, 45, 0, 0, 0, 0, 0, 0, - 0, 0, 100, 101, 78, 0, 0, 79, - 0, 18, 18, 0, 0, 0, 0, 0, - 0, 0, 0, 80, 81, 0 +static const char _deserialize_text_indicies[] = { + 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 4, 1, 5, + 1, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 1, 1, 1, 1, + 1, 1, 6, 6, 6, 6, 6, 6, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 6, 6, 6, 6, 6, 6, + 1, 7, 7, 7, 7, 7, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 7, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 4, 1, 8, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 1, 10, 1, 1, 11, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 1, + 13, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 1, 15, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 1, 17, 1, + 1, 18, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 1, 20, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 1, 22, + 1, 23, 1, 1, 24, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 1, 26, + 27, 27, 27, 27, 27, 27, 27, 27, + 27, 1, 22, 1, 1, 1, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, + 1, 28, 28, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 28, 1, 1, 28, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 28, 28, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 28, 1, 29, 1, 1, 30, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 1, 32, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 1, 34, 34, 34, + 34, 34, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 34, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 35, 35, 35, 35, + 35, 35, 35, 35, 35, 35, 1, 1, + 1, 36, 37, 1, 1, 35, 35, 35, + 35, 35, 35, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 35, 35, 35, + 35, 35, 35, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 38, 1, 39, 39, 39, 39, 39, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 39, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 40, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 41, 1, 1, + 7, 7, 7, 7, 7, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 7, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 4, 1, 42, 42, + 42, 42, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 42, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 43, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 44, 1, 42, 42, 42, 42, 42, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 1, 1, 1, 1, + 43, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 44, 1, + 47, 47, 47, 47, 47, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 47, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 48, 1, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 49, 46, 46, 50, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 51, 52, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 53, 46, 54, 54, 54, + 54, 54, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 54, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 55, + 1, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 56, 28, 28, 57, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 58, 59, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, + 60, 28, 61, 61, 61, 61, 61, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 61, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 62, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 63, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 64, 1, 65, + 65, 65, 65, 65, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 65, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 40, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 66, 1, 67, 67, 67, 67, + 67, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 67, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 48, 1, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 49, 46, 46, 50, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 51, + 52, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 46, + 46, 46, 46, 46, 46, 46, 46, 53, + 46, 68, 68, 68, 68, 68, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 68, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 69, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 70, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 43, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 71, 1, 72, 72, + 72, 72, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 72, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 73, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 74, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 75, 1, 72, 72, 72, 72, 72, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 72, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 73, 1, 1, + 1, 1, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 74, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 75, 1, + 68, 68, 68, 68, 68, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 68, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 69, 1, 1, 1, 1, 76, + 76, 76, 76, 76, 76, 76, 76, 76, + 76, 1, 1, 1, 1, 1, 1, 70, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 43, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 71, 1, 77, 77, 77, + 77, 77, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 77, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 78, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 79, 1, 77, 77, 77, 77, 77, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 77, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 78, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 79, 1, 61, + 61, 61, 61, 61, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 61, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 62, 1, 1, 1, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 63, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 64, 1, 0 }; -static const signed char _deserialize_text_index_defaults[] = { - 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, 62, 38, 0, 0, 62, 0, 0, - 0, 0, 0, 0, 0, 0 +static const char _deserialize_text_trans_targs[] = { + 1, 0, 2, 25, 3, 4, 19, 5, + 23, 24, 8, 27, 36, 27, 36, 30, + 33, 11, 12, 15, 12, 15, 13, 14, + 31, 32, 31, 32, 26, 18, 34, 35, + 34, 35, 20, 19, 6, 21, 22, 20, + 21, 22, 20, 21, 22, 24, 26, 26, + 7, 9, 10, 16, 21, 29, 26, 7, + 9, 10, 16, 21, 29, 28, 17, 21, + 29, 28, 29, 29, 28, 7, 10, 29, + 28, 7, 21, 29, 33, 28, 21, 29 }; -static const signed char _deserialize_text_cond_targs[] = { - 0, 1, 2, 25, 3, 3, 4, 19, - 5, 6, 23, 24, 7, 8, 27, 36, - 8, 27, 36, 9, 30, 33, 10, 11, - 12, 15, 11, 12, 15, 13, 13, 14, - 31, 32, 14, 31, 32, 16, 26, 17, - 18, 34, 35, 18, 34, 35, 19, 20, - 19, 6, 21, 22, 20, 21, 22, 23, - 20, 21, 22, 24, 24, 25, 26, 26, - 7, 9, 10, 16, 21, 29, 26, 26, - 7, 9, 10, 21, 29, 27, 28, 17, - 21, 29, 28, 29, 29, 30, 28, 7, - 10, 29, 31, 28, 7, 21, 29, 32, - 33, 33, 34, 28, 21, 29, 35, 36, - 0 +static const char _deserialize_text_trans_actions[] = { + 0, 0, 0, 0, 1, 0, 2, 0, + 2, 2, 3, 4, 4, 5, 5, 4, + 4, 3, 3, 3, 0, 0, 6, 3, + 4, 4, 5, 5, 5, 3, 4, 4, + 5, 5, 7, 8, 9, 7, 7, 0, + 0, 0, 10, 10, 10, 8, 12, 13, + 14, 14, 14, 15, 11, 11, 17, 18, + 18, 18, 0, 16, 16, 19, 20, 19, + 19, 0, 0, 13, 10, 21, 21, 10, + 22, 23, 22, 22, 5, 24, 24, 24 }; -static const signed char _deserialize_text_cond_actions[] = { - 0, 0, 0, 0, 1, 0, 0, 2, - 0, 0, 2, 2, 0, 3, 4, 4, - 0, 5, 5, 0, 4, 4, 0, 3, - 3, 3, 0, 0, 0, 6, 0, 3, - 4, 4, 0, 5, 5, 0, 5, 0, - 3, 4, 4, 0, 5, 5, 7, 7, - 8, 9, 7, 7, 0, 0, 0, 10, - 10, 10, 10, 10, 8, 11, 12, 13, - 14, 14, 14, 15, 11, 11, 16, 17, - 18, 18, 18, 16, 16, 19, 19, 20, - 19, 19, 0, 0, 13, 10, 10, 21, - 21, 10, 22, 22, 23, 22, 22, 22, - 10, 5, 24, 24, 24, 24, 24, 19, - 0 -}; - -static const signed char _deserialize_text_eof_trans[] = { - 1, 2, 3, 6, 7, 9, 10, 13, - 17, 20, 23, 27, 28, 31, 35, 29, - 38, 40, 44, 47, 53, 54, 55, 56, - 60, 62, 71, 78, 83, 70, 86, 91, - 96, 97, 99, 103, 104, 0 +static const char _deserialize_text_eof_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 0, 0, 10, + 10, 11, 16, 19, 0, 11, 10, 22, + 22, 10, 24, 24, 19 }; static const int deserialize_text_start = 1; @@ -182,583 +406,448 @@ static const int deserialize_text_en_main = 1; static hb_bool_t _hb_buffer_deserialize_text (hb_buffer_t *buffer, -const char *buf, -unsigned int buf_len, -const char **end_ptr, -hb_font_t *font) + const char *buf, + unsigned int buf_len, + const char **end_ptr, + hb_font_t *font) { - const char *p = buf, *pe = buf + buf_len; - - /* Ensure we have positions. */ - (void) hb_buffer_get_glyph_positions (buffer, nullptr); - - while (p < pe && ISSPACE (*p)) - p++; - - const char *eof = pe, *tok = nullptr; - int cs; - hb_glyph_info_t info = {0}; - hb_glyph_position_t pos = {0}; - -#line 204 "hb-buffer-deserialize-text.hh" + const char *p = buf, *pe = buf + buf_len; + + /* Ensure we have positions. */ + (void) hb_buffer_get_glyph_positions (buffer, nullptr); + + while (p < pe && ISSPACE (*p)) + p++; + + const char *eof = pe, *tok = nullptr; + int cs; + hb_glyph_info_t info = {0}; + hb_glyph_position_t pos = {0}; + +#line 428 "hb-buffer-deserialize-text.hh" { - cs = (int)deserialize_text_start; + cs = deserialize_text_start; } - -#line 209 "hb-buffer-deserialize-text.hh" + +#line 433 "hb-buffer-deserialize-text.hh" { - unsigned int _trans = 0; - const unsigned char * _keys; - const signed char * _inds; - int _ic; - _resume: {} - if ( p == pe && p != eof ) - goto _out; - if ( p == eof ) { - if ( _deserialize_text_eof_trans[cs] > 0 ) { - _trans = (unsigned int)_deserialize_text_eof_trans[cs] - 1; - } - } - else { - _keys = ( _deserialize_text_trans_keys + ((cs<<1))); - _inds = ( _deserialize_text_indicies + (_deserialize_text_index_offsets[cs])); - - if ( ( (*( p))) <= 124 && ( (*( p))) >= 9 ) { - _ic = (int)_deserialize_text_char_class[(int)( (*( p))) - 9]; - if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) ) - _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); - else - _trans = (unsigned int)_deserialize_text_index_defaults[cs]; - } - else { - _trans = (unsigned int)_deserialize_text_index_defaults[cs]; - } - - } - cs = (int)_deserialize_text_cond_targs[_trans]; - - if ( _deserialize_text_cond_actions[_trans] != 0 ) { - - switch ( _deserialize_text_cond_actions[_trans] ) { - case 1: { - { + int _slen; + int _trans; + const unsigned char *_keys; + const char *_inds; + if ( p == pe ) + goto _test_eof; + if ( cs == 0 ) + goto _out; +_resume: + _keys = _deserialize_text_trans_keys + (cs<<1); + _inds = _deserialize_text_indicies + _deserialize_text_index_offsets[cs]; + + _slen = _deserialize_text_key_spans[cs]; + _trans = _inds[ _slen > 0 && _keys[0] <=(*p) && + (*p) <= _keys[1] ? + (*p) - _keys[0] : _slen ]; + + cs = _deserialize_text_trans_targs[_trans]; + + if ( _deserialize_text_trans_actions[_trans] == 0 ) + goto _again; + + switch ( _deserialize_text_trans_actions[_trans] ) { + case 1: #line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 252 "hb-buffer-deserialize-text.hh" - - - break; - } - case 3: { - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} + break; + case 3: #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 264 "hb-buffer-deserialize-text.hh" - - - break; - } - case 5: { - { + { + tok = p; +} + break; + case 5: #line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 274 "hb-buffer-deserialize-text.hh" - - - break; - } - case 8: { - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 8: #line 56 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 284 "hb-buffer-deserialize-text.hh" - - - break; - } - case 18: { - { + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 18: #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 300 "hb-buffer-deserialize-text.hh" - - - break; - } - case 9: { - { + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 9: #line 66 "hb-buffer-deserialize-text.rl" - if (!parse_hex (tok, p, &info.codepoint )) return false; } - -#line 310 "hb-buffer-deserialize-text.hh" - - - break; - } - case 21: { - { + {if (!parse_hex (tok, p, &info.codepoint )) return false; } + break; + case 21: #line 68 "hb-buffer-deserialize-text.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 320 "hb-buffer-deserialize-text.hh" - - - break; - } - case 6: { - { + { if (!parse_uint (tok, p, &info.cluster )) return false; } + break; + case 6: #line 69 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.x_offset )) return false; } - -#line 330 "hb-buffer-deserialize-text.hh" - - - break; - } - case 23: { - { + { if (!parse_int (tok, p, &pos.x_offset )) return false; } + break; + case 23: #line 70 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 340 "hb-buffer-deserialize-text.hh" - - - break; - } - case 20: { - { + { if (!parse_int (tok, p, &pos.y_offset )) return false; } + break; + case 20: #line 71 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 350 "hb-buffer-deserialize-text.hh" - - - break; - } - case 15: { - { + { if (!parse_int (tok, p, &pos.x_advance)) return false; } + break; + case 15: #line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 363 "hb-buffer-deserialize-text.hh" - - { + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 371 "hb-buffer-deserialize-text.hh" - - - break; - } - case 4: { - { + { + tok = p; +} + break; + case 4: #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 383 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 389 "hb-buffer-deserialize-text.hh" - - - break; - } - case 2: { - { + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 2: #line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 401 "hb-buffer-deserialize-text.hh" - - { + { + tok = p; +} #line 56 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_unicode ())) return false; } - -#line 407 "hb-buffer-deserialize-text.hh" - - - break; - } - case 16: { - { + { if (unlikely (!buffer->ensure_unicode ())) return false; } + break; + case 16: #line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 423 "hb-buffer-deserialize-text.hh" - - { + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} #line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 435 "hb-buffer-deserialize-text.hh" - - - break; - } - case 7: { - { -#line 66 "hb-buffer-deserialize-text.rl" - if (!parse_hex (tok, p, &info.codepoint )) return false; } - -#line 445 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 457 "hb-buffer-deserialize-text.hh" - - - break; - } - case 10: { - { -#line 68 "hb-buffer-deserialize-text.rl" - if (!parse_uint (tok, p, &info.cluster )) return false; } - -#line 467 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 479 "hb-buffer-deserialize-text.hh" - - - break; - } - case 22: { - { -#line 70 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.y_offset )) return false; } - -#line 489 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 501 "hb-buffer-deserialize-text.hh" - - - break; - } - case 19: { - { -#line 71 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.x_advance)) return false; } - -#line 511 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 523 "hb-buffer-deserialize-text.hh" - - - break; - } - case 24: { - { -#line 72 "hb-buffer-deserialize-text.rl" - if (!parse_int (tok, p, &pos.y_advance)) return false; } - -#line 533 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 545 "hb-buffer-deserialize-text.hh" - - - break; - } - case 12: { - { -#line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 558 "hb-buffer-deserialize-text.hh" - - { -#line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 566 "hb-buffer-deserialize-text.hh" - - { -#line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 572 "hb-buffer-deserialize-text.hh" - - - break; - } - case 14: { - { -#line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 585 "hb-buffer-deserialize-text.hh" - - { -#line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 593 "hb-buffer-deserialize-text.hh" - - { -#line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 605 "hb-buffer-deserialize-text.hh" - - - break; - } - case 17: { - { -#line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 621 "hb-buffer-deserialize-text.hh" - - { -#line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 627 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 639 "hb-buffer-deserialize-text.hh" - - - break; - } - case 11: { - { -#line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 652 "hb-buffer-deserialize-text.hh" - - { -#line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 660 "hb-buffer-deserialize-text.hh" - - { -#line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 672 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 684 "hb-buffer-deserialize-text.hh" - - - break; - } - case 13: { - { -#line 38 "hb-buffer-deserialize-text.rl" - - memset (&info, 0, sizeof (info)); - memset (&pos , 0, sizeof (pos )); - } - -#line 697 "hb-buffer-deserialize-text.hh" - - { -#line 51 "hb-buffer-deserialize-text.rl" - - tok = p; - } - -#line 705 "hb-buffer-deserialize-text.hh" - - { -#line 58 "hb-buffer-deserialize-text.rl" - - /* TODO Unescape delimeters. */ - if (!hb_font_glyph_from_string (font, - tok, p - tok, - &info.codepoint)) - return false; - } - -#line 717 "hb-buffer-deserialize-text.hh" - - { -#line 55 "hb-buffer-deserialize-text.rl" - if (unlikely (!buffer->ensure_glyphs ())) return false; } - -#line 723 "hb-buffer-deserialize-text.hh" - - { -#line 43 "hb-buffer-deserialize-text.rl" - - buffer->add_info (info); - if (unlikely (!buffer->successful)) - return false; - buffer->pos[buffer->len - 1] = pos; - *end_ptr = p; - } - -#line 735 "hb-buffer-deserialize-text.hh" - - - break; - } - } - - } - - if ( p == eof ) { - if ( cs >= 19 ) - goto _out; - } - else { - if ( cs != 0 ) { - p += 1; - goto _resume; - } - } - _out: {} - } - -#line 138 "hb-buffer-deserialize-text.rl" - - + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; *end_ptr = p; - - return p == pe && *(p-1) != ']'; +} + break; + case 7: +#line 66 "hb-buffer-deserialize-text.rl" + {if (!parse_hex (tok, p, &info.codepoint )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 10: +#line 68 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 22: +#line 70 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 19: +#line 71 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 24: +#line 72 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 12: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 55 "hb-buffer-deserialize-text.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } + break; + case 14: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} + break; + case 17: +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 55 "hb-buffer-deserialize-text.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 13: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 55 "hb-buffer-deserialize-text.rl" + { if (unlikely (!buffer->ensure_glyphs ())) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 722 "hb-buffer-deserialize-text.hh" + } + +_again: + if ( cs == 0 ) + goto _out; + if ( ++p != pe ) + goto _resume; + _test_eof: {} + if ( p == eof ) + { + switch ( _deserialize_text_eof_actions[cs] ) { + case 16: +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 7: +#line 66 "hb-buffer-deserialize-text.rl" + {if (!parse_hex (tok, p, &info.codepoint )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 10: +#line 68 "hb-buffer-deserialize-text.rl" + { if (!parse_uint (tok, p, &info.cluster )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 22: +#line 70 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_offset )) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 19: +#line 71 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.x_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 24: +#line 72 "hb-buffer-deserialize-text.rl" + { if (!parse_int (tok, p, &pos.y_advance)) return false; } +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; + case 11: +#line 38 "hb-buffer-deserialize-text.rl" + { + memset (&info, 0, sizeof (info)); + memset (&pos , 0, sizeof (pos )); +} +#line 51 "hb-buffer-deserialize-text.rl" + { + tok = p; +} +#line 58 "hb-buffer-deserialize-text.rl" + { + /* TODO Unescape delimeters. */ + if (!hb_font_glyph_from_string (font, + tok, p - tok, + &info.codepoint)) + return false; +} +#line 43 "hb-buffer-deserialize-text.rl" + { + buffer->add_info (info); + if (unlikely (!buffer->successful)) + return false; + buffer->pos[buffer->len - 1] = pos; + *end_ptr = p; +} + break; +#line 839 "hb-buffer-deserialize-text.hh" + } + } + + _out: {} + } + +#line 138 "hb-buffer-deserialize-text.rl" + + + *end_ptr = p; + + return p == pe && *(p-1) != ']'; } #endif /* HB_BUFFER_DESERIALIZE_TEXT_HH */ diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index 8cad6ab8e6..c6591ca230 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -96,14 +96,15 @@ hb_segment_properties_hash (const hb_segment_properties_t *p) * As an optimization, both info and out_info may point to the * same piece of memory, which is owned by info. This remains the * case as long as out_len doesn't exceed i at any time. - * In that case, swap_buffers() is no-op and the glyph operations operate - * mostly in-place. + * In that case, swap_buffers() is mostly no-op and the glyph operations + * operate mostly in-place. * * As soon as out_info gets longer than info, out_info is moved over - * to an alternate buffer (which we reuse the pos buffer for!), and its + * to an alternate buffer (which we reuse the pos buffer for), and its * current contents (out_len entries) are copied to the new place. + * * This should all remain transparent to the user. swap_buffers() then - * switches info and out_info. + * switches info over to out_info and does housekeeping. */ @@ -136,8 +137,8 @@ hb_buffer_t::enlarge (unsigned int size) if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0])))) goto done; - new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0])); - new_info = (hb_glyph_info_t *) realloc (info, new_allocated * sizeof (info[0])); + new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0])); + new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0])); done: if (unlikely (!new_pos || !new_info)) @@ -281,22 +282,13 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info) } -void -hb_buffer_t::remove_output () -{ - have_output = false; - have_positions = false; - - out_len = 0; - out_info = info; -} - void hb_buffer_t::clear_output () { have_output = true; have_positions = false; + idx = 0; out_len = 0; out_info = info; } @@ -316,29 +308,23 @@ hb_buffer_t::clear_positions () void hb_buffer_t::swap_buffers () { - if (unlikely (!successful)) return; + assert (have_output); assert (idx <= len); - if (unlikely (!next_glyphs (len - idx))) return; - assert (have_output); - have_output = false; + if (unlikely (!successful || !next_glyphs (len - idx))) + goto reset; if (out_info != info) { - hb_glyph_info_t *tmp; - tmp = info; + pos = (hb_glyph_position_t *) info; info = out_info; - out_info = tmp; - - pos = (hb_glyph_position_t *) out_info; } - - unsigned int tmp; - tmp = len; len = out_len; - out_len = tmp; +reset: + have_output = false; + out_len = 0; idx = 0; } @@ -373,12 +359,11 @@ hb_buffer_t::move_to (unsigned int i) /* This will blow in our face if memory allocation fails later * in this same lookup... * - * We used to shift with extra 32 items, instead of the 0 below. + * We used to shift with extra 32 items. * But that would leave empty slots in the buffer in case of allocation - * failures. Setting to zero for now to avoid other problems (see - * comments in shift_forward(). This can cause O(N^2) behavior more - * severely than adding 32 empty slots can... */ - if (unlikely (idx < count && !shift_forward (count + 0))) return false; + * failures. See comments in shift_forward(). This can cause O(N^2) + * behavior more severely than adding 32 empty slots can... */ + if (unlikely (idx < count && !shift_forward (count - idx))) return false; assert (idx >= count); @@ -630,7 +615,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) = HB_BUFFER_CONTENT_TYPE_INVALID, HB_SEGMENT_PROPERTIES_DEFAULT, false, /* successful */ - true, /* have_output */ + false, /* have_output */ true /* have_positions */ /* Zero is good enough for everything else. */ @@ -717,14 +702,14 @@ hb_buffer_destroy (hb_buffer_t *buffer) hb_unicode_funcs_destroy (buffer->unicode); - free (buffer->info); - free (buffer->pos); + hb_free (buffer->info); + hb_free (buffer->pos); #ifndef HB_NO_BUFFER_MESSAGE if (buffer->message_destroy) buffer->message_destroy (buffer->message_data); #endif - free (buffer); + hb_free (buffer); } /** @@ -1363,6 +1348,11 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer, * Returns @buffer glyph position array. Returned pointer * is valid as long as @buffer contents are not modified. * + * If buffer did not have positions before, the positions will be + * initialized to zeros, unless this function is called from + * within a buffer message callback (see hb_buffer_set_message_func()), + * in which case %NULL is returned. + * * Return value: (transfer none) (array length=length): * The @buffer glyph position array. * The value valid as long as buffer has not been modified. @@ -1373,12 +1363,17 @@ hb_glyph_position_t * hb_buffer_get_glyph_positions (hb_buffer_t *buffer, unsigned int *length) { - if (!buffer->have_positions) - buffer->clear_positions (); - if (length) *length = buffer->len; + if (!buffer->have_positions) + { + if (unlikely (buffer->message_depth)) + return nullptr; + + buffer->clear_positions (); + } + return (hb_glyph_position_t *) buffer->pos; } @@ -1760,6 +1755,28 @@ hb_buffer_append (hb_buffer_t *buffer, 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])); + + if (source->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) + { + /* See similar logic in add_utf. */ + + /* pre-context */ + if (!orig_len && start + source->context_len[0] > 0) + { + buffer->clear_context (0); + while (start > 0 && buffer->context_len[0] < buffer->CONTEXT_LENGTH) + buffer->context[0][buffer->context_len[0]++] = source->info[--start].codepoint; + for (auto i = 0u; i < source->context_len[0] && buffer->context_len[0] < buffer->CONTEXT_LENGTH; i++) + buffer->context[0][buffer->context_len[0]++] = source->context[0][i]; + } + + /* post-context */ + buffer->clear_context (1); + while (end < source->len && buffer->context_len[1] < buffer->CONTEXT_LENGTH) + buffer->context[1][buffer->context_len[1]++] = source->info[end++].codepoint; + for (auto i = 0u; i < source->context_len[1] && buffer->context_len[1] < buffer->CONTEXT_LENGTH; i++) + buffer->context[1][buffer->context_len[1]++] = source->context[1][i]; + } } diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index 8b432b5f96..8635ebd35f 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -107,7 +107,7 @@ struct hb_buffer_t unsigned int idx; /* Cursor into ->info and ->pos arrays */ unsigned int len; /* Length of ->info and ->pos arrays */ - unsigned int out_len; /* Length of ->out array if have_output */ + unsigned int out_len; /* Length of ->out_info array if have_output */ unsigned int allocated; /* Length of allocated arrays */ hb_glyph_info_t *info; @@ -128,6 +128,9 @@ struct hb_buffer_t hb_buffer_message_func_t message_func; void *message_data; hb_destroy_func_t message_destroy; + unsigned message_depth; /* How deeply are we inside a message callback? */ +#else + static constexpr unsigned message_depth = 0u; #endif /* Internal debugging. */ @@ -186,13 +189,10 @@ struct hb_buffer_t hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; } hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; } - HB_NODISCARD bool has_separate_output () const { return info != out_info; } - - HB_INTERNAL void reset (); HB_INTERNAL void clear (); - unsigned int backtrack_len () const { return have_output? out_len : idx; } + unsigned int backtrack_len () const { return have_output ? out_len : idx; } unsigned int lookahead_len () const { return len - idx; } unsigned int next_serial () { return serial++; } @@ -206,7 +206,6 @@ struct hb_buffer_t HB_INTERNAL void guess_segment_properties (); HB_INTERNAL void swap_buffers (); - HB_INTERNAL void remove_output (); HB_INTERNAL void clear_output (); HB_INTERNAL void clear_positions (); @@ -400,10 +399,16 @@ struct hb_buffer_t #else if (!messaging ()) return true; + + message_depth++; + va_list ap; va_start (ap, fmt); bool ret = message_impl (font, fmt, ap); va_end (ap); + + message_depth--; + return ret; #endif } diff --git a/thirdparty/harfbuzz/src/hb-cache.hh b/thirdparty/harfbuzz/src/hb-cache.hh index bf26d96be4..e617b75de9 100644 --- a/thirdparty/harfbuzz/src/hb-cache.hh +++ b/thirdparty/harfbuzz/src/hb-cache.hh @@ -30,7 +30,7 @@ #include "hb.hh" -/* Implements a lock-free cache for int->int functions. */ +/* Implements a lockfree cache for int->int functions. */ template struct hb_cache_t diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh index 91a9b7d0d1..c251e2d0ed 100644 --- a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh +++ b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh @@ -263,7 +263,7 @@ struct UnsizedByteStr : UnsizedArrayOf T *ip = c->allocate_size (T::static_size); if (unlikely (!ip)) return_trace (false); - return_trace (c->check_assign (*ip, value)); + return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW)); } template diff --git a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh index 332ece31cd..d961566447 100644 --- a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh +++ b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh @@ -136,8 +136,8 @@ struct cff2_cs_interp_env_t : cs_interp_env_t if (unlikely (!scalars.resize (region_count))) set_error (); else - varStore->varStore.get_scalars (get_ivs (), coords, num_coords, - &scalars[0], region_count); + varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords, + &scalars[0], region_count); } seen_blend = true; } diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc index 7bb878b217..26c8ad0f49 100644 --- a/thirdparty/harfbuzz/src/hb-common.cc +++ b/thirdparty/harfbuzz/src/hb-common.cc @@ -257,13 +257,11 @@ struct hb_language_item_t { bool operator == (const char *s) const { return lang_equal (lang, s); } - hb_language_item_t & operator = (const char *s) { - /* If a custom allocated is used calling strdup() pairs - badly with a call to the custom free() in fini() below. - Therefore don't call strdup(), implement its behavior. - */ + hb_language_item_t & operator = (const char *s) + { + /* We can't call strdup(), because we allow custom allocators. */ size_t len = strlen(s) + 1; - lang = (hb_language_t) malloc(len); + lang = (hb_language_t) hb_malloc(len); if (likely (lang)) { memcpy((unsigned char *) lang, s, len); @@ -274,16 +272,15 @@ struct hb_language_item_t { return *this; } - void fini () { free ((void *) lang); } + void fini () { hb_free ((void *) lang); } }; -/* Thread-safe lock-free language list */ +/* Thread-safe lockfree language list */ static hb_atomic_ptr_t langs; -#if HB_USE_ATEXIT -static void +static inline void free_langs () { retry: @@ -294,11 +291,10 @@ retry: while (first_lang) { hb_language_item_t *next = first_lang->next; first_lang->fini (); - free (first_lang); + hb_free (first_lang); first_lang = next; } } -#endif static hb_language_item_t * lang_find_or_insert (const char *key) @@ -311,28 +307,26 @@ retry: return lang; /* Not found; allocate one. */ - hb_language_item_t *lang = (hb_language_item_t *) calloc (1, sizeof (hb_language_item_t)); + hb_language_item_t *lang = (hb_language_item_t *) hb_calloc (1, sizeof (hb_language_item_t)); if (unlikely (!lang)) return nullptr; lang->next = first_lang; *lang = key; if (unlikely (!lang->lang)) { - free (lang); + hb_free (lang); return nullptr; } if (unlikely (!langs.cmpexch (first_lang, lang))) { lang->fini (); - free (lang); + hb_free (lang); goto retry; } -#if HB_USE_ATEXIT if (!first_lang) - atexit (free_langs); /* First person registers atexit() callback. */ -#endif + hb_atexit (free_langs); /* First person registers atexit() callback. */ return lang; } @@ -601,6 +595,9 @@ hb_script_get_horizontal_direction (hb_script_t script) case HB_SCRIPT_CHORASMIAN: case HB_SCRIPT_YEZIDI: + /* Unicode-14.0 additions */ + case HB_SCRIPT_OLD_UYGHUR: + return HB_DIRECTION_RTL; diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h index 532fd428cb..0384117a4d 100644 --- a/thirdparty/harfbuzz/src/hb-common.h +++ b/thirdparty/harfbuzz/src/hb-common.h @@ -476,6 +476,11 @@ hb_language_get_default (void); * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7 * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7 * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7 + * @HB_SCRIPT_CYPRO_MINOAN: `Cpmn`, Since: 3.0.0 + * @HB_SCRIPT_OLD_UYGHUR: `Ougr`, Since: 3.0.0 + * @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0 + * @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0 + * @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0 * @HB_SCRIPT_INVALID: No script set * * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding @@ -683,6 +688,15 @@ typedef enum HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/ HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/ + /* + * Since 3.0.0 + */ + HB_SCRIPT_CYPRO_MINOAN = HB_TAG ('C','p','m','n'), /*14.0*/ + HB_SCRIPT_OLD_UYGHUR = HB_TAG ('O','u','g','r'), /*14.0*/ + HB_SCRIPT_TANGSA = HB_TAG ('T','n','s','a'), /*14.0*/ + HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/ + HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/ + /* No script set. */ HB_SCRIPT_INVALID = HB_TAG_NONE, diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh index fc8d424bfb..ad800f0f74 100644 --- a/thirdparty/harfbuzz/src/hb-config.hh +++ b/thirdparty/harfbuzz/src/hb-config.hh @@ -86,6 +86,9 @@ #define HB_NO_LEGACY #endif +#ifdef HAVE_CONFIG_OVERRIDE_H +#include "config-override.h" +#endif /* Closure of options. */ @@ -117,7 +120,7 @@ #define HB_NO_CMAP_LEGACY_SUBTABLES #define HB_NO_FALLBACK_SHAPE #define HB_NO_OT_KERN -#define HB_NO_OT_LAYOUT_BLACKLIST +#define HB_NO_OT_LAYOUT_BLOCKLIST #define HB_NO_OT_SHAPE_FALLBACK #endif @@ -155,9 +158,5 @@ #endif #endif -#ifdef HAVE_CONFIG_OVERRIDE_H -#include "config-override.h" -#endif - #endif /* HB_CONFIG_HH */ diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc index 461bd20e65..4b6c67c1ee 100644 --- a/thirdparty/harfbuzz/src/hb-coretext.cc +++ b/thirdparty/harfbuzz/src/hb-coretext.cc @@ -332,6 +332,44 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font) return nullptr; } + if (font->coords) + { + CFMutableDictionaryRef variations = + CFDictionaryCreateMutable (kCFAllocatorDefault, + font->num_coords, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + for (unsigned i = 0; i < font->num_coords; i++) + { + if (font->coords[i] == 0.) continue; + + hb_ot_var_axis_info_t info; + unsigned int c = 1; + hb_ot_var_get_axis_infos (font->face, i, &c, &info); + CFDictionarySetValue (variations, + CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag), + CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &font->design_coords[i]) + ); + } + + CFDictionaryRef attributes = + CFDictionaryCreate (kCFAllocatorDefault, + (const void **) &kCTFontVariationAttribute, + (const void **) &variations, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CTFontDescriptorRef varDesc = CTFontDescriptorCreateWithAttributes (attributes); + CTFontRef new_ct_font = CTFontCreateCopyWithAttributes (ct_font, 0, nullptr, varDesc); + + CFRelease (ct_font); + CFRelease (attributes); + CFRelease (variations); + ct_font = new_ct_font; + } + return (hb_coretext_font_data_t *) ct_font; } @@ -1061,7 +1099,7 @@ resize_and_retry: hb_glyph_info_t *info = run_info; if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) { - hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; + hb_position_t x_offset = round ((positions[0].x - advances_so_far) * x_mult); for (unsigned int j = 0; j < num_glyphs; j++) { CGFloat advance; @@ -1069,15 +1107,15 @@ resize_and_retry: advance = positions[j + 1].x - positions[j].x; else /* last glyph */ advance = run_advance - (positions[j].x - positions[0].x); - info->mask = advance * x_mult; + info->mask = round (advance * x_mult); info->var1.i32 = x_offset; - info->var2.i32 = positions[j].y * y_mult; + info->var2.i32 = round (positions[j].y * y_mult); info++; } } else { - hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult; + hb_position_t y_offset = round ((positions[0].y - advances_so_far) * y_mult); for (unsigned int j = 0; j < num_glyphs; j++) { CGFloat advance; @@ -1085,8 +1123,8 @@ resize_and_retry: advance = positions[j + 1].y - positions[j].y; else /* last glyph */ advance = run_advance - (positions[j].y - positions[0].y); - info->mask = advance * y_mult; - info->var1.i32 = positions[j].x * x_mult; + info->mask = round (advance * y_mult); + info->var1.i32 = round (positions[j].x * x_mult); info->var2.i32 = y_offset; info++; } diff --git a/thirdparty/harfbuzz/src/hb-debug.hh b/thirdparty/harfbuzz/src/hb-debug.hh index ec3a1ff211..f80c8980ba 100644 --- a/thirdparty/harfbuzz/src/hb-debug.hh +++ b/thirdparty/harfbuzz/src/hb-debug.hh @@ -307,7 +307,7 @@ struct hb_auto_trace_t _hb_debug_msg (what, obj, func, true, plevel ? *plevel : 1, -1, "return %s (line %d)", - hb_printer_t().print (v), line); + hb_printer_t>().print (v), line); if (plevel) --*plevel; plevel = nullptr; returned = true; @@ -438,6 +438,10 @@ struct hb_no_trace_t { #define TRACE_SUBSET(this) hb_no_trace_t trace #endif +#ifndef HB_DEBUG_SUBSET_REPACK +#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0) +#endif + #ifndef HB_DEBUG_DISPATCH #define HB_DEBUG_DISPATCH ( \ HB_DEBUG_APPLY + \ diff --git a/thirdparty/harfbuzz/src/hb-deprecated.h b/thirdparty/harfbuzz/src/hb-deprecated.h index 5f19125789..a130d77f77 100644 --- a/thirdparty/harfbuzz/src/hb-deprecated.h +++ b/thirdparty/harfbuzz/src/hb-deprecated.h @@ -107,9 +107,6 @@ 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 HB_DEPRECATED void -hb_set_invert (hb_set_t *set); - /** * hb_unicode_eastasian_width_func_t: * @ufuncs: A Unicode-functions structure diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc index a07302159c..8f6d73b639 100644 --- a/thirdparty/harfbuzz/src/hb-directwrite.cc +++ b/thirdparty/harfbuzz/src/hb-directwrite.cc @@ -32,6 +32,7 @@ #include "hb-directwrite.h" +#include "hb-ms-feature-ranges.hh" /** * SECTION:hb-directwrite @@ -42,24 +43,6 @@ * Functions for using HarfBuzz with DirectWrite fonts. **/ -/* Declare object creator for dynamic support of DWRITE */ -typedef HRESULT (* WINAPI t_DWriteCreateFactory)( - DWRITE_FACTORY_TYPE factoryType, - REFIID iid, - IUnknown **factory -); - -/* - * hb-directwrite uses new/delete syntatically but as we let users - * to override malloc/free, we will redefine new/delete so users - * won't need to do that by their own. - */ -void* operator new (size_t size) { return malloc (size); } -void* operator new [] (size_t size) { return malloc (size); } -void operator delete (void* pointer) { free (pointer); } -void operator delete [] (void* pointer) { free (pointer); } - - /* * DirectWrite font stream helpers */ @@ -154,7 +137,6 @@ public: struct hb_directwrite_face_data_t { - HMODULE dwrite_dll; IDWriteFactory *dwriteFactory; IDWriteFontFile *fontFile; DWriteFontFileStream *fontFileStream; @@ -176,33 +158,12 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face) return nullptr; \ } HB_STMT_END - data->dwrite_dll = LoadLibrary (TEXT ("DWRITE")); - if (unlikely (!data->dwrite_dll)) - FAIL ("Cannot find DWrite.DLL"); - - t_DWriteCreateFactory p_DWriteCreateFactory; - -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-function-type" -#endif - - p_DWriteCreateFactory = (t_DWriteCreateFactory) - GetProcAddress (data->dwrite_dll, "DWriteCreateFactory"); - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - - if (unlikely (!p_DWriteCreateFactory)) - FAIL ("Cannot find DWriteCreateFactory()."); - HRESULT hr; // TODO: factory and fontFileLoader should be cached separately IDWriteFactory* dwriteFactory; - hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), - (IUnknown**) &dwriteFactory); + hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory), + (IUnknown**) &dwriteFactory); if (unlikely (hr != S_OK)) FAIL ("Failed to run DWriteCreateFactory()."); @@ -266,8 +227,6 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data) delete data->fontFileStream; if (data->faceBlob) hb_blob_destroy (data->faceBlob); - if (data->dwrite_dll) - FreeLibrary (data->dwrite_dll); if (data) delete data; } @@ -552,13 +511,12 @@ protected: * shaper */ -static hb_bool_t -_hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, - hb_font_t *font, - hb_buffer_t *buffer, - const hb_feature_t *features, - unsigned int num_features, - float lineWidth) +hb_bool_t +_hb_directwrite_shape (hb_shape_plan_t *shape_plan, + hb_font_t *font, + hb_buffer_t *buffer, + const hb_feature_t *features, + unsigned int num_features) { hb_face_t *face = font->face; const hb_directwrite_face_data_t *face_data = face->data.directwrite; @@ -611,8 +569,6 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, log_clusters[chars_len++] = cluster; /* Surrogates. */ } - // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES - DWRITE_READING_DIRECTION readingDirection; readingDirection = buffer->props.direction ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : @@ -623,7 +579,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, * but we never attempt to shape a word longer than 64K characters * in a single gfxShapedWord, so we cannot exceed that limit. */ - uint32_t textLength = buffer->len; + uint32_t textLength = chars_len; TextAnalysis analysis (textString, textLength, nullptr, readingDirection); TextAnalysis::Run *runHead; @@ -648,38 +604,54 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan, mbstowcs ((wchar_t*) localeName, hb_language_to_string (buffer->props.language), 20); - // TODO: it does work but doesn't care about ranges - DWRITE_TYPOGRAPHIC_FEATURES typographic_features; - typographic_features.featureCount = num_features; + /* + * Set up features. + */ + static_assert ((sizeof (DWRITE_TYPOGRAPHIC_FEATURES) == sizeof (hb_ms_features_t)), ""); + static_assert ((sizeof (DWRITE_FONT_FEATURE) == sizeof (hb_ms_feature_t)), ""); + hb_vector_t range_features; + hb_vector_t range_char_counts; if (num_features) { - typographic_features.features = new DWRITE_FONT_FEATURE[num_features]; - for (unsigned int i = 0; i < num_features; ++i) - { - typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG) - hb_uint32_swap (features[i].tag); - typographic_features.features[i].parameter = features[i].value; - } + hb_vector_t feature_records; + hb_vector_t range_records; + if (hb_ms_setup_features (features, num_features, feature_records, range_records)) + hb_ms_make_feature_ranges (feature_records, + range_records, + 0, + chars_len, + log_clusters, + range_features, + range_char_counts); } - const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures; - dwFeatures = (const DWRITE_TYPOGRAPHIC_FEATURES*) &typographic_features; - const uint32_t featureRangeLengths[] = { textLength }; - // uint16_t* clusterMap; clusterMap = new uint16_t[textLength]; DWRITE_SHAPING_TEXT_PROPERTIES* textProperties; textProperties = new DWRITE_SHAPING_TEXT_PROPERTIES[textLength]; + retry_getglyphs: uint16_t* glyphIndices = new uint16_t[maxGlyphCount]; DWRITE_SHAPING_GLYPH_PROPERTIES* glyphProperties; glyphProperties = new DWRITE_SHAPING_GLYPH_PROPERTIES[maxGlyphCount]; - hr = analyzer->GetGlyphs (textString, textLength, fontFace, false, - isRightToLeft, &runHead->mScript, localeName, - nullptr, &dwFeatures, featureRangeLengths, 1, - maxGlyphCount, clusterMap, textProperties, - glyphIndices, glyphProperties, &glyphCount); + hr = analyzer->GetGlyphs (textString, + chars_len, + fontFace, + false, + isRightToLeft, + &runHead->mScript, + localeName, + nullptr, + (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ, + range_char_counts.arrayZ, + range_features.length, + maxGlyphCount, + clusterMap, + textProperties, + glyphIndices, + glyphProperties, + &glyphCount); if (unlikely (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER))) { @@ -715,101 +687,28 @@ retry_getglyphs: double x_mult = (double) font->x_scale / fontEmSize; double y_mult = (double) font->y_scale / fontEmSize; - hr = analyzer->GetGlyphPlacements (textString, clusterMap, textProperties, - textLength, glyphIndices, glyphProperties, - glyphCount, fontFace, fontEmSize, - false, isRightToLeft, &runHead->mScript, localeName, - &dwFeatures, featureRangeLengths, 1, - glyphAdvances, glyphOffsets); + hr = analyzer->GetGlyphPlacements (textString, + clusterMap, + textProperties, + chars_len, + glyphIndices, + glyphProperties, + glyphCount, + fontFace, + fontEmSize, + false, + isRightToLeft, + &runHead->mScript, + localeName, + (const DWRITE_TYPOGRAPHIC_FEATURES**) range_features.arrayZ, + range_char_counts.arrayZ, + range_features.length, + glyphAdvances, + glyphOffsets); if (FAILED (hr)) FAIL ("Analyzer failed to get glyph placements."); - IDWriteTextAnalyzer1* analyzer1; - analyzer->QueryInterface (&analyzer1); - - if (analyzer1 && lineWidth) - { - DWRITE_JUSTIFICATION_OPPORTUNITY* justificationOpportunities = - new DWRITE_JUSTIFICATION_OPPORTUNITY[maxGlyphCount]; - hr = analyzer1->GetJustificationOpportunities (fontFace, fontEmSize, runHead->mScript, - textLength, glyphCount, textString, - clusterMap, glyphProperties, - justificationOpportunities); - - if (FAILED (hr)) - FAIL ("Analyzer failed to get justification opportunities."); - - float* justifiedGlyphAdvances = new float[maxGlyphCount]; - DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[glyphCount]; - hr = analyzer1->JustifyGlyphAdvances (lineWidth, glyphCount, justificationOpportunities, - glyphAdvances, glyphOffsets, justifiedGlyphAdvances, - justifiedGlyphOffsets); - - if (FAILED (hr)) FAIL ("Analyzer failed to get justify glyph advances."); - - DWRITE_SCRIPT_PROPERTIES scriptProperties; - hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties); - if (FAILED (hr)) FAIL ("Analyzer failed to get script properties."); - uint32_t justificationCharacter = scriptProperties.justificationCharacter; - - // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs - if (justificationCharacter != 32) - { - uint16_t* modifiedClusterMap = new uint16_t[textLength]; - retry_getjustifiedglyphs: - uint16_t* modifiedGlyphIndices = new uint16_t[maxGlyphCount]; - float* modifiedGlyphAdvances = new float[maxGlyphCount]; - DWRITE_GLYPH_OFFSET* modifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount]; - uint32_t actualGlyphsCount; - hr = analyzer1->GetJustifiedGlyphs (fontFace, fontEmSize, runHead->mScript, - textLength, glyphCount, maxGlyphCount, - clusterMap, glyphIndices, glyphAdvances, - justifiedGlyphAdvances, justifiedGlyphOffsets, - glyphProperties, &actualGlyphsCount, - modifiedClusterMap, modifiedGlyphIndices, - modifiedGlyphAdvances, modifiedGlyphOffsets); - - if (hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)) - { - maxGlyphCount = actualGlyphsCount; - delete [] modifiedGlyphIndices; - delete [] modifiedGlyphAdvances; - delete [] modifiedGlyphOffsets; - - maxGlyphCount = actualGlyphsCount; - - goto retry_getjustifiedglyphs; - } - if (FAILED (hr)) - FAIL ("Analyzer failed to get justified glyphs."); - - delete [] clusterMap; - delete [] glyphIndices; - delete [] glyphAdvances; - delete [] glyphOffsets; - - glyphCount = actualGlyphsCount; - clusterMap = modifiedClusterMap; - glyphIndices = modifiedGlyphIndices; - glyphAdvances = modifiedGlyphAdvances; - glyphOffsets = modifiedGlyphOffsets; - - delete [] justifiedGlyphAdvances; - delete [] justifiedGlyphOffsets; - } - else - { - delete [] glyphAdvances; - delete [] glyphOffsets; - - glyphAdvances = justifiedGlyphAdvances; - glyphOffsets = justifiedGlyphOffsets; - } - - delete [] justificationOpportunities; - } - /* Ok, we've got everything we need, now compose output buffer, * very, *very*, carefully! */ @@ -870,43 +769,10 @@ retry_getglyphs: delete [] glyphAdvances; delete [] glyphOffsets; - if (num_features) - delete [] typographic_features.features; - /* Wow, done! */ return true; } -hb_bool_t -_hb_directwrite_shape (hb_shape_plan_t *shape_plan, - hb_font_t *font, - hb_buffer_t *buffer, - const hb_feature_t *features, - unsigned int num_features) -{ - return _hb_directwrite_shape_full (shape_plan, font, buffer, - features, num_features, 0); -} - -HB_UNUSED static bool -_hb_directwrite_shape_experimental_width (hb_font_t *font, - hb_buffer_t *buffer, - const hb_feature_t *features, - unsigned int num_features, - float width) -{ - static const char *shapers = "directwrite"; - hb_shape_plan_t *shape_plan; - shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, - features, num_features, &shapers); - hb_bool_t res = _hb_directwrite_shape_full (shape_plan, font, buffer, - features, num_features, width); - - buffer->unsafe_to_break_all (); - - return res; -} - struct _hb_directwrite_font_table_context { IDWriteFontFace *face; void *table_context; @@ -917,7 +783,7 @@ _hb_directwrite_table_data_release (void *data) { _hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) data; context->face->ReleaseFontTable (context->table_context); - delete context; + hb_free (context); } static hb_blob_t * @@ -938,7 +804,7 @@ _hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void * return nullptr; } - _hb_directwrite_font_table_context *context = new _hb_directwrite_font_table_context; + _hb_directwrite_font_table_context *context = (_hb_directwrite_font_table_context *) hb_malloc (sizeof (_hb_directwrite_font_table_context)); context->face = dw_face; context->table_context = table_context; diff --git a/thirdparty/harfbuzz/src/hb-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc index 1a5f9c8c6b..c0af6ce013 100644 --- a/thirdparty/harfbuzz/src/hb-draw.cc +++ b/thirdparty/harfbuzz/src/hb-draw.cc @@ -191,7 +191,7 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *funcs) { if (!hb_object_destroy (funcs)) return; - free (funcs); + hb_free (funcs); } /** diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc index 61bd4af7b1..2c0087370c 100644 --- a/thirdparty/harfbuzz/src/hb-face.cc +++ b/thirdparty/harfbuzz/src/hb-face.cc @@ -33,6 +33,7 @@ #include "hb-open-file.hh" #include "hb-ot-face.hh" #include "hb-ot-cmap-table.hh" +#include "hb-map.hh" /** @@ -106,9 +107,9 @@ DEFINE_NULL_INSTANCE (hb_face_t) = * convenient to provide data for individual tables instead of the whole font * data. With the caveat that hb_face_get_table_tags() does not currently work * with faces created this way. - * + * * Creates a new face object from the specified @user_data and @reference_table_func, - * with the @destroy callback. + * with the @destroy callback. * * Return value: (transfer full): The new face object * @@ -150,7 +151,7 @@ _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) { hb_face_for_data_closure_t *closure; - closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t)); + closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t)); if (unlikely (!closure)) return nullptr; @@ -166,7 +167,7 @@ _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); + hb_free (closure); } static hb_blob_t * @@ -265,7 +266,7 @@ hb_face_reference (hb_face_t *face) /** * hb_face_destroy: (skip) * @face: A face object - * + * * Decreases the reference count on a face object. When the * reference count reaches zero, the face is destroyed, * freeing all memory. @@ -281,7 +282,7 @@ hb_face_destroy (hb_face_t *face) { hb_face_t::plan_node_t *next = node->next; hb_shape_plan_destroy (node->shape_plan); - free (node); + hb_free (node); node = next; } @@ -291,7 +292,7 @@ hb_face_destroy (hb_face_t *face) if (face->destroy) face->destroy (face->user_data); - free (face); + hb_free (face); } /** @@ -302,7 +303,7 @@ hb_face_destroy (hb_face_t *face) * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * - * Attaches a user-data key/data pair to the given face object. + * Attaches a user-data key/data pair to the given face object. * * Return value: %true if success, %false otherwise * @@ -441,7 +442,7 @@ hb_face_set_index (hb_face_t *face, * * Note: face indices within a collection are zero-based. * - * Return value: The index of @face. + * Return value: The index of @face. * * Since: 0.9.2 **/ @@ -623,26 +624,26 @@ hb_face_collect_variation_unicodes (hb_face_t *face, struct hb_face_builder_data_t { - struct table_entry_t - { - int cmp (hb_tag_t t) const - { - if (t < tag) return -1; - if (t > tag) return -1; - return 0; - } - - hb_tag_t tag; - hb_blob_t *blob; - }; - - hb_vector_t tables; + hb_hashmap_t tables; }; +static int compare_entries (const void* pa, const void* pb) +{ + const auto& a = * (const hb_pair_t *) pa; + const auto& b = * (const hb_pair_t *) pb; + + /* Order by blob size first (smallest to largest) and then table tag */ + + if (a.second->length != b.second->length) + return a.second->length < b.second->length ? -1 : +1; + + return a.first < b.first ? -1 : a.first == b.first ? 0 : +1; +} + static hb_face_builder_data_t * _hb_face_builder_data_create () { - hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t)); + hb_face_builder_data_t *data = (hb_face_builder_data_t *) hb_calloc (1, sizeof (hb_face_builder_data_t)); if (unlikely (!data)) return nullptr; @@ -656,25 +657,25 @@ _hb_face_builder_data_destroy (void *user_data) { hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data; - for (unsigned int i = 0; i < data->tables.length; i++) - hb_blob_destroy (data->tables[i].blob); + for (hb_blob_t* b : data->tables.values()) + hb_blob_destroy (b); data->tables.fini (); - free (data); + hb_free (data); } static hb_blob_t * _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) { - unsigned int table_count = data->tables.length; + unsigned int table_count = data->tables.get_population (); unsigned int face_length = table_count * 16 + 12; - for (unsigned int i = 0; i < table_count; i++) - face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob)); + for (hb_blob_t* b : data->tables.values()) + face_length += hb_ceil_to_4 (hb_blob_get_length (b)); - char *buf = (char *) malloc (face_length); + char *buf = (char *) hb_malloc (face_length); if (unlikely (!buf)) return nullptr; @@ -682,20 +683,31 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data) c.propagate_error (data->tables); OT::OpenTypeFontFile *f = c.start_serialize (); - bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2')); + bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' ')) + || data->tables.has (HB_TAG ('C','F','F','2'))); hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag; - bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ()); + // Sort the tags so that produced face is deterministic. + hb_vector_t> sorted_entries; + data->tables.iter () | hb_sink (sorted_entries); + if (unlikely (sorted_entries.in_error ())) + { + hb_free (buf); + return nullptr; + } + + sorted_entries.qsort (compare_entries); + bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter()); c.end_serialize (); if (unlikely (!ret)) { - free (buf); + hb_free (buf); return nullptr; } - return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free); + return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, hb_free); } static hb_blob_t * @@ -706,11 +718,7 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void if (!tag) return _hb_face_builder_data_reference_blob (data); - hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag); - if (entry) - return hb_blob_reference (entry->blob); - - return nullptr; + return hb_blob_reference (data->tables[tag]); } @@ -750,17 +758,21 @@ hb_face_builder_create () hb_bool_t hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) { + if (tag == HB_MAP_VALUE_INVALID) + return false; + if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy)) return false; hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data; - hb_face_builder_data_t::table_entry_t *entry = data->tables.push (); - if (unlikely (data->tables.in_error())) + hb_blob_t* previous = data->tables.get (tag); + if (!data->tables.set (tag, hb_blob_reference (blob))) + { + hb_blob_destroy (blob); return false; + } - entry->tag = tag; - entry->blob = hb_blob_reference (blob); - + hb_blob_destroy (previous); return true; } diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc index 37a0e7fe85..fa8da96395 100644 --- a/thirdparty/harfbuzz/src/hb-font.cc +++ b/thirdparty/harfbuzz/src/hb-font.cc @@ -620,7 +620,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT - free (ffuncs); + hb_free (ffuncs); } /** @@ -1544,8 +1544,8 @@ _hb_font_adopt_var_coords (hb_font_t *font, float *design_coords, unsigned int coords_length) { - free (font->coords); - free (font->design_coords); + hb_free (font->coords); + hb_free (font->design_coords); font->coords = coords; font->design_coords = design_coords; @@ -1586,8 +1586,8 @@ hb_font_create_sub_font (hb_font_t *parent) unsigned int num_coords = parent->num_coords; if (num_coords) { - int *coords = (int *) calloc (num_coords, sizeof (parent->coords[0])); - float *design_coords = (float *) calloc (num_coords, sizeof (parent->design_coords[0])); + int *coords = (int *) hb_calloc (num_coords, sizeof (parent->coords[0])); + float *design_coords = (float *) hb_calloc (num_coords, sizeof (parent->design_coords[0])); if (likely (coords && design_coords)) { memcpy (coords, parent->coords, num_coords * sizeof (parent->coords[0])); @@ -1596,8 +1596,8 @@ hb_font_create_sub_font (hb_font_t *parent) } else { - free (coords); - free (design_coords); + hb_free (coords); + hb_free (design_coords); } } @@ -1659,10 +1659,10 @@ hb_font_destroy (hb_font_t *font) hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); - free (font->coords); - free (font->design_coords); + hb_free (font->coords); + hb_free (font->design_coords); - free (font); + hb_free (font); } /** @@ -2052,29 +2052,30 @@ hb_font_set_variations (hb_font_t *font, return; } - unsigned int coords_length = hb_ot_var_get_axis_count (font->face); + const OT::fvar &fvar = *font->face->table.fvar; + auto axes = fvar.get_axes (); + const unsigned coords_length = axes.length; - int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; - float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr; + int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr; + float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; if (unlikely (coords_length && !(normalized && design_coords))) { - free (normalized); - free (design_coords); + hb_free (normalized); + hb_free (design_coords); return; } - const OT::fvar &fvar = *font->face->table.fvar; for (unsigned int i = 0; i < variations_length; i++) { - hb_ot_var_axis_info_t info; - if (hb_ot_var_find_axis_info (font->face, variations[i].tag, &info) && - info.axis_index < coords_length) - { - float v = variations[i].value; - design_coords[info.axis_index] = v; - normalized[info.axis_index] = fvar.normalize_axis_value (info.axis_index, v); - } + const auto tag = variations[i].tag; + const auto v = variations[i].value; + for (unsigned axis_index = 0; axis_index < coords_length; axis_index++) + if (axes[axis_index].axisTag == tag) + { + design_coords[axis_index] = v; + normalized[axis_index] = fvar.normalize_axis_value (axis_index, v); + } } font->face->table.avar->map_coords (normalized, coords_length); @@ -2100,13 +2101,13 @@ hb_font_set_var_coords_design (hb_font_t *font, if (hb_object_is_immutable (font)) return; - int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr; - float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr; + int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr; + float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; if (unlikely (coords_length && !(normalized && design_coords))) { - free (normalized); - free (design_coords); + hb_free (normalized); + hb_free (design_coords); return; } @@ -2135,13 +2136,13 @@ hb_font_set_var_named_instance (hb_font_t *font, unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr); - float *coords = coords_length ? (float *) calloc (coords_length, sizeof (float)) : nullptr; + float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr; if (unlikely (coords_length && !coords)) return; hb_ot_var_named_instance_get_design_coords (font->face, instance_index, &coords_length, coords); hb_font_set_var_coords_design (font, coords, coords_length); - free (coords); + hb_free (coords); } /** @@ -2165,15 +2166,15 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (hb_object_is_immutable (font)) return; - int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr; - int *unmapped = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr; - float *design_coords = coords_length ? (float *) calloc (coords_length, sizeof (design_coords[0])) : nullptr; + int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; + int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr; + float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr; if (unlikely (coords_length && !(copy && unmapped && design_coords))) { - free (copy); - free (unmapped); - free (design_coords); + hb_free (copy); + hb_free (unmapped); + hb_free (design_coords); return; } @@ -2187,7 +2188,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font, font->face->table.avar->unmap_coords (unmapped, coords_length); for (unsigned int i = 0; i < coords_length; ++i) design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]); - free (unmapped); + hb_free (unmapped); _hb_font_adopt_var_coords (font, copy, design_coords, coords_length); } @@ -2267,7 +2268,7 @@ trampoline_create (FuncType func, { typedef hb_trampoline_t trampoline_t; - trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t)); + trampoline_t *trampoline = (trampoline_t *) hb_calloc (1, sizeof (trampoline_t)); if (unlikely (!trampoline)) return nullptr; @@ -2296,7 +2297,7 @@ trampoline_destroy (void *user_data) if (closure->destroy) closure->destroy (closure->user_data); - free (closure); + hb_free (closure); } typedef hb_trampoline_t hb_font_get_glyph_trampoline_t; diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc index b82c1a67bd..97a2c82e68 100644 --- a/thirdparty/harfbuzz/src/hb-ft.cc +++ b/thirdparty/harfbuzz/src/hb-ft.cc @@ -91,7 +91,7 @@ struct hb_ft_font_t static hb_ft_font_t * _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) { - hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); + hb_ft_font_t *ft_font = (hb_ft_font_t *) hb_calloc (1, sizeof (hb_ft_font_t)); if (unlikely (!ft_font)) return nullptr; ft_font->lock.init (); @@ -125,7 +125,7 @@ _hb_ft_font_destroy (void *data) ft_font->lock.fini (); - free (ft_font); + hb_free (ft_font); } /** @@ -561,9 +561,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED, return true; } -#if HB_USE_ATEXIT -static void free_static_ft_funcs (); -#endif +static inline void free_static_ft_funcs (); static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t { @@ -591,21 +589,17 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_tnum_axis, sizeof (FT_Fixed)); - int *coords = (int *) calloc (mm_var->num_axis, sizeof (int)); + FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (mm_var->num_axis, sizeof (FT_Fixed)); + int *coords = (int *) hb_calloc (mm_var->num_axis, sizeof (int)); if (coords && ft_coords) { if (!FT_Get_Var_Blend_Coordinates (ft_face, mm_var->num_axis, ft_coords)) @@ -866,12 +860,12 @@ hb_ft_font_changed (hb_font_t *font) hb_font_set_var_coords_normalized (font, nullptr, 0); } } - free (coords); - free (ft_coords); + hb_free (coords); + hb_free (ft_coords); #ifdef HAVE_FT_DONE_MM_VAR FT_Done_MM_Var (ft_face->glyph->library, mm_var); #else - free (mm_var); + hb_free (mm_var); #endif } #endif @@ -905,9 +899,7 @@ hb_ft_font_create_referenced (FT_Face ft_face) return hb_ft_font_create (ft_face, _hb_ft_face_destroy); } -#if HB_USE_ATEXIT -static void free_static_ft_library (); -#endif +static inline void free_static_ft_library (); static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t, hb_ft_library_lazy_loader_t> @@ -918,9 +910,7 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t { @@ -237,21 +235,17 @@ static struct hb_glib_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader hb_unicode_funcs_make_immutable (funcs); -#if HB_USE_ATEXIT - atexit (free_static_glib_funcs); -#endif + hb_atexit (free_static_glib_funcs); return funcs; } } static_glib_funcs; -#if HB_USE_ATEXIT -static +static inline void free_static_glib_funcs () { static_glib_funcs.free_instance (); } -#endif /** * hb_glib_get_unicode_funcs: diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.cc b/thirdparty/harfbuzz/src/hb-gobject-structs.cc index 7c46e26400..540b11f911 100644 --- a/thirdparty/harfbuzz/src/hb-gobject-structs.cc +++ b/thirdparty/harfbuzz/src/hb-gobject-structs.cc @@ -80,12 +80,12 @@ hb_gobject_##name##_get_type () \ #define HB_DEFINE_VALUE_TYPE(name) \ static hb_##name##_t *_hb_##name##_reference (const hb_##name##_t *l) \ { \ - hb_##name##_t *c = (hb_##name##_t *) calloc (1, sizeof (hb_##name##_t)); \ + hb_##name##_t *c = (hb_##name##_t *) hb_calloc (1, sizeof (hb_##name##_t)); \ if (unlikely (!c)) return nullptr; \ *c = *l; \ return c; \ } \ - static void _hb_##name##_destroy (hb_##name##_t *l) { free (l); } \ + static void _hb_##name##_destroy (hb_##name##_t *l) { hb_free (l); } \ HB_DEFINE_BOXED_TYPE (name, _hb_##name##_reference, _hb_##name##_destroy) HB_DEFINE_OBJECT_TYPE (buffer) diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc index 9dafe654c8..209207f1e5 100644 --- a/thirdparty/harfbuzz/src/hb-graphite2.cc +++ b/thirdparty/harfbuzz/src/hb-graphite2.cc @@ -88,7 +88,7 @@ static const void *hb_graphite2_get_table (const void *data, unsigned int tag, s { blob = face_data->face->reference_table (tag); - hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) calloc (1, sizeof (hb_graphite2_tablelist_t)); + hb_graphite2_tablelist_t *p = (hb_graphite2_tablelist_t *) hb_calloc (1, sizeof (hb_graphite2_tablelist_t)); if (unlikely (!p)) { hb_blob_destroy (blob); return nullptr; @@ -123,15 +123,16 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face) } hb_blob_destroy (silf_blob); - hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) calloc (1, sizeof (hb_graphite2_face_data_t)); + hb_graphite2_face_data_t *data = (hb_graphite2_face_data_t *) hb_calloc (1, sizeof (hb_graphite2_face_data_t)); if (unlikely (!data)) return nullptr; data->face = face; - data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll); + const gr_face_ops ops = {sizeof(gr_face_ops), &hb_graphite2_get_table, NULL}; + data->grface = gr_make_face_with_ops (data, &ops, gr_face_preloadAll); if (unlikely (!data->grface)) { - free (data); + hb_free (data); return nullptr; } @@ -148,12 +149,12 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data) hb_graphite2_tablelist_t *old = tlist; hb_blob_destroy (tlist->blob); tlist = tlist->next; - free (old); + hb_free (old); } gr_face_destroy (data->grface); - free (data); + hb_free (data); } /** diff --git a/thirdparty/harfbuzz/src/hb-icu.cc b/thirdparty/harfbuzz/src/hb-icu.cc index 008a39e414..e46401f7a6 100644 --- a/thirdparty/harfbuzz/src/hb-icu.cc +++ b/thirdparty/harfbuzz/src/hb-icu.cc @@ -233,9 +233,7 @@ hb_icu_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED, } -#if HB_USE_ATEXIT -static void free_static_icu_funcs (); -#endif +static inline void free_static_icu_funcs (); static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t { @@ -257,21 +255,17 @@ static struct hb_icu_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_ hb_unicode_funcs_make_immutable (funcs); -#if HB_USE_ATEXIT - atexit (free_static_icu_funcs); -#endif + hb_atexit (free_static_icu_funcs); return funcs; } } static_icu_funcs; -#if HB_USE_ATEXIT -static +static inline void free_static_icu_funcs () { static_icu_funcs.free_instance (); } -#endif /** * hb_icu_get_unicode_funcs: diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh index f7018150e4..b8c4472636 100644 --- a/thirdparty/harfbuzz/src/hb-iter.hh +++ b/thirdparty/harfbuzz/src/hb-iter.hh @@ -46,7 +46,7 @@ * TODO Document more. * * If iterator implementation implements operator!=, then can be - * used in range-based for loop. That comes free if the iterator + * used in range-based for loop. That already happens if the iterator * is random-access. Otherwise, the range-based for loop incurs * one traversal to find end(), which can be avoided if written * as a while-style for loop, or if iterator implements a faster diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh index 3bd5a979b0..010c2570d7 100644 --- a/thirdparty/harfbuzz/src/hb-machinery.hh +++ b/thirdparty/harfbuzz/src/hb-machinery.hh @@ -242,14 +242,14 @@ struct hb_lazy_loader_t : hb_data_wrapper_t static const Stored* get_null () { return &Null (Stored); } static Stored *create (Data *data) { - Stored *p = (Stored *) calloc (1, sizeof (Stored)); + Stored *p = (Stored *) hb_calloc (1, sizeof (Stored)); if (likely (p)) p->init (data); return p; } static Stored *create () { - Stored *p = (Stored *) calloc (1, sizeof (Stored)); + Stored *p = (Stored *) hb_calloc (1, sizeof (Stored)); if (likely (p)) p->init (); return p; @@ -257,7 +257,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t static void destroy (Stored *p) { p->fini (); - free (p); + hb_free (p); } // private: diff --git a/thirdparty/harfbuzz/src/hb-map.cc b/thirdparty/harfbuzz/src/hb-map.cc index f115da2bb8..9f1ac42846 100644 --- a/thirdparty/harfbuzz/src/hb-map.cc +++ b/thirdparty/harfbuzz/src/hb-map.cc @@ -109,7 +109,7 @@ hb_map_destroy (hb_map_t *map) map->fini_shallow (); - free (map); + hb_free (map); } /** @@ -188,6 +188,7 @@ hb_map_set (hb_map_t *map, hb_codepoint_t key, hb_codepoint_t value) { + /* Immutable-safe. */ map->set (key, value); } @@ -220,6 +221,7 @@ void hb_map_del (hb_map_t *map, hb_codepoint_t key) { + /* Immutable-safe. */ map->del (key); } @@ -253,9 +255,6 @@ hb_map_has (const hb_map_t *map, void hb_map_clear (hb_map_t *map) { - if (unlikely (hb_object_is_immutable (map))) - return; - return map->clear (); } diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index 84fe1d549b..dcd5267d74 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -85,7 +85,7 @@ struct hb_hashmap_t } void fini_shallow () { - free (items); + hb_free (items); items = nullptr; population = occupancy = 0; } @@ -109,7 +109,7 @@ struct hb_hashmap_t unsigned int power = hb_bit_storage (population * 2 + 8); unsigned int new_size = 1u << power; - item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t)); + item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t)); if (unlikely (!new_items)) { successful = false; @@ -135,14 +135,14 @@ struct hb_hashmap_t old_items[i].hash, old_items[i].value); - free (old_items); + hb_free (old_items); return true; } - void set (K key, V value) + bool set (K key, V value) { - set_with_hash (key, hb_hash (key), value); + return set_with_hash (key, hb_hash (key), value); } V get (K key) const @@ -169,6 +169,8 @@ struct hb_hashmap_t void clear () { + if (unlikely (!successful)) return; + if (items) for (auto &_ : hb_iter (items, mask + 1)) _.clear (); @@ -211,20 +213,20 @@ struct hb_hashmap_t protected: - void set_with_hash (K key, uint32_t hash, V value) + bool set_with_hash (K key, uint32_t hash, V value) { - if (unlikely (!successful)) return; - if (unlikely (key == kINVALID)) return; - if ((occupancy + occupancy / 2) >= mask && !resize ()) return; + if (unlikely (!successful)) return false; + if (unlikely (key == kINVALID)) return true; + if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; unsigned int i = bucket_for_hash (key, hash); if (value == vINVALID && items[i].key != key) - return; /* Trying to delete non-existent key. */ + return true; /* Trying to delete non-existent key. */ if (!items[i].is_unused ()) { occupancy--; - if (items[i].is_tombstone ()) + if (!items[i].is_tombstone ()) population--; } @@ -235,6 +237,8 @@ struct hb_hashmap_t occupancy++; if (!items[i].is_tombstone ()) population++; + + return true; } unsigned int bucket_for (K key) const diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh index e40d9fd178..a714bc2bf0 100644 --- a/thirdparty/harfbuzz/src/hb-meta.hh +++ b/thirdparty/harfbuzz/src/hb-meta.hh @@ -101,14 +101,14 @@ HB_FUNCOBJ (hb_addressof); template static inline T hb_declval (); #define hb_declval(T) (hb_declval ()) -template struct hb_match_const : hb_type_identity_t, hb_bool_constant{}; -template struct hb_match_const : hb_type_identity_t, hb_bool_constant {}; +template struct hb_match_const : hb_type_identity_t, hb_false_type {}; +template struct hb_match_const : hb_type_identity_t, hb_true_type {}; template using hb_remove_const = typename hb_match_const::type; template using hb_add_const = const T; #define hb_is_const(T) hb_match_const::value -template struct hb_match_reference : hb_type_identity_t, hb_bool_constant{}; -template struct hb_match_reference : hb_type_identity_t, hb_bool_constant {}; -template struct hb_match_reference : hb_type_identity_t, hb_bool_constant {}; +template struct hb_match_reference : hb_type_identity_t, hb_false_type {}; +template struct hb_match_reference : hb_type_identity_t, hb_true_type {}; +template struct hb_match_reference : hb_type_identity_t, hb_true_type {}; template using hb_remove_reference = typename hb_match_reference::type; template auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity; template auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity; @@ -117,8 +117,8 @@ template auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_t template auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity; template using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference (hb_prioritize)); #define hb_is_reference(T) hb_match_reference::value -template struct hb_match_pointer : hb_type_identity_t, hb_bool_constant{}; -template struct hb_match_pointer : hb_type_identity_t, hb_bool_constant {}; +template struct hb_match_pointer : hb_type_identity_t, hb_false_type {}; +template struct hb_match_pointer : hb_type_identity_t, hb_true_type {}; template using hb_remove_pointer = typename hb_match_pointer::type; template auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity*>; template auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity; @@ -259,15 +259,15 @@ using hb_is_arithmetic = hb_bool_constant< #define hb_is_arithmetic(T) hb_is_arithmetic::value -template -using hb_is_signed = hb_conditional, - hb_false_type>; +template struct hb_is_signed_; +template struct hb_is_signed_ : hb_false_type {}; +template struct hb_is_signed_ : hb_bool_constant<(T) -1 < (T) 0> {}; +template struct hb_is_signed : hb_is_signed_ {}; #define hb_is_signed(T) hb_is_signed::value -template -using hb_is_unsigned = hb_conditional, - hb_false_type>; +template struct hb_is_unsigned_; +template struct hb_is_unsigned_ : hb_false_type {}; +template struct hb_is_unsigned_ : hb_bool_constant<(T) 0 < (T) -1> {}; +template struct hb_is_unsigned : hb_is_unsigned_ {}; #define hb_is_unsigned(T) hb_is_unsigned::value template struct hb_int_min; @@ -282,6 +282,7 @@ template <> struct hb_int_min : hb_integral_constant struct hb_int_min : hb_integral_constant {}; template <> struct hb_int_min : hb_integral_constant {}; template <> struct hb_int_min : hb_integral_constant {}; +template struct hb_int_min : hb_integral_constant {}; #define hb_int_min(T) hb_int_min::value template struct hb_int_max; template <> struct hb_int_max : hb_integral_constant {}; diff --git a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc new file mode 100644 index 0000000000..6d09b252d8 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.cc @@ -0,0 +1,177 @@ +/* + * Copyright © 2011,2012,2013 Google, Inc. + * Copyright © 2021 Khaled Hosny + * + * 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-ms-feature-ranges.hh" + +bool +hb_ms_setup_features (const hb_feature_t *features, + unsigned int num_features, + hb_vector_t &feature_records, /* OUT */ + hb_vector_t &range_records /* OUT */) +{ + feature_records.shrink(0); + range_records.shrink(0); + + /* Sort features by start/end events. */ + hb_vector_t feature_events; + for (unsigned int i = 0; i < num_features; i++) + { + hb_ms_active_feature_t feature; + feature.fea.tag_le = hb_uint32_swap (features[i].tag); + feature.fea.value = features[i].value; + feature.order = i; + + hb_ms_feature_event_t *event; + + event = feature_events.push (); + event->index = features[i].start; + event->start = true; + event->feature = feature; + + event = feature_events.push (); + event->index = features[i].end; + event->start = false; + event->feature = feature; + } + feature_events.qsort (); + /* Add a strategic final event. */ + { + hb_ms_active_feature_t feature; + feature.fea.tag_le = 0; + feature.fea.value = 0; + feature.order = num_features + 1; + + auto *event = feature_events.push (); + event->index = 0; /* This value does magic. */ + event->start = false; + event->feature = feature; + } + + /* Scan events and save features for each range. */ + hb_vector_t active_features; + unsigned int last_index = 0; + for (unsigned int i = 0; i < feature_events.length; i++) + { + auto *event = &feature_events[i]; + + if (event->index != last_index) + { + /* Save a snapshot of active features and the range. */ + auto *range = range_records.push (); + auto offset = feature_records.length; + + active_features.qsort (); + for (unsigned int j = 0; j < active_features.length; j++) + { + if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le) + { + feature_records.push (active_features[j].fea); + } + else + { + /* Overrides value for existing feature. */ + feature_records[feature_records.length - 1].value = active_features[j].fea.value; + } + } + + /* Will convert to pointer after all is ready, since feature_records.array + * may move as we grow it. */ + range->features.features = reinterpret_cast (offset); + range->features.num_features = feature_records.length - offset; + range->index_first = last_index; + range->index_last = event->index - 1; + + last_index = event->index; + } + + if (event->start) + { + active_features.push (event->feature); + } + else + { + auto *feature = active_features.find (&event->feature); + if (feature) + active_features.remove (feature - active_features.arrayZ); + } + } + + if (!range_records.length) /* No active feature found. */ + num_features = 0; + + /* Fixup the pointers. */ + for (unsigned int i = 0; i < range_records.length; i++) + { + auto *range = &range_records[i]; + range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast (range->features.features); + } + + return !!num_features; +} + +void +hb_ms_make_feature_ranges (hb_vector_t &feature_records, + hb_vector_t &range_records, + unsigned int chars_offset, + unsigned int chars_len, + uint16_t *log_clusters, + hb_vector_t &range_features, /* OUT */ + hb_vector_t &range_counts /* OUT */) +{ + range_features.shrink (0); + range_counts.shrink (0); + + auto *last_range = &range_records[0]; + for (unsigned int i = chars_offset; i < chars_len; i++) + { + auto *range = last_range; + while (log_clusters[i] < range->index_first) + range--; + while (log_clusters[i] > range->index_last) + range++; + if (!range_features.length || + &range->features != range_features[range_features.length - 1]) + { + auto **features = range_features.push (); + auto *c = range_counts.push (); + if (unlikely (!features || !c)) + { + range_features.shrink (0); + range_counts.shrink (0); + break; + } + *features = &range->features; + *c = 1; + } + else + { + range_counts[range_counts.length - 1]++; + } + + last_range = range; + } +} diff --git a/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh new file mode 100644 index 0000000000..401d1e1d97 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh @@ -0,0 +1,96 @@ +/* + * Copyright © 2011,2012,2013 Google, Inc. + * Copyright © 2021 Khaled Hosny + * + * 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_MS_FEATURE_RANGES_HH +#define HB_MS_FEATURE_RANGES_HH + +#include "hb.hh" + +typedef struct hb_ms_feature_t { + uint32_t tag_le; + uint32_t value; +} hb_ms_feature_t; + +typedef struct hb_ms_features_t { + hb_ms_feature_t *features; + uint32_t num_features; +} hb_ms_features_t; + +struct hb_ms_active_feature_t { + hb_ms_feature_t fea; + unsigned int order; + + HB_INTERNAL static int cmp (const void *pa, const void *pb) { + const auto *a = (const hb_ms_active_feature_t *) pa; + const auto *b = (const hb_ms_active_feature_t *) pb; + return a->fea.tag_le < b->fea.tag_le ? -1 : a->fea.tag_le > b->fea.tag_le ? 1 : + a->order < b->order ? -1 : a->order > b->order ? 1 : + a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 : + 0; + } + bool operator== (const hb_ms_active_feature_t *f) + { return cmp (this, f) == 0; } +}; + +struct hb_ms_feature_event_t { + unsigned int index; + bool start; + hb_ms_active_feature_t feature; + + HB_INTERNAL static int cmp (const void *pa, const void *pb) + { + const auto *a = (const hb_ms_feature_event_t *) pa; + const auto *b = (const hb_ms_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 : + hb_ms_active_feature_t::cmp (&a->feature, &b->feature); + } +}; + +struct hb_ms_range_record_t { + hb_ms_features_t features; + unsigned int index_first; /* == start */ + unsigned int index_last; /* == end - 1 */ +}; + +HB_INTERNAL bool +hb_ms_setup_features (const hb_feature_t *features, + unsigned int num_features, + hb_vector_t &feature_records, /* OUT */ + hb_vector_t &range_records /* OUT */); + + +HB_INTERNAL void +hb_ms_make_feature_ranges (hb_vector_t &feature_records, + hb_vector_t &range_records, + unsigned int chars_offset, + unsigned int chars_len, + uint16_t *log_clusters, + hb_vector_t &range_features, /* OUT */ + hb_vector_t &range_counts /* OUT */); + +#endif /* HB_MS_FEATURE_RANGES_HH */ diff --git a/thirdparty/harfbuzz/src/hb-mutex.hh b/thirdparty/harfbuzz/src/hb-mutex.hh index 2fc8d7ee58..a9227a741d 100644 --- a/thirdparty/harfbuzz/src/hb-mutex.hh +++ b/thirdparty/harfbuzz/src/hb-mutex.hh @@ -39,8 +39,7 @@ /* We need external help for these */ -#if defined(HB_MUTEX_IMPL_INIT) \ - && defined(hb_mutex_impl_init) \ +#if defined(hb_mutex_impl_init) \ && defined(hb_mutex_impl_lock) \ && defined(hb_mutex_impl_unlock) \ && defined(hb_mutex_impl_finish) @@ -52,7 +51,6 @@ #include 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, nullptr) #define hb_mutex_impl_lock(M) pthread_mutex_lock (M) #define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M) @@ -62,7 +60,6 @@ typedef pthread_mutex_t hb_mutex_impl_t; #elif !defined(HB_NO_MT) && defined(_WIN32) typedef CRITICAL_SECTION hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT {0} #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0) #else @@ -76,7 +73,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t; #elif defined(HB_NO_MT) typedef int hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT 0 #define hb_mutex_impl_init(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_lock(M) HB_STMT_START {} HB_STMT_END #define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END @@ -91,8 +87,6 @@ typedef int hb_mutex_impl_t; #endif -#define HB_MUTEX_INIT {HB_MUTEX_IMPL_INIT} - struct hb_mutex_t { hb_mutex_impl_t m; diff --git a/thirdparty/harfbuzz/src/hb-null.hh b/thirdparty/harfbuzz/src/hb-null.hh index d09f858cde..db38a4dfd2 100644 --- a/thirdparty/harfbuzz/src/hb-null.hh +++ b/thirdparty/harfbuzz/src/hb-null.hh @@ -39,8 +39,11 @@ #define HB_NULL_POOL_SIZE 384 -/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size, - * otherwise return sizeof(T). */ +/* Use SFINAE to sniff whether T has min_size; in which case return the larger + * of sizeof(T) and T::null_size, otherwise return sizeof(T). + * + * The main purpose of this is to let structs communicate that they are not nullable, + * by defining min_size but *not* null_size. */ /* The hard way... * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol @@ -49,8 +52,9 @@ template struct _hb_null_size : hb_integral_constant {}; template -struct _hb_null_size> : hb_integral_constant {}; - +struct _hb_null_size> + : hb_integral_constant T::null_size ? sizeof (T) : T::null_size)> {}; template using hb_null_size = _hb_null_size; #define hb_null_size(T) hb_null_size::value @@ -68,6 +72,14 @@ template using hb_static_size = _hb_static_size; #define hb_static_size(T) hb_static_size::value +template +struct _hb_min_size : hb_integral_constant {}; +template +struct _hb_min_size> : hb_integral_constant {}; +template +using hb_min_size = _hb_min_size; +#define hb_min_size(T) hb_min_size::value + /* * Null() diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh index f3048b1c3e..0e15cb12c4 100644 --- a/thirdparty/harfbuzz/src/hb-object.hh +++ b/thirdparty/harfbuzz/src/hb-object.hh @@ -140,8 +140,6 @@ struct hb_lockable_set_t * Reference-count. */ -#define HB_REFERENCE_COUNT_INIT {0} - struct hb_reference_count_t { mutable hb_atomic_int_t ref_count; @@ -197,6 +195,8 @@ struct hb_object_header_t hb_reference_count_t ref_count; mutable hb_atomic_int_t writable = 0; hb_atomic_ptr_t user_data; + + bool is_inert () const { return !ref_count.get_relaxed (); } }; #define HB_OBJECT_HEADER_STATIC {} @@ -217,7 +217,7 @@ static inline void hb_object_trace (const Type *obj, const char *function) template static inline Type *hb_object_create () { - Type *obj = (Type *) calloc (1, sizeof (Type)); + Type *obj = (Type *) hb_calloc (1, sizeof (Type)); if (unlikely (!obj)) return obj; @@ -234,11 +234,6 @@ static inline void hb_object_init (Type *obj) obj->header.user_data.init (); } template -static inline bool hb_object_is_inert (const Type *obj) -{ - return unlikely (obj->header.ref_count.is_inert ()); -} -template static inline bool hb_object_is_valid (const Type *obj) { return likely (obj->header.ref_count.is_valid ()); @@ -257,7 +252,7 @@ template static inline Type *hb_object_reference (Type *obj) { hb_object_trace (obj, HB_FUNC); - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return obj; assert (hb_object_is_valid (obj)); obj->header.ref_count.inc (); @@ -267,7 +262,7 @@ template static inline bool hb_object_destroy (Type *obj) { hb_object_trace (obj, HB_FUNC); - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return false; assert (hb_object_is_valid (obj)); if (obj->header.ref_count.dec () != 1) @@ -284,7 +279,7 @@ static inline void hb_object_fini (Type *obj) if (user_data) { user_data->fini (); - free (user_data); + hb_free (user_data); user_data = nullptr; } } @@ -295,7 +290,7 @@ static inline bool hb_object_set_user_data (Type *obj, hb_destroy_func_t destroy, hb_bool_t replace) { - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return false; assert (hb_object_is_valid (obj)); @@ -303,14 +298,14 @@ retry: hb_user_data_array_t *user_data = obj->header.user_data.get (); if (unlikely (!user_data)) { - user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1); + user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1); if (unlikely (!user_data)) return false; user_data->init (); if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data))) { user_data->fini (); - free (user_data); + hb_free (user_data); goto retry; } } @@ -322,7 +317,7 @@ template static inline void *hb_object_get_user_data (Type *obj, hb_user_data_key_t *key) { - if (unlikely (!obj || hb_object_is_inert (obj))) + if (unlikely (!obj || obj->header.is_inert ())) return nullptr; assert (hb_object_is_valid (obj)); hb_user_data_array_t *user_data = obj->header.user_data.get (); diff --git a/thirdparty/harfbuzz/src/hb-open-file.hh b/thirdparty/harfbuzz/src/hb-open-file.hh index 54c07ff13c..6eee5827c1 100644 --- a/thirdparty/harfbuzz/src/hb-open-file.hh +++ b/thirdparty/harfbuzz/src/hb-open-file.hh @@ -35,7 +35,6 @@ namespace OT { - /* * * The OpenType Font File @@ -102,7 +101,13 @@ typedef struct OpenTypeOffsetTable { Tag t; t = tag; - return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + /* Use lfind for small fonts; there are fonts that have unsorted table entries; + * those tend to work in other tools, so tolerate them. + * https://github.com/harfbuzz/harfbuzz/issues/3065 */ + if (tables.len < 16) + return tables.lfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + else + return tables.bfind (t, table_index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); } const TableRecord& get_table_by_tag (hb_tag_t tag) const { @@ -113,44 +118,53 @@ typedef struct OpenTypeOffsetTable public: - template + template >::value))> bool serialize (hb_serialize_context_t *c, hb_tag_t sfnt_tag, - hb_array_t items) + Iterator it) { TRACE_SERIALIZE (this); /* Alloc 12 for the OTHeader. */ - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); /* Write sfntVersion (bytes 0..3). */ sfnt_version = sfnt_tag; /* Take space for numTables, searchRange, entrySelector, RangeShift * and the TableRecords themselves. */ - if (unlikely (!tables.serialize (c, items.length))) return_trace (false); + unsigned num_items = it.len (); + if (unlikely (!tables.serialize (c, num_items))) return_trace (false); const char *dir_end = (const char *) c->head; HBUINT32 *checksum_adjustment = nullptr; /* Write OffsetTables, alloc for and write actual table blobs. */ - for (unsigned int i = 0; i < tables.len; i++) + unsigned i = 0; + for (hb_pair_t entry : it) { - TableRecord &rec = tables.arrayZ[i]; - hb_blob_t *blob = items[i].blob; - rec.tag = items[i].tag; - rec.length = blob->length; - rec.offset.serialize (c, this); + hb_blob_t *blob = entry.second; + unsigned len = blob->length; /* Allocate room for the table and copy it. */ - char *start = (char *) c->allocate_size (rec.length); + char *start = (char *) c->allocate_size (len); if (unlikely (!start)) return false; - if (likely (rec.length)) - memcpy (start, blob->data, rec.length); + TableRecord &rec = tables.arrayZ[i]; + rec.tag = entry.first; + rec.length = len; + rec.offset = 0; + if (unlikely (!c->check_assign (rec.offset, + (unsigned) ((char *) start - (char *) this), + HB_SERIALIZE_ERROR_OFFSET_OVERFLOW))) + return_trace (false); + + if (likely (len)) + memcpy (start, blob->data, len); /* 4-byte alignment. */ c->align (4); const char *end = (const char *) c->head; - if (items[i].tag == HB_OT_TAG_head && + if (entry.first == HB_OT_TAG_head && (unsigned) (end - start) >= head::static_size) { head *h = (head *) start; @@ -159,6 +173,7 @@ typedef struct OpenTypeOffsetTable } rec.checkSum.set_for_data (start, end - start); + i++; } tables.qsort (); @@ -170,7 +185,7 @@ typedef struct OpenTypeOffsetTable /* The following line is a slower version of the following block. */ //checksum.set_for_data (this, (const char *) c->head - (const char *) this); checksum.set_for_data (this, dir_end - (const char *) this); - for (unsigned int i = 0; i < items.length; i++) + for (unsigned int i = 0; i < num_items; i++) { TableRecord &rec = tables.arrayZ[i]; checksum = checksum + rec.checkSum; @@ -218,7 +233,7 @@ struct TTCHeaderVersion1 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - LArrayOf> + Array32Of> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: @@ -295,7 +310,7 @@ struct ResourceRecord HBINT16 nameOffset; /* Offset from beginning of resource name list * to resource name, -1 means there is none. */ HBUINT8 attrs; /* Resource attributes */ - NNOffsetTo, HBUINT24> + NNOffset24To> offset; /* Offset from beginning of data block to * data for this resource */ HBUINT32 reserved; /* Reserved for handle to resource */ @@ -330,7 +345,7 @@ struct ResourceTypeRecord protected: Tag tag; /* Resource type. */ HBUINT16 resCountM1; /* Number of resources minus 1. */ - NNOffsetTo> + NNOffset16To> resourcesZ; /* Offset from beginning of resource type list * to reference item list for this type. */ public: @@ -386,7 +401,7 @@ struct ResourceMap HBUINT32 reserved1; /* Reserved for handle to next resource map */ HBUINT16 resreved2; /* Reserved for file reference number */ HBUINT16 attrs; /* Resource fork attribute */ - NNOffsetTo> + NNOffset16To> typeList; /* Offset from beginning of map to * resource type list */ Offset16 nameList; /* Offset from beginning of map to @@ -418,10 +433,10 @@ struct ResourceForkHeader } protected: - LNNOffsetTo> + NNOffset32To> data; /* Offset from beginning of resource fork * to resource data */ - LNNOffsetTo + NNOffset32To map; /* Offset from beginning of resource fork * to resource map */ HBUINT32 dataLen; /* Length of resource data */ @@ -477,14 +492,15 @@ struct OpenTypeFontFile } } - template + template >::value))> bool serialize_single (hb_serialize_context_t *c, hb_tag_t sfnt_tag, - hb_array_t items) + Iterator items) { TRACE_SERIALIZE (this); assert (sfnt_tag != TTCTag); - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); return_trace (u.fontFace.serialize (c, sfnt_tag, items)); } diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh index dc0ae1d989..49653ce97e 100644 --- a/thirdparty/harfbuzz/src/hb-open-type.hh +++ b/thirdparty/harfbuzz/src/hb-open-type.hh @@ -196,6 +196,12 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, Index); typedef Index NameID; +struct VarIdx : HBUINT32 { + static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu; + VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; } +}; +DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx); + /* Offset, Null offset = 0 */ template struct Offset : Type @@ -206,18 +212,12 @@ struct Offset : Type bool is_null () const { return has_null && 0 == *this; } - void *serialize (hb_serialize_context_t *c, const void *base) - { - void *t = c->start_embed (); - c->check_assign (*this, (unsigned) ((char *) t - (char *) base)); - return t; - } - public: DEFINE_SIZE_STATIC (sizeof (Type)); }; typedef Offset Offset16; +typedef Offset Offset24; typedef Offset Offset32; @@ -287,7 +287,7 @@ struct _hb_has_null static Type *get_crap () { return &Crap (Type); } }; -template +template struct OffsetTo : Offset { HB_DELETE_COPY_ASSIGN (OffsetTo); @@ -319,10 +319,6 @@ struct OffsetTo : Offset hb_enable_if (hb_is_convertible (Base, void *))> friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); } - Type& serialize (hb_serialize_context_t *c, const void *base) - { - return * (Type *) Offset::serialize (c, base); - } template bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src, @@ -346,6 +342,23 @@ struct OffsetTo : Offset return ret; } + + template + bool serialize_serialize (hb_serialize_context_t *c, Ts&&... ds) + { + *this = 0; + + Type* obj = c->push (); + bool ret = obj->serialize (c, hb_forward (ds)...); + + if (ret) + c->add_link (*this, c->pop_pack ()); + else + c->pop_discard (); + + return ret; + } + /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */ /* Workaround clang bug: https://bugs.llvm.org/show_bug.cgi?id=23029 * Can't compile: whence = hb_serialize_context_t::Head followed by Ts&&... @@ -378,7 +391,7 @@ struct OffsetTo : Offset TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return_trace (false); if (unlikely (this->is_null ())) return_trace (true); - if (unlikely (!c->check_range (base, *this))) return_trace (false); + if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false); return_trace (true); } @@ -401,12 +414,14 @@ struct OffsetTo : Offset DEFINE_SIZE_STATIC (sizeof (OffsetType)); }; /* Partial specializations. */ -template -using LOffsetTo = OffsetTo; -template -using NNOffsetTo = OffsetTo; -template -using LNNOffsetTo = LOffsetTo; +template using Offset16To = OffsetTo; +template using Offset24To = OffsetTo; +template using Offset32To = OffsetTo; + +template using NNOffsetTo = OffsetTo; +template using NNOffset16To = Offset16To; +template using NNOffset24To = Offset24To; +template using NNOffset32To = Offset32To; /* @@ -453,8 +468,10 @@ struct UnsizedArrayOf const Type &lsearch (unsigned int len, const T &x, const Type ¬_found = Null (Type)) const { return *as_array (len).lsearch (x, ¬_found); } template - bool lfind (unsigned int len, const T &x, unsigned *pos = nullptr) const - { return as_array (len).lfind (x, pos); } + bool lfind (unsigned int len, const T &x, unsigned int *i = nullptr, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const + { return as_array (len).lfind (x, i, not_found, to_store); } void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1) { as_array (len).qsort (start, end); } @@ -462,7 +479,7 @@ struct UnsizedArrayOf bool serialize (hb_serialize_context_t *c, unsigned int items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend (*this, items_len))) return_trace (false); + if (unlikely (!c->extend (this, items_len))) return_trace (false); return_trace (true); } template -using UnsizedOffsetArrayOf = UnsizedArrayOf>; +using UnsizedArray16OfOffsetTo = UnsizedArrayOf>; /* Unsized array of offsets relative to the beginning of the array itself. */ template -struct UnsizedOffsetListOf : UnsizedOffsetArrayOf +struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo { const Type& operator [] (int i_) const { @@ -538,7 +555,7 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace ((UnsizedOffsetArrayOf + return_trace ((UnsizedArray16OfOffsetTo ::sanitize (c, count, this, hb_forward (ds)...))); } }; @@ -562,14 +579,14 @@ struct SortedUnsizedArrayOf : UnsizedArrayOf { return *as_array (len).bsearch (x, ¬_found); } template bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, unsigned int to_store = (unsigned int) -1) const { return as_array (len).bfind (x, i, not_found, to_store); } }; /* An array with a number of elements. */ -template +template struct ArrayOf { typedef Type item_t; @@ -617,17 +634,32 @@ struct ArrayOf hb_array_t sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) { return as_array ().sub_array (start_offset, count); } - hb_success_t serialize (hb_serialize_context_t *c, unsigned items_len) + template + Type &lsearch (const T &x, Type ¬_found = Crap (Type)) + { return *as_array ().lsearch (x, ¬_found); } + template + const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const + { return *as_array ().lsearch (x, ¬_found); } + template + bool lfind (const T &x, unsigned int *i = nullptr, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, + unsigned int to_store = (unsigned int) -1) const + { return as_array ().lfind (x, i, not_found, to_store); } + + void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) + { as_array ().qsort (start, end); } + + HB_NODISCARD bool serialize (hb_serialize_context_t *c, unsigned items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return_trace (false); - c->check_assign (len, items_len); - if (unlikely (!c->extend (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); + c->check_assign (len, items_len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); + if (unlikely (!c->extend (this))) return_trace (false); return_trace (true); } template - hb_success_t serialize (hb_serialize_context_t *c, Iterator items) + HB_NODISCARD bool serialize (hb_serialize_context_t *c, Iterator items) { TRACE_SERIALIZE (this); unsigned count = items.len (); @@ -643,7 +675,7 @@ struct ArrayOf { TRACE_SERIALIZE (this); len++; - if (unlikely (!len || !c->extend (*this))) + if (unlikely (!len || !c->extend (this))) { len--; return_trace (nullptr); @@ -656,7 +688,7 @@ struct ArrayOf TRACE_SERIALIZE (this); auto *out = c->start_embed (this); if (unlikely (!c->extend_min (out))) return_trace (nullptr); - c->check_assign (out->len, len); + c->check_assign (out->len, len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); if (unlikely (!as_array ().copy (c))) return_trace (nullptr); return_trace (out); } @@ -674,19 +706,6 @@ struct ArrayOf return_trace (true); } - template - Type &lsearch (const T &x, Type ¬_found = Crap (Type)) - { return *as_array ().lsearch (x, ¬_found); } - template - const Type &lsearch (const T &x, const Type ¬_found = Null (Type)) const - { return *as_array ().lsearch (x, ¬_found); } - template - bool lfind (const T &x, unsigned *pos = nullptr) const - { return as_array ().lfind (x, pos); } - - void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1) - { as_array ().qsort (start, end); } - bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -699,21 +718,18 @@ struct ArrayOf public: DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ); }; -template -using LArrayOf = ArrayOf; +template using Array16Of = ArrayOf; +template using Array32Of = ArrayOf; using PString = ArrayOf; /* Array of Offset's */ -template -using OffsetArrayOf = ArrayOf>; -template -using LOffsetArrayOf = ArrayOf>; -template -using LOffsetLArrayOf = ArrayOf, HBUINT32>; +template using Array16OfOffset16To = ArrayOf, HBUINT16>; +template using Array16OfOffset32To = ArrayOf, HBUINT16>; +template using Array32OfOffset32To = ArrayOf, HBUINT32>; /* Array of offsets relative to the beginning of the array itself. */ template -struct OffsetListOf : OffsetArrayOf +struct List16OfOffset16To : Array16OfOffset16To { const Type& operator [] (int i_) const { @@ -731,7 +747,7 @@ struct OffsetListOf : OffsetArrayOf bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - struct OffsetListOf *out = c->serializer->embed (*this); + struct List16OfOffset16To *out = c->serializer->embed (*this); if (unlikely (!out)) return_trace (false); unsigned int count = this->len; for (unsigned int i = 0; i < count; i++) @@ -743,7 +759,7 @@ struct OffsetListOf : OffsetArrayOf bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const { TRACE_SANITIZE (this); - return_trace (OffsetArrayOf::sanitize (c, this, hb_forward (ds)...)); + return_trace (Array16OfOffset16To::sanitize (c, this, hb_forward (ds)...)); } }; @@ -786,9 +802,9 @@ struct HeadlessArrayOf bool serialize (hb_serialize_context_t *c, unsigned int items_len) { TRACE_SERIALIZE (this); - if (unlikely (!c->extend_min (*this))) return_trace (false); - c->check_assign (lenP1, items_len + 1); - if (unlikely (!c->extend (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); + c->check_assign (lenP1, items_len + 1, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW); + if (unlikely (!c->extend (this))) return_trace (false); return_trace (true); } template dispatch (arrayZ[i], hb_forward (ds)...))) @@ -882,7 +899,7 @@ struct ArrayOfM1 }; /* An array with sorted elements. Supports binary searching. */ -template +template struct SortedArrayOf : ArrayOf { hb_sorted_array_t< Type> as_array () { return hb_sorted_array (this->arrayZ, this->len); } @@ -928,11 +945,14 @@ struct SortedArrayOf : ArrayOf { return *as_array ().bsearch (x, ¬_found); } template bool bfind (const T &x, unsigned int *i = nullptr, - hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE, + hb_not_found_t not_found = HB_NOT_FOUND_DONT_STORE, unsigned int to_store = (unsigned int) -1) const { return as_array ().bfind (x, i, not_found, to_store); } }; +template using SortedArray16Of = SortedArrayOf; +template using SortedArray32Of = SortedArrayOf; + /* * Binary-search arrays */ diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh index 864a27f458..eaaf5e12ec 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh @@ -126,7 +126,7 @@ struct CFFIndex else { /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); this->count = byteArray.length; this->offSize = offSize_; if (unlikely (!c->allocate_size (offSize_ * (byteArray.length + 1)))) @@ -214,7 +214,7 @@ struct CFFIndex unsigned off_size = calcOffSize (total); /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); this->count = it.len (); this->offSize = off_size; if (unlikely (!c->allocate_size (off_size * (it.len () + 1)))) @@ -335,7 +335,7 @@ struct CFFIndexOf : CFFIndex { TRACE_SERIALIZE (this); /* serialize CFFIndex header */ - if (unlikely (!c->extend_min (*this))) return_trace (false); + if (unlikely (!c->extend_min (this))) return_trace (false); this->count = dataArrayLen; this->offSize = offSize_; if (unlikely (!c->allocate_size (offSize_ * (dataArrayLen + 1)))) diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh index 7228f77727..5dd183e3a0 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh @@ -187,7 +187,7 @@ struct Encoding const hb_vector_t& supp_codes) { TRACE_SERIALIZE (this); - Encoding *dest = c->extend_min (*this); + Encoding *dest = c->extend_min (this); if (unlikely (!dest)) return_trace (false); dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0); switch (format) { @@ -457,7 +457,7 @@ struct Charset const hb_vector_t& sid_ranges) { TRACE_SERIALIZE (this); - Charset *dest = c->extend_min (*this); + Charset *dest = c->extend_min (this); if (unlikely (!dest)) return_trace (false); dest->format = format; switch (format) @@ -713,6 +713,7 @@ struct cff1_top_dict_opset_t : top_dict_opset_t case OpCode_Notice: case OpCode_Copyright: case OpCode_FullName: + case OpCode_FontName: case OpCode_FamilyName: case OpCode_Weight: case OpCode_PostScript: @@ -1390,7 +1391,7 @@ struct cff1 public: FixedVersion version; /* Version of CFF table. set to 0x0100u */ - OffsetTo nameIndex; /* headerSize = Offset to Name INDEX. */ + NNOffsetTo nameIndex; /* headerSize = Offset to Name INDEX. */ HBUINT8 offSize; /* offset size (unused?) */ public: diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh index 878e02ff17..b904bb46a8 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh @@ -49,6 +49,12 @@ struct CmapSubtableFormat0 *glyph = gid; return true; } + + unsigned get_language () const + { + return language; + } + void collect_unicodes (hb_set_t *out) const { for (unsigned int i = 0; i < 256; i++) @@ -212,29 +218,24 @@ struct CmapSubtableFormat4 HBINT16 *idDelta, unsigned segcount) { + hb_hashmap_t cp_to_gid; + + it | hb_sink (cp_to_gid); + HBUINT16 *idRangeOffset = c->allocate_size (HBUINT16::static_size * segcount); if (unlikely (!c->check_success (idRangeOffset))) return nullptr; if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr; - + hb_range (segcount) - | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }) - | hb_apply ([&] (const unsigned i) - { - idRangeOffset[i] = 2 * (c->start_embed () - idRangeOffset - i); - - + it - | hb_filter ([&] (const hb_item_type _) { return _.first >= startCode[i] && _.first <= endCode[i]; }) - | hb_apply ([&] (const hb_item_type _) - { - HBUINT16 glyID; - glyID = _.second; - c->copy (glyID); - }) - ; - - - }) - ; + for (unsigned i : + hb_range (segcount) + | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; })) + { + idRangeOffset[i] = 2 * (c->start_embed () - idRangeOffset - i); + for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++) + { + HBUINT16 gid; + gid = cp_to_gid[cp]; + c->copy (gid); + } + } return idRangeOffset; } @@ -253,7 +254,7 @@ struct CmapSubtableFormat4 if (format4_iter.len () == 0) return; unsigned table_initpos = c->length (); - if (unlikely (!c->extend_min (*this))) return; + if (unlikely (!c->extend_min (this))) return; this->format = 4; //serialize endCode[] @@ -276,7 +277,17 @@ struct CmapSubtableFormat4 HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount); if (unlikely (!c->check_success (idRangeOffset))) return; - if (unlikely (!c->check_assign(this->length, c->length () - table_initpos))) return; + this->length = c->length () - table_initpos; + if ((long long) this->length != (long long) c->length () - table_initpos) + { + // Length overflowed. Discard the current object before setting the error condition, otherwise + // discard is a noop which prevents the higher level code from reverting the serializer to the + // pre-error state in cmap4 overflow handling code. + c->pop_discard (); + c->err (HB_SERIALIZE_ERROR_INT_OVERFLOW); + return; + } + this->segCountX2 = segcount * 2; this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1; this->searchRange = 2 * (1u << this->entrySelector); @@ -285,6 +296,11 @@ struct CmapSubtableFormat4 : 0; } + unsigned get_language () const + { + return language; + } + struct accelerator_t { accelerator_t () {} @@ -547,6 +563,12 @@ struct CmapSubtableTrimmed *glyph = gid; return true; } + + unsigned get_language () const + { + return language; + } + void collect_unicodes (hb_set_t *out) const { hb_codepoint_t start = startCharCode; @@ -606,6 +628,11 @@ struct CmapSubtableLongSegmented return true; } + unsigned get_language () const + { + return language; + } + void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const { for (unsigned int i = 0; i < this->groups.len; i++) @@ -670,7 +697,7 @@ struct CmapSubtableLongSegmented HBUINT16 reserved; /* Reserved; set to 0. */ HBUINT32 length; /* Byte length of this subtable. */ HBUINT32 language; /* Ignore. */ - SortedArrayOf + SortedArray32Of groups; /* Groupings. */ public: DEFINE_SIZE_ARRAY (16, groups); @@ -691,7 +718,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented { if (it.len () == 0) return; unsigned table_initpos = c->length (); - if (unlikely (!c->extend_min (*this))) return; + if (unlikely (!c->extend_min (this))) return; hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF; hb_codepoint_t glyphID = 0; @@ -784,7 +811,7 @@ struct UnicodeValueRange DEFINE_SIZE_STATIC (4); }; -struct DefaultUVS : SortedArrayOf +struct DefaultUVS : SortedArray32Of { void collect_unicodes (hb_set_t *out) const { @@ -850,7 +877,9 @@ struct DefaultUVS : SortedArrayOf } else { - if (unlikely (!c->check_assign (out->len, (c->length () - init_len) / UnicodeValueRange::static_size))) return nullptr; + if (unlikely (!c->check_assign (out->len, + (c->length () - init_len) / UnicodeValueRange::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW))) return nullptr; return out; } } @@ -876,23 +905,21 @@ struct UVSMapping DEFINE_SIZE_STATIC (5); }; -struct NonDefaultUVS : SortedArrayOf +struct NonDefaultUVS : SortedArray32Of { void collect_unicodes (hb_set_t *out) const { - unsigned int count = len; - for (unsigned int i = 0; i < count; i++) - out->add (arrayZ[i].unicodeValue); + for (const auto& a : as_array ()) + out->add (a.unicodeValue); } void collect_mapping (hb_set_t *unicodes, /* OUT */ hb_map_t *mapping /* OUT */) const { - unsigned count = len; - for (unsigned i = 0; i < count; i++) + for (const auto& a : as_array ()) { - hb_codepoint_t unicode = arrayZ[i].unicodeValue; - hb_codepoint_t glyphid = arrayZ[i].glyphID; + hb_codepoint_t unicode = a.unicodeValue; + hb_codepoint_t glyphid = a.glyphID; unicodes->add (unicode); mapping->set (unicode, glyphid); } @@ -1041,9 +1068,9 @@ struct VariationSelectorRecord } HBUINT24 varSelector; /* Variation selector. */ - LOffsetTo + Offset32To defaultUVS; /* Offset to Default UVS Table. May be 0. */ - LOffsetTo + Offset32To nonDefaultUVS; /* Offset to Non-Default UVS Table. May be 0. */ public: DEFINE_SIZE_STATIC (11); @@ -1058,9 +1085,8 @@ struct CmapSubtableFormat14 void collect_variation_selectors (hb_set_t *out) const { - unsigned int count = record.len; - for (unsigned int i = 0; i < count; i++) - out->add (record.arrayZ[i].varSelector); + for (const auto& a : record.as_array ()) + out->add (a.varSelector); } void collect_variation_unicodes (hb_codepoint_t variation_selector, hb_set_t *out) const @@ -1076,7 +1102,7 @@ struct CmapSubtableFormat14 unsigned table_initpos = c->length (); const char* init_tail = c->tail; - if (unlikely (!c->extend_min (*this))) return; + if (unlikely (!c->extend_min (this))) return; this->format = 14; auto src_tbl = reinterpret_cast (base); @@ -1112,10 +1138,12 @@ struct CmapSubtableFormat14 return; int tail_len = init_tail - c->tail; - c->check_assign (this->length, c->length () - table_initpos + tail_len); + c->check_assign (this->length, c->length () - table_initpos + tail_len, + HB_SERIALIZE_ERROR_INT_OVERFLOW); c->check_assign (this->record.len, (c->length () - table_initpos - CmapSubtableFormat14::min_size) / - VariationSelectorRecord::static_size); + VariationSelectorRecord::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW); /* Correct the incorrect write order by reversing the order of the variation records array. */ @@ -1180,7 +1208,7 @@ struct CmapSubtableFormat14 protected: HBUINT16 format; /* Format number is set to 14. */ HBUINT32 length; /* Byte length of this subtable. */ - SortedArrayOf + SortedArray32Of record; /* Variation selector records; sorted * in increasing order of `varSelector'. */ public: @@ -1235,6 +1263,20 @@ struct CmapSubtable } } + unsigned get_language () const + { + switch (u.format) { + case 0: return u.format0 .get_language (); + case 4: return u.format4 .get_language (); + case 6: return u.format6 .get_language (); + case 10: return u.format10.get_language (); + case 12: return u.format12.get_language (); + case 13: return u.format13.get_language (); + case 14: + default: return 0; + } + } + template void serialize (hb_serialize_context_t *c, @@ -1338,7 +1380,7 @@ struct EncodingRecord HBUINT16 platformID; /* Platform ID. */ HBUINT16 encodingID; /* Platform-specific encoding ID. */ - LOffsetTo + Offset32To subtable; /* Byte offset from beginning of table to the subtable for this encoding. */ public: DEFINE_SIZE_STATIC (8); @@ -1350,58 +1392,112 @@ struct cmap template - void serialize (hb_serialize_context_t *c, + bool serialize (hb_serialize_context_t *c, Iterator it, EncodingRecIter encodingrec_iter, const void *base, - const hb_subset_plan_t *plan) + const hb_subset_plan_t *plan, + bool drop_format_4 = false) { - if (unlikely (!c->extend_min ((*this)))) return; + if (unlikely (!c->extend_min ((*this)))) return false; this->version = 0; unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0; + auto snap = c->snapshot (); for (const EncodingRecord& _ : encodingrec_iter) { + if (c->in_error ()) + return false; + unsigned format = (base+_.subtable).u.format; - if (!plan->glyphs_requested->is_empty ()) + if (format != 4 && format != 12 && format != 14) continue; + + hb_set_t unicodes_set; + (base+_.subtable).collect_unicodes (&unicodes_set); + + if (!drop_format_4 && format == 4) { - hb_set_t unicodes_set; - hb_map_t cp_glyphid_map; - (base+_.subtable).collect_mapping (&unicodes_set, &cp_glyphid_map); - - auto table_iter = - + hb_zip (unicodes_set.iter(), unicodes_set.iter() | hb_map(cp_glyphid_map)) - | hb_filter (plan->_glyphset, hb_second) - | hb_filter ([plan] (const hb_pair_t& p) - { - return plan->unicodes->has (p.first) || - plan->glyphs_requested->has (p.second); - }) - | hb_map ([plan] (const hb_pair_t& p_org) - { - return hb_pair_t (p_org.first, plan->glyph_map->get(p_org.second)); - }) - ; - - if (format == 4) c->copy (_, table_iter, 4u, base, plan, &format4objidx); - else if (format == 12) c->copy (_, table_iter, 12u, base, plan, &format12objidx); - else if (format == 14) c->copy (_, table_iter, 14u, base, plan, &format14objidx); + c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx); + if (c->in_error () && c->only_overflow ()) + { + // cmap4 overflowed, reset and retry serialization without format 4 subtables. + c->revert (snap); + return serialize (c, it, + encodingrec_iter, + base, + plan, + true); + } } - /* when --gids option is not used, we iterate input unicodes instead of - * all codepoints in each subtable, which is more efficient */ - else + + else if (format == 12) { - hb_set_t unicodes_set; - (base+_.subtable).collect_unicodes (&unicodes_set); - - if (format == 4) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx); - else if (format == 12) c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx); - else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx); + if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue; + c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx); } + else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx); + } + c->check_assign(this->encodingRecord.len, + (c->length () - cmap::min_size)/EncodingRecord::static_size, + HB_SERIALIZE_ERROR_INT_OVERFLOW); + + // Fail if format 4 was dropped and there is no cmap12. + return !drop_format_4 || format12objidx; + } + + template + bool _can_drop (const EncodingRecord& cmap12, + const hb_set_t& cmap12_unicodes, + const void* base, + Iterator subset_unicodes, + EncodingRecordIterator encoding_records) + { + for (auto cp : + subset_unicodes | hb_filter (cmap12_unicodes)) + { + if (cp >= 0x10000) return false; } - c->check_assign(this->encodingRecord.len, (c->length () - cmap::min_size)/EncodingRecord::static_size); + unsigned target_platform; + unsigned target_encoding; + unsigned target_language = (base+cmap12.subtable).get_language (); + + if (cmap12.platformID == 0 && cmap12.encodingID == 4) + { + target_platform = 0; + target_encoding = 3; + } else if (cmap12.platformID == 3 && cmap12.encodingID == 10) { + target_platform = 3; + target_encoding = 1; + } else { + return false; + } + + for (const auto& _ : encoding_records) + { + if (_.platformID != target_platform + || _.encodingID != target_encoding + || (base+_.subtable).get_language() != target_language) + continue; + + hb_set_t sibling_unicodes; + (base+_.subtable).collect_unicodes (&sibling_unicodes); + + auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes); + auto sibling = + subset_unicodes | hb_filter (sibling_unicodes); + for (; cmap12 && sibling; cmap12++, sibling++) + { + unsigned a = *cmap12; + unsigned b = *sibling; + if (a != b) return false; + } + + return !cmap12 && !sibling; + } + + return false; } void closure_glyphs (const hb_set_t *unicodes, @@ -1468,8 +1564,8 @@ struct cmap | hb_filter ([&] (const hb_pair_t _) { return (_.second != HB_MAP_VALUE_INVALID); }) ; - cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan); - return_trace (true); + + return_trace (cmap_prime->serialize (c->serializer, it, encodingrec_iter, this, c->plan)); } const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const @@ -1697,7 +1793,7 @@ struct cmap protected: HBUINT16 version; /* Table version number (0). */ - SortedArrayOf + SortedArray16Of encodingRecord; /* Encoding tables. */ public: DEFINE_SIZE_ARRAY (4, encodingRecord); diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh index e285acec3d..6c31d1b53e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh @@ -510,7 +510,7 @@ struct IndexSubtableRecord HBGlyphID firstGlyphIndex; HBGlyphID lastGlyphIndex; - LOffsetTo offsetToSubtable; + Offset32To offsetToSubtable; public: DEFINE_SIZE_STATIC (8); }; @@ -672,7 +672,7 @@ struct BitmapSizeTable } protected: - LNNOffsetTo + NNOffset32To indexSubtableArrayOffset; HBUINT32 indexTablesSize; HBUINT32 numberOfIndexSubtables; @@ -697,7 +697,7 @@ struct BitmapSizeTable struct GlyphBitmapDataFormat17 { SmallGlyphMetrics glyphMetrics; - LArrayOf data; + Array32Of data; public: DEFINE_SIZE_ARRAY (9, data); }; @@ -705,14 +705,14 @@ struct GlyphBitmapDataFormat17 struct GlyphBitmapDataFormat18 { BigGlyphMetrics glyphMetrics; - LArrayOf data; + Array32Of data; public: DEFINE_SIZE_ARRAY (12, data); }; struct GlyphBitmapDataFormat19 { - LArrayOf data; + Array32Of data; public: DEFINE_SIZE_ARRAY (4, data); }; @@ -738,7 +738,7 @@ struct CBLC cbdt_prime->length, HB_MEMORY_MODE_WRITABLE, cbdt_prime->arrayZ, - free); + hb_free); cbdt_prime->init (); // Leak arrayZ to the blob. bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob); hb_blob_destroy (cbdt_prime_blob); @@ -798,7 +798,7 @@ struct CBLC protected: FixedVersion<> version; - LArrayOf sizeTables; + Array32Of sizeTables; public: DEFINE_SIZE_ARRAY (8, sizeTables); }; diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh index e2a1ff4662..007ff3f47b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh @@ -29,6 +29,7 @@ #define HB_OT_COLOR_COLR_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" /* * COLR -- Color @@ -36,9 +37,78 @@ */ #define HB_OT_TAG_COLR HB_TAG('C','O','L','R') +#ifndef COLRV1_MAX_NESTING_LEVEL +#define COLRV1_MAX_NESTING_LEVEL 100 +#endif + +#ifndef COLRV1_ENABLE_SUBSETTING +#define COLRV1_ENABLE_SUBSETTING 0 +#endif namespace OT { +struct COLR; +struct hb_colrv1_closure_context_t : + hb_dispatch_context_t +{ + template + return_t dispatch (const T &obj) + { + if (unlikely (nesting_level_left == 0)) + return hb_empty_t (); + + if (paint_visited (&obj)) + return hb_empty_t (); + + nesting_level_left--; + obj.closurev1 (this); + nesting_level_left++; + return hb_empty_t (); + } + static return_t default_return_value () { return hb_empty_t (); } + + bool paint_visited (const void *paint) + { + hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) paint - (uintptr_t) base); + if (visited_paint.has (delta)) + return true; + + visited_paint.add (delta); + return false; + } + + const COLR* get_colr_table () const + { return reinterpret_cast (base); } + + void add_glyph (unsigned glyph_id) + { glyphs->add (glyph_id); } + + void add_layer_indices (unsigned first_layer_index, unsigned num_of_layers) + { layer_indices->add_range (first_layer_index, first_layer_index + num_of_layers - 1); } + + void add_palette_index (unsigned palette_index) + { palette_indices->add (palette_index); } + + public: + const void *base; + hb_set_t visited_paint; + hb_set_t *glyphs; + hb_set_t *layer_indices; + hb_set_t *palette_indices; + unsigned nesting_level_left; + + hb_colrv1_closure_context_t (const void *base_, + hb_set_t *glyphs_, + hb_set_t *layer_indices_, + hb_set_t *palette_indices_, + unsigned nesting_level_left_ = COLRV1_MAX_NESTING_LEVEL) : + base (base_), + glyphs (glyphs_), + layer_indices (layer_indices_), + palette_indices (palette_indices_), + nesting_level_left (nesting_level_left_) + {} +}; struct LayerRecord { @@ -90,6 +160,707 @@ struct BaseGlyphRecord DEFINE_SIZE_STATIC (6); }; +template +struct Variable +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + T value; + VarIdx varIdx; + public: + DEFINE_SIZE_STATIC (4 + T::static_size); +}; + +template +struct NoVariable +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + T value; + public: + DEFINE_SIZE_STATIC (T::static_size); +}; + +// Color structures + +template class Var> +struct ColorIndex +{ + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (*this); + if (unlikely (!out)) return_trace (false); + return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes->get (paletteIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT16 paletteIndex; + Var alpha; + public: + DEFINE_SIZE_STATIC (2 + Var::static_size); +}; + +template class Var> +struct ColorStop +{ + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + if (unlikely (!c->serializer->embed (stopOffset))) return_trace (false); + return_trace (color.subset (c)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + Var stopOffset; + ColorIndex color; + public: + DEFINE_SIZE_STATIC (Var::static_size + ColorIndex::static_size); +}; + +struct Extend : HBUINT8 +{ + enum { + EXTEND_PAD = 0, + EXTEND_REPEAT = 1, + EXTEND_REFLECT = 2, + }; + public: + DEFINE_SIZE_STATIC (1); +}; + +template class Var> +struct ColorLine +{ + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!out)) return_trace (false); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + if (!c->serializer->check_assign (out->extend, extend, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false); + if (!c->serializer->check_assign (out->stops.len, stops.len, HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)) return_trace (false); + + for (const auto& stop : stops.iter ()) + { + if (!stop.subset (c)) return_trace (false); + } + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + stops.sanitize (c)); + } + + Extend extend; + Array16Of> stops; + public: + DEFINE_SIZE_ARRAY_SIZED (3, stops); +}; + +// Composition modes + +// Compositing modes are taken from https://www.w3.org/TR/compositing-1/ +// NOTE: a brief audit of major implementations suggests most support most +// or all of the specified modes. +struct CompositeMode : HBUINT8 +{ + enum { + // Porter-Duff modes + // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators + COMPOSITE_CLEAR = 0, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_clear + COMPOSITE_SRC = 1, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_src + COMPOSITE_DEST = 2, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dst + COMPOSITE_SRC_OVER = 3, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcover + COMPOSITE_DEST_OVER = 4, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstover + COMPOSITE_SRC_IN = 5, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin + COMPOSITE_DEST_IN = 6, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstin + COMPOSITE_SRC_OUT = 7, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcout + COMPOSITE_DEST_OUT = 8, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstout + COMPOSITE_SRC_ATOP = 9, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcatop + COMPOSITE_DEST_ATOP = 10, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_dstatop + COMPOSITE_XOR = 11, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_xor + COMPOSITE_PLUS = 12, // https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_plus + + // Blend modes + // https://www.w3.org/TR/compositing-1/#blending + COMPOSITE_SCREEN = 13, // https://www.w3.org/TR/compositing-1/#blendingscreen + COMPOSITE_OVERLAY = 14, // https://www.w3.org/TR/compositing-1/#blendingoverlay + COMPOSITE_DARKEN = 15, // https://www.w3.org/TR/compositing-1/#blendingdarken + COMPOSITE_LIGHTEN = 16, // https://www.w3.org/TR/compositing-1/#blendinglighten + COMPOSITE_COLOR_DODGE = 17, // https://www.w3.org/TR/compositing-1/#blendingcolordodge + COMPOSITE_COLOR_BURN = 18, // https://www.w3.org/TR/compositing-1/#blendingcolorburn + COMPOSITE_HARD_LIGHT = 19, // https://www.w3.org/TR/compositing-1/#blendinghardlight + COMPOSITE_SOFT_LIGHT = 20, // https://www.w3.org/TR/compositing-1/#blendingsoftlight + COMPOSITE_DIFFERENCE = 21, // https://www.w3.org/TR/compositing-1/#blendingdifference + COMPOSITE_EXCLUSION = 22, // https://www.w3.org/TR/compositing-1/#blendingexclusion + COMPOSITE_MULTIPLY = 23, // https://www.w3.org/TR/compositing-1/#blendingmultiply + + // Modes that, uniquely, do not operate on components + // https://www.w3.org/TR/compositing-1/#blendingnonseparable + COMPOSITE_HSL_HUE = 24, // https://www.w3.org/TR/compositing-1/#blendinghue + COMPOSITE_HSL_SATURATION = 25, // https://www.w3.org/TR/compositing-1/#blendingsaturation + COMPOSITE_HSL_COLOR = 26, // https://www.w3.org/TR/compositing-1/#blendingcolor + COMPOSITE_HSL_LUMINOSITY = 27, // https://www.w3.org/TR/compositing-1/#blendingluminosity + }; + public: + DEFINE_SIZE_STATIC (1); +}; + +template class Var> +struct Affine2x3 +{ + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + Var xx; + Var yx; + Var xy; + Var yy; + Var dx; + Var dy; + public: + DEFINE_SIZE_STATIC (6 * Var::static_size); +}; + +struct PaintColrLayers +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + return_trace (c->serializer->check_assign (out->firstLayerIndex, c->plan->colrv1_layers->get (firstLayerIndex), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 1 */ + HBUINT8 numLayers; + HBUINT32 firstLayerIndex; /* index into COLRv1::layersV1 */ + public: + DEFINE_SIZE_STATIC (6); +}; + +template class Var> +struct PaintSolid +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { c->add_palette_index (color.paletteIndex); } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + if (unlikely (!c->serializer->embed (format))) return_trace (false); + return_trace (color.subset (c)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 2(noVar) or 3(Var)*/ + ColorIndex color; + public: + DEFINE_SIZE_STATIC (1 + ColorIndex::static_size); +}; + +template class Var> +struct PaintLinearGradient +{ + void closurev1 (hb_colrv1_closure_context_t* c) const + { + for (const auto &stop : (this+colorLine).stops.iter ()) + c->add_palette_index (stop.color.paletteIndex); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->colorLine.serialize_subset (c, colorLine, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 4(noVar) or 5 (Var) */ + Offset24To> colorLine; /* Offset (from beginning of PaintLinearGradient + * table) to ColorLine subtable. */ + Var x0; + Var y0; + Var x1; + Var y1; + Var x2; + Var y2; + public: + DEFINE_SIZE_STATIC (4 + 6 * Var::static_size); +}; + +template class Var> +struct PaintRadialGradient +{ + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->colorLine.serialize_subset (c, colorLine, this)); + } + + void closurev1 (hb_colrv1_closure_context_t* c) const + { + for (const auto &stop : (this+colorLine).stops.iter ()) + c->add_palette_index (stop.color.paletteIndex); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 6(noVar) or 7 (Var) */ + Offset24To> colorLine; /* Offset (from beginning of PaintRadialGradient + * table) to ColorLine subtable. */ + Var x0; + Var y0; + Var radius0; + Var x1; + Var y1; + Var radius1; + public: + DEFINE_SIZE_STATIC (4 + 6 * Var::static_size); +}; + +template class Var> +struct PaintSweepGradient +{ + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->colorLine.serialize_subset (c, colorLine, this)); + } + + void closurev1 (hb_colrv1_closure_context_t* c) const + { + for (const auto &stop : (this+colorLine).stops.iter ()) + c->add_palette_index (stop.color.paletteIndex); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && colorLine.sanitize (c, this)); + } + + HBUINT8 format; /* format = 8(noVar) or 9 (Var) */ + Offset24To> colorLine; /* Offset (from beginning of PaintSweepGradient + * table) to ColorLine subtable. */ + Var centerX; + Var centerY; + Var startAngle; + Var endAngle; + public: + DEFINE_SIZE_STATIC (2 * Var::static_size + 2 * Var::static_size); +}; + +struct Paint; +// Paint a non-COLR glyph, filled as indicated by paint. +struct PaintGlyph +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + if (! c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid), + HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + return_trace (out->paint.serialize_subset (c, paint, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && paint.sanitize (c, this)); + } + + HBUINT8 format; /* format = 10 */ + Offset24To paint; /* Offset (from beginning of PaintGlyph table) to Paint subtable. */ + HBUINT16 gid; + public: + DEFINE_SIZE_STATIC (6); +}; + +struct PaintColrGlyph +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (c->serializer->check_assign (out->gid, c->plan->glyph_map->get (gid), + HB_SERIALIZE_ERROR_INT_OVERFLOW)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + HBUINT8 format; /* format = 11 */ + HBUINT16 gid; + public: + DEFINE_SIZE_STATIC (3); +}; + +template class Var> +struct PaintTransform +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 12(noVar) or 13 (Var) */ + Offset24To src; /* Offset (from beginning of PaintTransform table) to Paint subtable. */ + Affine2x3 transform; + public: + DEFINE_SIZE_STATIC (4 + Affine2x3::static_size); +}; + +template class Var> +struct PaintTranslate +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 14(noVar) or 15 (Var) */ + Offset24To src; /* Offset (from beginning of PaintTranslate table) to Paint subtable. */ + Var dx; + Var dy; + public: + DEFINE_SIZE_STATIC (4 + Var::static_size); +}; + +template class Var> +struct PaintRotate +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 16 (noVar) or 17(Var) */ + Offset24To src; /* Offset (from beginning of PaintRotate table) to Paint subtable. */ + Var angle; + Var centerX; + Var centerY; + public: + DEFINE_SIZE_STATIC (4 + 3 * Var::static_size); +}; + +template class Var> +struct PaintSkew +{ + HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + return_trace (out->src.serialize_subset (c, src, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && src.sanitize (c, this)); + } + + HBUINT8 format; /* format = 18(noVar) or 19 (Var) */ + Offset24To src; /* Offset (from beginning of PaintSkew table) to Paint subtable. */ + Var xSkewAngle; + Var ySkewAngle; + Var centerX; + Var centerY; + public: + DEFINE_SIZE_STATIC (4 + 4 * Var::static_size); +}; + +struct PaintComposite +{ + void closurev1 (hb_colrv1_closure_context_t* c) const; + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->embed (this); + if (unlikely (!out)) return_trace (false); + + if (!out->src.serialize_subset (c, src, this)) return_trace (false); + return_trace (out->backdrop.serialize_subset (c, backdrop, this)); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + src.sanitize (c, this) && + backdrop.sanitize (c, this)); + } + + HBUINT8 format; /* format = 20 */ + Offset24To src; /* Offset (from beginning of PaintComposite table) to source Paint subtable. */ + CompositeMode mode; /* If mode is unrecognized use COMPOSITE_CLEAR */ + Offset24To backdrop; /* Offset (from beginning of PaintComposite table) to backdrop Paint subtable. */ + public: + DEFINE_SIZE_STATIC (8); +}; + +struct Paint +{ + template + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + TRACE_DISPATCH (this, u.format); + if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); + switch (u.format) { + case 1: return_trace (c->dispatch (u.paintformat1, hb_forward (ds)...)); + case 2: return_trace (c->dispatch (u.paintformat2, hb_forward (ds)...)); + case 3: return_trace (c->dispatch (u.paintformat3, hb_forward (ds)...)); + case 4: return_trace (c->dispatch (u.paintformat4, hb_forward (ds)...)); + case 5: return_trace (c->dispatch (u.paintformat5, hb_forward (ds)...)); + case 6: return_trace (c->dispatch (u.paintformat6, hb_forward (ds)...)); + case 7: return_trace (c->dispatch (u.paintformat7, hb_forward (ds)...)); + case 8: return_trace (c->dispatch (u.paintformat8, hb_forward (ds)...)); + case 9: return_trace (c->dispatch (u.paintformat9, hb_forward (ds)...)); + case 10: return_trace (c->dispatch (u.paintformat10, hb_forward (ds)...)); + case 11: return_trace (c->dispatch (u.paintformat11, hb_forward (ds)...)); + case 12: return_trace (c->dispatch (u.paintformat12, hb_forward (ds)...)); + case 13: return_trace (c->dispatch (u.paintformat13, hb_forward (ds)...)); + case 14: return_trace (c->dispatch (u.paintformat14, hb_forward (ds)...)); + case 15: return_trace (c->dispatch (u.paintformat15, hb_forward (ds)...)); + case 16: return_trace (c->dispatch (u.paintformat16, hb_forward (ds)...)); + case 17: return_trace (c->dispatch (u.paintformat17, hb_forward (ds)...)); + case 18: return_trace (c->dispatch (u.paintformat18, hb_forward (ds)...)); + case 19: return_trace (c->dispatch (u.paintformat19, hb_forward (ds)...)); + case 20: return_trace (c->dispatch (u.paintformat20, hb_forward (ds)...)); + default:return_trace (c->default_return_value ()); + } + } + + protected: + union { + HBUINT8 format; + PaintColrLayers paintformat1; + PaintSolid paintformat2; + PaintSolid paintformat3; + PaintLinearGradient paintformat4; + PaintLinearGradient paintformat5; + PaintRadialGradient paintformat6; + PaintRadialGradient paintformat7; + PaintSweepGradient paintformat8; + PaintSweepGradient paintformat9; + PaintGlyph paintformat10; + PaintColrGlyph paintformat11; + PaintTransform paintformat12; + PaintTransform paintformat13; + PaintTranslate paintformat14; + PaintTranslate paintformat15; + PaintRotate paintformat16; + PaintRotate paintformat17; + PaintSkew paintformat18; + PaintSkew paintformat19; + PaintComposite paintformat20; + } u; +}; + +struct BaseGlyphV1Record +{ + int cmp (hb_codepoint_t g) const + { return g < glyphId ? -1 : g > glyphId ? 1 : 0; } + + bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map, + const void* src_base, hb_subset_context_t *c) const + { + TRACE_SERIALIZE (this); + auto *out = s->embed (this); + if (unlikely (!out)) return_trace (false); + if (!s->check_assign (out->glyphId, glyph_map->get (glyphId), + HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + + return_trace (out->paint.serialize_subset (c, paint, src_base)); + } + + bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && paint.sanitize (c, base))); + } + + public: + HBGlyphID glyphId; /* Glyph ID of reference glyph */ + Offset32To paint; /* Offset (from beginning of BaseGlyphV1Record array) to Paint, + * Typically PaintColrLayers */ + public: + DEFINE_SIZE_STATIC (6); +}; + +struct BaseGlyphV1List : SortedArray32Of +{ + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + const hb_set_t* glyphset = c->plan->_glyphset; + + for (const auto& _ : as_array ()) + { + unsigned gid = _.glyphId; + if (!glyphset->has (gid)) continue; + + if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++; + else return_trace (false); + } + + return_trace (out->len != 0); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (SortedArray32Of::sanitize (c, this)); + } +}; + +struct LayerV1List : Array32OfOffset32To +{ + const Paint& get_paint (unsigned i) const + { return this+(*this)[i]; } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + for (const auto& _ : + hb_enumerate (*this) + | hb_filter (c->plan->colrv1_layers, hb_first)) + + { + auto *o = out->serialize_append (c->serializer); + if (unlikely (!o) || !o->serialize_subset (c, _.second, this)) + return_trace (false); + } + return_trace (true); + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (Array32OfOffset32To::sanitize (c, this)); + } +}; + struct COLR { static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR; @@ -131,6 +902,15 @@ struct COLR hb_set_t *related_ids /* OUT */) const { colr->closure_glyphs (glyph, related_ids); } + void closure_V0palette_indices (const hb_set_t *glyphs, + hb_set_t *palettes /* OUT */) const + { colr->closure_V0palette_indices (glyphs, palettes); } + + void closure_forV1 (hb_set_t *glyphset, + hb_set_t *layer_indices, + hb_set_t *palette_indices) const + { colr->closure_forV1 (glyphset, layer_indices, palette_indices); } + private: hb_blob_ptr_t colr; }; @@ -147,21 +927,70 @@ struct COLR related_ids->add_array (&glyph_layers[0].glyphId, glyph_layers.length, LayerRecord::min_size); } + void closure_V0palette_indices (const hb_set_t *glyphs, + hb_set_t *palettes /* OUT */) const + { + if (!numBaseGlyphs || !numLayers) return; + hb_array_t baseGlyphs = (this+baseGlyphsZ).as_array (numBaseGlyphs); + hb_array_t all_layers = (this+layersZ).as_array (numLayers); + + for (const BaseGlyphRecord record : baseGlyphs) + { + if (!glyphs->has (record.glyphId)) continue; + hb_array_t glyph_layers = all_layers.sub_array (record.firstLayerIdx, + record.numLayers); + for (const LayerRecord layer : glyph_layers) + palettes->add (layer.colorIdx); + } + } + + void closure_forV1 (hb_set_t *glyphset, + hb_set_t *layer_indices, + hb_set_t *palette_indices) const + { + if (version != 1) return; + hb_set_t visited_glyphs; + + hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices); + const BaseGlyphV1List &baseglyphV1_records = this+baseGlyphsV1List; + + for (const BaseGlyphV1Record &baseglyphV1record: baseglyphV1_records.iter ()) + { + unsigned gid = baseglyphV1record.glyphId; + if (!glyphset->has (gid)) continue; + + const Paint &paint = &baseglyphV1_records+baseglyphV1record.paint; + paint.dispatch (&c); + } + hb_set_union (glyphset, &visited_glyphs); + } + + const LayerV1List& get_layerV1List () const + { return (this+layersV1); } + + const BaseGlyphV1List& get_baseglyphV1List () const + { return (this+baseGlyphsV1List); } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && - (this+layersZ).sanitize (c, numLayers))); + return_trace (c->check_struct (this) && + (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) && + (this+layersZ).sanitize (c, numLayers) && + (version == 0 || + (COLRV1_ENABLE_SUBSETTING && version == 1 && + baseGlyphsV1List.sanitize (c, this) && + layersV1.sanitize (c, this) && + varStore.sanitize (c, this)))); } template - bool serialize (hb_serialize_context_t *c, - unsigned version, - BaseIterator base_it, - LayerIterator layer_it) + bool serialize_V0 (hb_serialize_context_t *c, + unsigned version, + BaseIterator base_it, + LayerIterator layer_it) { TRACE_SERIALIZE (this); if (unlikely (base_it.len () != layer_it.len ())) @@ -171,6 +1000,12 @@ struct COLR this->version = version; numLayers = 0; numBaseGlyphs = base_it.len (); + if (base_it.len () == 0) + { + baseGlyphsZ = 0; + layersZ = 0; + return_trace (true); + } baseGlyphsZ = COLR::min_size; layersZ = COLR::min_size + numBaseGlyphs * BaseGlyphRecord::min_size; @@ -198,6 +1033,14 @@ struct COLR return record; } + const BaseGlyphV1Record* get_base_glyphV1_record (hb_codepoint_t gid) const + { + const BaseGlyphV1Record* record = &(this+baseGlyphsV1List).bsearch ((unsigned) gid); + if ((record && (hb_codepoint_t) record->glyphId != gid)) + record = nullptr; + return record; + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -245,6 +1088,7 @@ struct COLR if (unlikely (!c->plan->new_gid_for_old_gid (out_layers[i].glyphId, &new_gid))) return hb_pair_t> (false, out_layers); out_layers[i].glyphId = new_gid; + out_layers[i].colorIdx = c->plan->colr_palettes->get (layers[i].colorIdx); } return hb_pair_t> (true, out_layers); @@ -253,23 +1097,45 @@ struct COLR | hb_map_retains_sorting (hb_second) ; - if (unlikely (!base_it || !layer_it || base_it.len () != layer_it.len ())) + if (version == 0 && (!base_it || !layer_it)) return_trace (false); COLR *colr_prime = c->serializer->start_embed (); - return_trace (colr_prime->serialize (c->serializer, version, base_it, layer_it)); + bool ret = colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it); + + if (version == 0) return_trace (ret); + auto snap = c->serializer->snapshot (); + if (!c->serializer->allocate_size (3 * HBUINT32::static_size)) return_trace (false); + if (!colr_prime->baseGlyphsV1List.serialize_subset (c, baseGlyphsV1List, this)) + { + if (c->serializer->in_error ()) return_trace (false); + //no more COLRv1 glyphs: downgrade to version 0 + c->serializer->revert (snap); + colr_prime->version = 0; + return_trace (true); + } + + if (!colr_prime->layersV1.serialize_subset (c, layersV1, this)) return_trace (false); + + colr_prime->varStore = 0; + //TODO: subset varStore once it's implemented in fonttools + return_trace (true); } protected: HBUINT16 version; /* Table version number (starts at 0). */ HBUINT16 numBaseGlyphs; /* Number of Base Glyph Records. */ - LNNOffsetTo> + NNOffset32To> baseGlyphsZ; /* Offset to Base Glyph records. */ - LNNOffsetTo> + NNOffset32To> layersZ; /* Offset to Layer Records. */ HBUINT16 numLayers; /* Number of Layer Records. */ + // Version-1 additions + Offset32To baseGlyphsV1List; + Offset32To layersV1; + Offset32To varStore; public: - DEFINE_SIZE_STATIC (14); + DEFINE_SIZE_MIN (14); }; } /* namespace OT */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh b/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh new file mode 100644 index 0000000000..4124efe0b1 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-ot-color-colrv1-closure.hh @@ -0,0 +1,101 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * Copyright © 2020 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. + * + */ + +#ifndef HB_OT_COLR_COLRV1_CLOSURE_HH +#define HB_OT_COLR_COLRV1_CLOSURE_HH + +#include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" +#include "hb-ot-color-colr-table.hh" + +/* + * COLR -- Color + * https://docs.microsoft.com/en-us/typography/opentype/spec/colr + */ +namespace OT { + +HB_INTERNAL void PaintColrLayers::closurev1 (hb_colrv1_closure_context_t* c) const +{ + c->add_layer_indices (firstLayerIndex, numLayers); + const LayerV1List &paint_offset_lists = c->get_colr_table ()->get_layerV1List (); + for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++) + { + const Paint &paint = hb_addressof (paint_offset_lists) + paint_offset_lists[i]; + paint.dispatch (c); + } +} + +HB_INTERNAL void PaintGlyph::closurev1 (hb_colrv1_closure_context_t* c) const +{ + c->add_glyph (gid); + (this+paint).dispatch (c); +} + +HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) const +{ + const COLR *colr_table = c->get_colr_table (); + const BaseGlyphV1Record* baseglyphV1_record = colr_table->get_base_glyphV1_record (gid); + if (!baseglyphV1_record) return; + c->add_glyph (gid); + + const BaseGlyphV1List &baseglyphV1_list = colr_table->get_baseglyphV1List (); + (&baseglyphV1_list+baseglyphV1_record->paint).dispatch (c); +} + +template class Var> +HB_INTERNAL void PaintTransform::closurev1 (hb_colrv1_closure_context_t* c) const +{ + (this+src).dispatch (c); +} + +template class Var> +HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const +{ + (this+src).dispatch (c); +} + +template class Var> +HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const +{ + (this+src).dispatch (c); +} + +template class Var> +HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const +{ + (this+src).dispatch (c); +} + +HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const +{ + (this+src).dispatch (c); + (this+backdrop).dispatch (c); +} + +} /* namespace OT */ + + +#endif /* HB_OT_COLR_COLRV1_CLOSURE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh index fa7d3207be..a9deeba9a7 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh @@ -39,7 +39,6 @@ */ #define HB_OT_TAG_CPAL HB_TAG('C','P','A','L') - namespace OT { @@ -74,6 +73,44 @@ struct CPALV1Tail } public: + bool serialize (hb_serialize_context_t *c, + unsigned palette_count, + unsigned color_count, + const void *base, + const hb_map_t *color_index_map) const + { + TRACE_SERIALIZE (this); + auto *out = c->allocate_size (static_size); + if (unlikely (!out)) return_trace (false); + + out->paletteFlagsZ = 0; + if (paletteFlagsZ) + out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count); + + out->paletteLabelsZ = 0; + if (paletteLabelsZ) + out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count); + + const hb_array_t colorLabels = (base+colorLabelsZ).as_array (color_count); + if (colorLabelsZ) + { + c->push (); + for (const auto _ : colorLabels) + { + if (!color_index_map->has (_)) continue; + NameID new_color_idx; + new_color_idx = color_index_map->get (_); + if (!c->copy (new_color_idx)) + { + c->pop_discard (); + return_trace (false); + } + } + c->add_link (out->colorLabelsZ, c->pop_pack ()); + } + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palette_count, @@ -87,15 +124,17 @@ struct CPALV1Tail } protected: - LNNOffsetTo> + // TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets + // here. Currently they are needed since UnsizedArrayOf doesn't define null_size + NNOffset32To> paletteFlagsZ; /* Offset from the beginning of CPAL table to * the Palette Type Array. Set to 0 if no array * is provided. */ - LNNOffsetTo> + NNOffset32To> paletteLabelsZ; /* Offset from the beginning of CPAL table to * the palette labels array. Set to 0 if no * array is provided. */ - LNNOffsetTo> + NNOffset32To> colorLabelsZ; /* Offset from the beginning of CPAL table to * the color labels array. Set to 0 * if no array is provided. */ @@ -157,6 +196,84 @@ struct CPAL } public: + bool serialize (hb_serialize_context_t *c, + const hb_array_t &color_records, + const hb_array_t &color_record_indices, + const hb_map_t &color_record_index_map, + const hb_set_t &retained_color_record_indices) const + { + TRACE_SERIALIZE (this); + + for (const auto idx : color_record_indices) + { + HBUINT16 new_idx; + if (idx == 0) new_idx = 0; + else new_idx = color_record_index_map.get (idx); + if (!c->copy (new_idx)) return_trace (false); + } + + c->push (); + for (const auto _ : retained_color_record_indices.iter ()) + { + if (!c->copy (color_records[_])) + { + c->pop_discard (); + return_trace (false); + } + } + c->add_link (colorRecordsZ, c->pop_pack ()); + return_trace (true); + } + + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + const hb_map_t *color_index_map = c->plan->colr_palettes; + if (color_index_map->is_empty ()) return_trace (false); + + hb_set_t retained_color_indices; + for (const auto _ : color_index_map->keys ()) + { + if (_ == 0xFFFF) continue; + retained_color_indices.add (_); + } + if (retained_color_indices.is_empty ()) return_trace (false); + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + out->version = version; + out->numColors = retained_color_indices.get_population (); + out->numPalettes = numPalettes; + + const hb_array_t colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes); + hb_map_t color_record_index_map; + hb_set_t retained_color_record_indices; + + unsigned record_count = 0; + for (const auto first_color_record_idx : colorRecordIndices) + { + for (unsigned retained_color_idx : retained_color_indices.iter ()) + { + unsigned color_record_idx = first_color_record_idx + retained_color_idx; + if (color_record_index_map.has (color_record_idx)) continue; + color_record_index_map.set (color_record_idx, record_count); + retained_color_record_indices.add (color_record_idx); + record_count++; + } + } + + out->numColorRecords = record_count; + const hb_array_t color_records = (this+colorRecordsZ).as_array (numColorRecords); + if (!out->serialize (c->serializer, color_records, colorRecordIndices, color_record_index_map, retained_color_record_indices)) + return_trace (false); + + if (version == 1) + return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map)); + + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -173,7 +290,7 @@ struct CPAL HBUINT16 numPalettes; /* Number of palettes in the table. */ HBUINT16 numColorRecords; /* Total number of color records, combined for * all palettes. */ - LNNOffsetTo> + NNOffset32To> colorRecordsZ; /* Offset from the beginning of CPAL table to * the first ColorRecord. */ UnsizedArrayOf diff --git a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh index 09da11597d..d2911f19e6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh @@ -145,7 +145,7 @@ struct SBIXStrike auto* out = c->serializer->start_embed (); if (unlikely (!out)) return_trace (false); auto snap = c->serializer->snapshot (); - if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false); + if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false); out->ppem = ppem; out->resolution = resolution; HBUINT32 head; @@ -185,7 +185,7 @@ struct SBIXStrike HBUINT16 resolution; /* The device pixel density (in PPI) for which this * strike was designed. (E.g., 96 PPI, 192 PPI.) */ protected: - UnsizedArrayOf> + UnsizedArrayOf> imageOffsetsZ; /* Offset from the beginning of the strike data header * to bitmap data for an individual glyph ID. */ public: @@ -352,11 +352,11 @@ struct sbix { TRACE_SERIALIZE (this); - auto *out = c->serializer->start_embed> (); + auto *out = c->serializer->start_embed> (); if (unlikely (!out)) return_trace (false); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); - hb_vector_t*> new_strikes; + hb_vector_t*> new_strikes; hb_vector_t objidxs; for (int i = strikes.len - 1; i >= 0; --i) { @@ -400,7 +400,7 @@ struct sbix HBUINT16 version; /* Table version number — set to 1 */ HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines. * Bits 2 to 15: reserved (set to 0). */ - LOffsetLArrayOf + Array32OfOffset32To strikes; /* Offsets from the beginning of the 'sbix' * table to data for each individual bitmap strike. */ public: diff --git a/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh index 1cc40ae53f..e022ef43b7 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-svg-table.hh @@ -62,7 +62,7 @@ struct SVGDocumentIndexEntry * this index entry. */ HBUINT16 endGlyphID; /* The last glyph ID in the range described by * this index entry. Must be >= startGlyphID. */ - LNNOffsetTo> + NNOffset32To> svgDoc; /* Offset from the beginning of the SVG Document Index * to an SVG document. Must be non-zero. */ HBUINT32 svgDocLength; /* Length of the SVG document. @@ -107,7 +107,7 @@ struct SVG protected: HBUINT16 version; /* Table version (starting at 0). */ - LOffsetTo> + Offset32To> svgDocEntries; /* Offset (relative to the start of the SVG table) to the * SVG Documents Index. Must be non-zero. */ /* Array of SVG Document Index Entries. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh index 367e143fdf..ffbbb1bc53 100644 --- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh +++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh @@ -40,7 +40,7 @@ /* This lists font tables that the hb_face_t will contain and lazily * load. Don't add a table unless it's used though. This is not - * exactly free. */ + * exactly zero-cost. */ /* v--- Add new tables in the right place here. */ diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc index fae7b5b65a..5c044c1c4f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-font.cc +++ b/thirdparty/harfbuzz/src/hb-ot-font.cc @@ -253,9 +253,7 @@ hb_ot_get_font_v_extents (hb_font_t *font, _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_VERTICAL_LINE_GAP, &metrics->line_gap); } -#if HB_USE_ATEXIT -static void free_static_ot_funcs (); -#endif +static inline void free_static_ot_funcs (); static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t { @@ -281,21 +279,17 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t + Array16Of gaspRanges; /* Number of records to follow * Sorted by ppem */ public: diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh index 5352156f02..ff7b9b2d25 100644 --- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh @@ -45,6 +45,10 @@ namespace OT { */ #define HB_OT_TAG_loca HB_TAG('l','o','c','a') +#ifndef HB_MAX_COMPOSITE_OPERATIONS +#define HB_MAX_COMPOSITE_OPERATIONS 100000 +#endif + struct loca { @@ -98,7 +102,7 @@ struct glyf unsigned num_offsets = padded_offsets.len () + 1; bool use_short_loca = max_offset < 0x1FFFF; unsigned entry_size = use_short_loca ? 2 : 4; - char *loca_prime_data = (char *) calloc (entry_size, num_offsets); + char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets); if (unlikely (!loca_prime_data)) return false; @@ -115,7 +119,7 @@ struct glyf entry_size * num_offsets, HB_MEMORY_MODE_WRITABLE, loca_prime_data, - free); + hb_free); bool result = plan->add_table (HB_OT_TAG_loca, loca_blob) && _add_head_and_set_loca_version (plan, use_short_loca); @@ -209,10 +213,15 @@ struct glyf if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph; - subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true); - if (plan->drop_hints) subset_glyph.drop_hints_bytes (); - else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes (); - + if (new_gid == 0 && + !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) + subset_glyph.source_glyph = Glyph (); + else + subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true); + if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) + subset_glyph.drop_hints_bytes (); + else + subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes (); return subset_glyph; }) | hb_sink (glyphs) @@ -281,6 +290,11 @@ struct glyf hb_codepoint_t get_glyph_index () const { return glyphIndex; } void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; } + void set_overlaps_flag () + { + flags = (uint16_t) flags | OVERLAP_COMPOUND; + } + bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; } bool has_more () const { return flags & MORE_COMPONENTS; } @@ -383,9 +397,12 @@ struct glyf { typedef const CompositeGlyphChain *__item_t__; composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) : - glyph (glyph_), current (current_) - { if (!check_range (current)) current = nullptr; } - composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr) {} + glyph (glyph_), current (nullptr), current_size (0) + { + set_next (current_); + } + + composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {} const CompositeGlyphChain &__item__ () const { return *current; } bool __more__ () const { return current; } @@ -393,23 +410,36 @@ struct glyf { if (!current->has_more ()) { current = nullptr; return; } - const CompositeGlyphChain *possible = &StructAfter (*current); - if (!check_range (possible)) { current = nullptr; return; } - current = possible; + set_next (&StructAtOffset (current, current_size)); } bool operator != (const composite_iter_t& o) const { return glyph != o.glyph || current != o.current; } - bool check_range (const CompositeGlyphChain *composite) const + + void set_next (const CompositeGlyphChain *composite) { - return glyph.check_range (composite, CompositeGlyphChain::min_size) - && glyph.check_range (composite, composite->get_size ()); + if (!glyph.check_range (composite, CompositeGlyphChain::min_size)) + { + current = nullptr; + current_size = 0; + return; + } + unsigned size = composite->get_size (); + if (!glyph.check_range (composite, size)) + { + current = nullptr; + current_size = 0; + return; + } + + current = composite; + current_size = size; } private: hb_bytes_t glyph; __item_t__ current; + unsigned current_size; }; enum phantom_point_index_t @@ -427,14 +457,14 @@ struct glyf { enum simple_glyph_flag_t { - FLAG_ON_CURVE = 0x01, - FLAG_X_SHORT = 0x02, - FLAG_Y_SHORT = 0x04, - FLAG_REPEAT = 0x08, - FLAG_X_SAME = 0x10, - FLAG_Y_SAME = 0x20, - FLAG_RESERVED1 = 0x40, - FLAG_RESERVED2 = 0x80 + FLAG_ON_CURVE = 0x01, + FLAG_X_SHORT = 0x02, + FLAG_Y_SHORT = 0x04, + FLAG_REPEAT = 0x08, + FLAG_X_SAME = 0x10, + FLAG_Y_SAME = 0x20, + FLAG_OVERLAP_SIMPLE = 0x40, + FLAG_RESERVED2 = 0x80 }; private: @@ -495,8 +525,8 @@ struct glyf const Glyph trim_padding () const { /* based on FontTools _g_l_y_f.py::trim */ - const char *glyph = bytes.arrayZ; - const char *glyph_end = glyph + bytes.length; + const uint8_t *glyph = (uint8_t*) bytes.arrayZ; + const uint8_t *glyph_end = glyph + bytes.length; /* simple glyph w/contours, possibly trimmable */ glyph += instruction_len_offset (); @@ -553,6 +583,17 @@ struct glyf dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length); } + void set_overlaps_flag () + { + if (unlikely (!header.numberOfContours)) return; + + unsigned flags_offset = length (instructions_length ()); + if (unlikely (length (flags_offset + 1) > bytes.length)) return; + + HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset (&bytes, flags_offset); + first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE; + } + static bool read_points (const HBUINT8 *&p /* IN/OUT */, contour_point_vector_t &points_ /* IN/OUT */, const hb_bytes_t &bytes, @@ -666,6 +707,12 @@ struct glyf /* Chop instructions off the end */ void drop_hints_bytes (hb_bytes_t &dest_start) const { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); } + + void set_overlaps_flag () + { + const_cast (StructAfter (header)) + .set_overlaps_flag (); + } }; enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE }; @@ -695,6 +742,15 @@ struct glyf } } + void set_overlaps_flag () + { + switch (type) { + case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return; + case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return; + default: return; + } + } + void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const { switch (type) { @@ -886,7 +942,7 @@ struct glyf { if (gid >= num_glyphs) return false; - /* Making this alloc free is not that easy + /* Making this allocfree is not that easy https://github.com/harfbuzz/harfbuzz/issues/2095 mostly because of gvar handling in VF fonts, perhaps a separate path for non-VF fonts can be considered */ @@ -1045,18 +1101,28 @@ struct glyf return needs_padding_removal ? glyph.trim_padding () : glyph; } - void - add_gid_and_children (hb_codepoint_t gid, hb_set_t *gids_to_retain, - unsigned int depth = 0) const + unsigned + add_gid_and_children (hb_codepoint_t gid, + hb_set_t *gids_to_retain, + unsigned depth = 0, + unsigned operation_count = 0) const { - if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return; + if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count; + if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count; /* Check if is already visited */ - if (gids_to_retain->has (gid)) return; + if (gids_to_retain->has (gid)) return operation_count; gids_to_retain->add (gid); - for (auto &item : glyph_for_gid (gid).get_composite_iterator ()) - add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth); + auto it = glyph_for_gid (gid).get_composite_iterator (); + while (it) + { + auto item = *(it++); + operation_count += + add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count); + } + + return operation_count; } #ifdef HB_EXPERIMENTAL_API @@ -1230,7 +1296,11 @@ struct glyf const_cast (_).set_glyph_index (new_gid); } - if (plan->drop_hints) Glyph (dest_glyph).drop_hints (); + if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) + Glyph (dest_glyph).drop_hints (); + + if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG) + Glyph (dest_glyph).set_overlaps_flag (); return_trace (true); } diff --git a/thirdparty/harfbuzz/src/hb-ot-hdmx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hdmx-table.hh index c9c391bad5..dea2b7e29a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-hdmx-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-hdmx-table.hh @@ -52,7 +52,7 @@ struct DeviceRecord unsigned length = it.len (); - if (unlikely (!c->extend (*this, length))) return_trace (false); + if (unlikely (!c->extend (this, length))) return_trace (false); this->pixelSize = pixelSize; this->maxWidth = @@ -110,7 +110,7 @@ struct hdmx for (const hb_item_type& _ : +it) c->start_embed ()->serialize (c, _.first, _.second); - return_trace (c->successful); + return_trace (c->successful ()); } diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh index d06c0fa4a4..4038329938 100644 --- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh @@ -146,7 +146,7 @@ struct hmtxvmtx _mtx.fini (); - if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ())) + if (unlikely (c->serializer->in_error ())) return_trace (false); // Amend header num hmetrics diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh index 4df0d942ce..492947751e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh @@ -103,7 +103,7 @@ struct BaseCoordFormat3 protected: HBUINT16 format; /* Format identifier--format = 3 */ FWORD coordinate; /* X or Y value, in design units */ - OffsetTo + Offset16To deviceTable; /* Offset to Device table for X or * Y value, from beginning of * BaseCoord table (may be NULL). */ @@ -173,11 +173,11 @@ struct FeatMinMaxRecord protected: Tag tag; /* 4-byte feature identification tag--must * match feature tag in FeatureList */ - OffsetTo + Offset16To minCoord; /* Offset to BaseCoord table that defines * the minimum extent value, from beginning * of MinMax table (may be NULL) */ - OffsetTo + Offset16To maxCoord; /* Offset to BaseCoord table that defines * the maximum extent value, from beginning * of MinMax table (may be NULL) */ @@ -212,15 +212,15 @@ struct MinMax } protected: - OffsetTo + Offset16To minCoord; /* Offset to BaseCoord table that defines * minimum extent value, from the beginning * of MinMax table (may be NULL) */ - OffsetTo + Offset16To maxCoord; /* Offset to BaseCoord table that defines * maximum extent value, from the beginning * of MinMax table (may be NULL) */ - SortedArrayOf + SortedArray16Of featMinMaxRecords; /* Array of FeatMinMaxRecords, in alphabetical * order by featureTableTag */ @@ -247,7 +247,7 @@ struct BaseValues Index defaultIndex; /* Index number of default baseline for this * script — equals index position of baseline tag * in baselineTags array of the BaseTagList */ - OffsetArrayOf + Array16OfOffset16To baseCoords; /* Number of BaseCoord tables defined — should equal * baseTagCount in the BaseTagList * @@ -275,7 +275,7 @@ struct BaseLangSysRecord protected: Tag baseLangSysTag; /* 4-byte language system identification tag */ - OffsetTo + Offset16To minMax; /* Offset to MinMax table, from beginning * of BaseScript table */ public: @@ -305,13 +305,13 @@ struct BaseScript } protected: - OffsetTo + Offset16To baseValues; /* Offset to BaseValues table, from beginning * of BaseScript table (may be NULL) */ - OffsetTo + Offset16To defaultMinMax; /* Offset to MinMax table, from beginning of * BaseScript table (may be NULL) */ - SortedArrayOf + SortedArray16Of baseLangSysRecords; /* Number of BaseLangSysRecords * defined — may be zero (0) */ @@ -339,7 +339,7 @@ struct BaseScriptRecord protected: Tag baseScriptTag; /* 4-byte script identification tag */ - OffsetTo + Offset16To baseScript; /* Offset to BaseScript table, from beginning * of BaseScriptList */ @@ -364,7 +364,7 @@ struct BaseScriptList } protected: - SortedArrayOf + SortedArray16Of baseScriptRecords; public: @@ -426,12 +426,12 @@ struct Axis } protected: - OffsetTo> + Offset16To> baseTagList; /* Offset to BaseTagList table, from beginning * of Axis table (may be NULL) * Array of 4-byte baseline identification tags — must * be in alphabetical order */ - OffsetTo + Offset16To baseScriptList; /* Offset to BaseScriptList table, from beginning * of Axis table * Array of BaseScriptRecords, in alphabetical order @@ -501,11 +501,11 @@ struct BASE protected: FixedVersion<>version; /* Version of the BASE table */ - OffsetTohAxis; /* Offset to horizontal Axis table, from beginning + Offset16TohAxis; /* Offset to horizontal Axis table, from beginning * of BASE table (may be NULL) */ - OffsetTovAxis; /* Offset to vertical Axis table, from beginning + Offset16TovAxis; /* Offset to vertical Axis table, from beginning * of BASE table (may be NULL) */ - LOffsetTo + Offset32To varStore; /* Offset to the table of Item Variation * Store--from beginning of BASE * header (may be NULL). Introduced diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 0ba7e3c061..65f499a00d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -88,12 +88,66 @@ static inline void ClassDef_serialize (hb_serialize_context_t *c, Iterator it); static void ClassDef_remap_and_serialize (hb_serialize_context_t *c, - const hb_set_t &glyphset, const hb_map_t &gid_klass_map, hb_sorted_vector_t &glyphs, const hb_set_t &klasses, + bool use_class_zero, hb_map_t *klass_map /*INOUT*/); + +struct hb_prune_langsys_context_t +{ + hb_prune_langsys_context_t (const void *table_, + hb_hashmap_t *script_langsys_map_, + const hb_map_t *duplicate_feature_map_, + hb_set_t *new_collected_feature_indexes_) + :table (table_), + script_langsys_map (script_langsys_map_), + duplicate_feature_map (duplicate_feature_map_), + new_feature_indexes (new_collected_feature_indexes_), + script_count (0),langsys_count (0) {} + + bool visitedScript (const void *s) + { + if (script_count++ > HB_MAX_SCRIPTS) + return true; + + return visited (s, visited_script); + } + + bool visitedLangsys (const void *l) + { + if (langsys_count++ > HB_MAX_LANGSYS) + return true; + + return visited (l, visited_langsys); + } + + private: + template + bool visited (const T *p, hb_set_t &visited_set) + { + hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table); + if (visited_set.has (delta)) + return true; + + visited_set.add (delta); + return false; + } + + public: + const void *table; + hb_hashmap_t *script_langsys_map; + const hb_map_t *duplicate_feature_map; + hb_set_t *new_feature_indexes; + + private: + hb_set_t visited_script; + hb_set_t visited_langsys; + unsigned script_count; + unsigned langsys_count; +}; + struct hb_subset_layout_context_t : hb_dispatch_context_t { @@ -125,16 +179,21 @@ struct hb_subset_layout_context_t : hb_subset_context_t *subset_context; const hb_tag_t table_tag; const hb_map_t *lookup_index_map; + const hb_hashmap_t *script_langsys_map; const hb_map_t *feature_index_map; + unsigned cur_script_index; hb_subset_layout_context_t (hb_subset_context_t *c_, hb_tag_t tag_, hb_map_t *lookup_map_, - hb_map_t *feature_map_) : + hb_hashmap_t *script_langsys_map_, + hb_map_t *feature_index_map_) : subset_context (c_), table_tag (tag_), lookup_index_map (lookup_map_), - feature_index_map (feature_map_), + script_langsys_map (script_langsys_map_), + feature_index_map (feature_index_map_), + cur_script_index (0xFFFFu), script_count (0), langsys_count (0), feature_index_count (0), @@ -325,7 +384,7 @@ struct Record } Tag tag; /* 4-byte Tag identifier */ - OffsetTo + Offset16To offset; /* Offset from beginning of object holding * the Record */ public: @@ -333,11 +392,11 @@ struct Record }; template -struct RecordArrayOf : SortedArrayOf> +struct RecordArrayOf : SortedArray16Of> { - const OffsetTo& get_offset (unsigned int i) const + const Offset16To& get_offset (unsigned int i) const { return (*this)[i].offset; } - OffsetTo& get_offset (unsigned int i) + Offset16To& get_offset (unsigned int i) { return (*this)[i].offset; } const Tag& get_tag (unsigned int i) const { return (*this)[i].tag; } @@ -356,7 +415,7 @@ struct RecordArrayOf : SortedArrayOf> } bool find_index (hb_tag_t tag, unsigned int *index) const { - return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); + return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX); } }; @@ -407,6 +466,30 @@ struct RecordListOfFeature : RecordListOf } }; +struct Script; +struct RecordListOfScript : RecordListOf