diff options
98 files changed, 2527 insertions, 1672 deletions
diff --git a/cmake/QtConfigDependencies.cmake.in b/cmake/QtConfigDependencies.cmake.in index e68e2954f9d..b006f052f7f 100644 --- a/cmake/QtConfigDependencies.cmake.in +++ b/cmake/QtConfigDependencies.cmake.in @@ -7,8 +7,10 @@ if(DEFINED QT_REQUIRE_HOST_PATH_CHECK) set(__qt_platform_requires_host_info_package "${QT_REQUIRE_HOST_PATH_CHECK}") elseif(DEFINED ENV{QT_REQUIRE_HOST_PATH_CHECK}) set(__qt_platform_requires_host_info_package "$ENV{QT_REQUIRE_HOST_PATH_CHECK}") -else() +elseif(CMAKE_CROSSCOMPILING OR DEFINED QT_HOST_PATH) set(__qt_platform_requires_host_info_package "@platform_requires_host_info_package@") +else() + set(__qt_platform_requires_host_info_package FALSE) endif() set(__qt_platform_initial_qt_host_path "@qt_host_path_absolute@") set(__qt_platform_initial_qt_host_path_cmake_dir "@qt_host_path_cmake_dir_absolute@") diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake index c006f1b677a..9407fd0ebe5 100644 --- a/cmake/QtToolchainHelpers.cmake +++ b/cmake/QtToolchainHelpers.cmake @@ -34,10 +34,23 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file} set(init_vcpkg "") endif() - if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_SYSTEM_VERSION STREQUAL "10") - list(APPEND init_platform "set(CMAKE_SYSTEM_NAME Windows CACHE STRING \"\")") - list(APPEND init_platform "set(CMAKE_SYSTEM_VERSION 10 CACHE STRING \"\")") - list(APPEND init_platform "set(CMAKE_SYSTEM_PROCESSOR arm64 CACHE STRING \"\")") + if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND CMAKE_CROSSCOMPILING) + list(APPEND init_platform + "string(TOUPPER \"${CMAKE_SYSTEM_PROCESSOR}\" _qt_orig_target_system_processor_upper)" + "string(TOUPPER \"\${CMAKE_HOST_SYSTEM_PROCESSOR}\" _qt_host_system_processor_upper)" + "if(NOT _qt_orig_target_system_processor_upper STREQUAL _qt_host_system_processor_upper" + " OR NOT CMAKE_HOST_SYSTEM_VERSION MATCHES \"^${CMAKE_SYSTEM_VERSION}(\\\\..+|$)\"" + " OR QT_FORCE_CROSSCOMPILING)" + "" + " set(CMAKE_SYSTEM_NAME \"${CMAKE_SYSTEM_NAME}\" CACHE STRING \"\")" + " set(CMAKE_SYSTEM_VERSION \"${CMAKE_SYSTEM_VERSION}\" CACHE STRING \"\")" + " set(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\" CACHE STRING \"\")" + "else()" + " set(QT_REQUIRE_HOST_PATH_CHECK FALSE)" + "endif()" + "unset(_qt_host_system_processor_upper)" + "unset(_qt_orig_host_system_processor_upper)" + ) endif() if(QT_QMAKE_TARGET_MKSPEC) diff --git a/coin/instructions/cmake_build_tests_in_test_stage.yaml b/coin/instructions/cmake_build_tests_in_test_stage.yaml index 420b4331f57..2f4e62b989e 100644 --- a/coin/instructions/cmake_build_tests_in_test_stage.yaml +++ b/coin/instructions/cmake_build_tests_in_test_stage.yaml @@ -8,16 +8,26 @@ instructions: instructions: - !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts_host.yaml" disable_if: - condition: property - property: target.osVersion - in_values: [Android_ANY, QEMU, IOS_ANY, QNX_710, WebAssembly, INTEGRITY, VxWorks] + condition: or + conditions: + - condition: property + property: target.osVersion + in_values: [Android_ANY, QEMU, IOS_ANY, QNX_710, WebAssembly, INTEGRITY, VxWorks] + - condition: property + property: features + contains_value: UseToolchainFromTargetDir - type: Group instructions: - !include "{{qt/qtbase}}/cmake_build_and_upload_test_artifacts_target.yaml" enable_if: - condition: property - property: target.osVersion - in_values: [Android_ANY, QEMU, IOS_ANY, QNX_710, WebAssembly, INTEGRITY, VxWorks] + condition: or + conditions: + - condition: property + property: target.osVersion + in_values: [Android_ANY, QEMU, IOS_ANY, QNX_710, WebAssembly, INTEGRITY, VxWorks] + - condition: property + property: features + contains_value: UseToolchainFromTargetDir enable_if: condition: property property: features diff --git a/coin/instructions/prepare_building_env.yaml b/coin/instructions/prepare_building_env.yaml index 03b05ddf7ea..cda46145e01 100644 --- a/coin/instructions/prepare_building_env.yaml +++ b/coin/instructions/prepare_building_env.yaml @@ -202,8 +202,8 @@ instructions: property: target.arch in_values: ["AARCH64", "ARM64"] - condition: property - property: host - equals_property: target + property: host.arch + in_values: ["AARCH64", "ARM64"] - type: EnvironmentVariable # HACK. Overwrite TARGET_ARCHITECTURE as we do not use standard MSVC cross # compilation targets here. The target architecture will be detected by Qt. @@ -398,11 +398,11 @@ instructions: condition: and conditions: - condition: property - property: target.os + property: host.os equals_value: Windows - condition: property - property: target.arch - not_equals_property: host.arch + property: host.compiler + contains_value: MSVC instructions: - type: EnvironmentVariable variableName: TARGET_ENV_PREFIX diff --git a/src/3rdparty/harfbuzz-ng/CMakeLists.txt b/src/3rdparty/harfbuzz-ng/CMakeLists.txt index 6db3ce881bb..8c299a3daac 100644 --- a/src/3rdparty/harfbuzz-ng/CMakeLists.txt +++ b/src/3rdparty/harfbuzz-ng/CMakeLists.txt @@ -69,6 +69,11 @@ qt_internal_add_3rdparty_library(BundledHarfbuzz src/hb-subset-plan-layout.cc src/hb-subset-plan-member-list.hh src/hb-subset-serialize.cc src/hb-subset-serialize.h + src/hb-subset-table-cff.cc + src/hb-subset-table-color.cc + src/hb-subset-table-layout.cc + src/hb-subset-table-other.cc + src/hb-subset-table-var.cc src/hb-subset-table.hh src/hb-subset-plan-var.cc src/hb-unicode.cc src/hb-unicode.h src/hb-unicode.hh src/hb-utf.hh diff --git a/src/3rdparty/harfbuzz-ng/README.md b/src/3rdparty/harfbuzz-ng/README.md index 0cbdf00be31..7646565fb02 100644 --- a/src/3rdparty/harfbuzz-ng/README.md +++ b/src/3rdparty/harfbuzz-ng/README.md @@ -78,7 +78,7 @@ Internationalization and Unicode Conference over the years: More presentations and papers are available on [behdad][11]'s website. In particular, the following _studies_ are relevant to HarfBuzz development: -- 2025 - [Introducing HarfRust][22] +- 2025 – [Introducing HarfRust][22] - 2025 – [Subsetting][21] - 2025 – [Caching][12] - 2025 – [`hb-decycler`][13] @@ -119,10 +119,10 @@ transliterated using the Latin script. It also means "talkative" or [2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html [3]: https://github.com/harfbuzz/harfbuzz/releases [4]: https://github.com/harfbuzz/harfbuzz -[6]: http://behdad.org/text2024 +[6]: https://behdad.org/text2024 [7]: https://docs.google.com/presentation/d/1x97pfbB1gbD53Yhz6-_yBUozQMVJ_5yMqqR_D-R7b7I/preview [8]: https://docs.google.com/presentation/d/1ySTZaXP5XKFg0OpmHZM00v5b17GSr3ojnzJekl4U8qI/preview -[9]: http://behdad.org/download/Presentations/slippy/harfbuzz_slides.pdf +[9]: https://behdad.org/doc/harfbuzz2009-slides.pdf [10]: https://docs.google.com/document/d/12jfNpQJzeVIAxoUSpk7KziyINAa1msbGliyXqguS86M/preview [11]: https://behdad.org/ [12]: https://docs.google.com/document/d/1_VgObf6Je0J8byMLsi7HCQHnKo2emGnx_ib_sHo-bt4/preview diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json index 8bb94c14423..9c286cb13b1 100644 --- a/src/3rdparty/harfbuzz-ng/qt_attribution.json +++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json @@ -7,8 +7,8 @@ "Description": "HarfBuzz is an OpenType text shaping engine.", "Homepage": "http://harfbuzz.org", - "Version": "11.3.3", - "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/11.3.3", + "Version": "11.4.1", + "DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/11.4.1", "PURL": "pkg:github/harfbuzz/harfbuzz@$<VERSION>", "CPE": "cpe:2.3:a:harfbuzz_project:harfbuzz:$<VERSION>:*:*:*:*:*:*:*", "License": "MIT License", diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh index 896b0fb1034..7d72a11a42c 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/COLR/COLR.hh @@ -178,7 +178,10 @@ struct hb_colrv1_closure_context_t : { 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); } + { + if (num_of_layers == 0) return; + 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); } @@ -650,10 +653,10 @@ struct PaintColrLayers 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); + uint32_t first_layer_index = numLayers ? c->plan->colrv1_layers.get (firstLayerIndex) : 0; + return_trace (c->serializer->check_assign (out->firstLayerIndex, first_layer_index, + HB_SERIALIZE_ERROR_INT_OVERFLOW)); } bool sanitize (hb_sanitize_context_t *c) const diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh b/src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh index 940126a86c5..2b8b69b6009 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Color/CPAL/CPAL.hh @@ -307,6 +307,7 @@ struct CPAL if (first_color_to_layer_index.has (first_color_record_idx)) continue; first_color_index_for_layer.push (first_color_record_idx); + if (unlikely (!c->serializer->propagate_error (first_color_index_for_layer))) return_trace (false); first_color_to_layer_index.set (first_color_record_idx, first_color_index_for_layer.length - 1); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh index daa1979544c..797a8d2448a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/Common/Coverage.hh @@ -97,12 +97,17 @@ struct Coverage } } unsigned int get_coverage (hb_codepoint_t glyph_id, - hb_ot_lookup_cache_t *cache) const + hb_ot_layout_mapping_cache_t *cache) const { unsigned coverage; - if (cache && cache->get (glyph_id, &coverage)) return coverage; + if (cache && cache->get (glyph_id, &coverage)) return coverage < cache->MAX_VALUE ? coverage : NOT_COVERED; coverage = get_coverage (glyph_id); - if (cache) cache->set (glyph_id, coverage); + if (cache) { + if (coverage == NOT_COVERED) + cache->set_unchecked (glyph_id, cache->MAX_VALUE); + else if (likely (coverage < cache->MAX_VALUE)) + cache->set_unchecked (glyph_id, coverage); + } return coverage; } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh index 79de21e5919..ed397b75088 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GDEF/GDEF.hh @@ -977,7 +977,7 @@ struct GDEF } #ifndef HB_NO_GDEF_CACHE - table->get_mark_glyph_sets ().collect_coverage (mark_glyph_set_digests); + table->get_mark_glyph_sets ().collect_coverage (mark_glyph_sets); #endif } ~accelerator_t () { table.destroy (); } @@ -1006,14 +1006,16 @@ struct GDEF { return #ifndef HB_NO_GDEF_CACHE - mark_glyph_set_digests[set_index].may_have (glyph_id) && + mark_glyph_sets[set_index].may_have (glyph_id) +#else + table->mark_set_covers (set_index, glyph_id) #endif - table->mark_set_covers (set_index, glyph_id); + ; } hb_blob_ptr_t<GDEF> table; #ifndef HB_NO_GDEF_CACHE - hb_vector_t<hb_set_digest_t> mark_glyph_set_digests; + hb_vector_t<hb_bit_set_t> mark_glyph_sets; mutable hb_cache_t<21, 3> glyph_props_cache; static_assert (sizeof (glyph_props_cache) == 512, ""); #endif diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh index 2557e9a7231..7e676371f7b 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/AnchorMatrix.hh @@ -77,6 +77,13 @@ struct AnchorMatrix return_trace (true); } + + bool offset_is_null (unsigned row, unsigned col, unsigned num_cols) const + { + if (unlikely (row >= rows || col >= num_cols)) return true; + auto &offset = matrixZ[row * num_cols + col]; + return offset.is_null (); + } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh index 59cca40aadc..fd131224630 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/LigatureArray.hh @@ -19,22 +19,30 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach> bool subset (hb_subset_context_t *c, Iterator coverage, unsigned class_count, - const hb_map_t *klass_mapping) const + const hb_map_t *klass_mapping, + hb_sorted_vector_t<hb_codepoint_t> &new_coverage /* OUT */) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_map_t &glyph_map = c->plan->glyph_map_gsub; auto *out = c->serializer->start_embed (this); if (unlikely (!c->serializer->extend_min (out))) return_trace (false); bool ret = false; for (const auto _ : + hb_zip (coverage, *this) - | hb_filter (glyphset, hb_first)) + | hb_filter (glyph_map, hb_first)) { + const LigatureAttach& src = (this + _.second); + bool non_empty = + hb_range (src.rows * class_count) + | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) + | hb_map ([&] (const unsigned index) { return !src.offset_is_null (index / class_count, index % class_count, class_count); }) + | hb_any; + + if (!non_empty) continue; + auto *matrix = out->serialize_append (c->serializer); if (unlikely (!matrix)) return_trace (false); - const LigatureAttach& src = (this + _.second); auto indexes = + hb_range (src.rows * class_count) | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); }) @@ -44,6 +52,9 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach> this, src.rows, indexes); + + hb_codepoint_t new_gid = glyph_map.get (_.first); + new_coverage.push (new_gid); } return_trace (ret); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh index ab1378e615c..c13dc65d439 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkBasePosFormat1.hh @@ -209,19 +209,22 @@ struct MarkBasePosFormat1_2 ; new_coverage.reset (); - + base_iter - | hb_map (hb_first) - | hb_map (glyph_map) - | hb_sink (new_coverage) - ; - - if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ())) - return_trace (false); - hb_sorted_vector_t<unsigned> base_indexes; - for (const unsigned row : + base_iter - | hb_map (hb_second)) + auto &base_array = (this+baseArray); + for (const auto _ : + base_iter) { + unsigned row = _.second; + bool non_empty = + hb_range ((unsigned) classCount) + | hb_filter (klass_mapping) + | hb_map ([&] (const unsigned col) { return !base_array.offset_is_null (row, col, (unsigned) classCount); }) + | hb_any + ; + + if (!non_empty) continue; + + hb_codepoint_t new_g = glyph_map.get ( _.first); + new_coverage.push (new_g); + + hb_range ((unsigned) classCount) | hb_filter (klass_mapping) | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) @@ -229,8 +232,12 @@ struct MarkBasePosFormat1_2 ; } + if (!new_coverage) return_trace (false); + if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ())) + return_trace (false); + return_trace (out->baseArray.serialize_subset (c, baseArray, this, - base_iter.len (), + new_coverage.length, base_indexes.iter ())); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh index 46013c613b0..57dae77a9d0 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkLigPosFormat1.hh @@ -200,19 +200,13 @@ struct MarkLigPosFormat1_2 &klass_mapping))) return_trace (false); - auto new_ligature_coverage = - + hb_iter (this + ligatureCoverage) - | hb_take ((this + ligatureArray).len) - | hb_map_retains_sorting (glyph_map) - | hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; }) - ; - - if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage)) + hb_sorted_vector_t<hb_codepoint_t> new_lig_coverage; + if (!out->ligatureArray.serialize_subset (c, ligatureArray, this, + hb_iter (this+ligatureCoverage), + classCount, &klass_mapping, new_lig_coverage)) return_trace (false); - return_trace (out->ligatureArray.serialize_subset (c, ligatureArray, this, - hb_iter (this+ligatureCoverage), - classCount, &klass_mapping)); + return_trace (out->ligatureCoverage.serialize_serialize (c->serializer, new_lig_coverage.iter ())); } }; diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh index c4d129f2cb0..3221704caec 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh @@ -196,19 +196,23 @@ struct MarkMarkPosFormat1_2 ; new_coverage.reset (); - + mark2_iter - | hb_map (hb_first) - | hb_map (glyph_map) - | hb_sink (new_coverage) - ; - - if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) - return_trace (false); - hb_sorted_vector_t<unsigned> mark2_indexes; - for (const unsigned row : + mark2_iter - | hb_map (hb_second)) + auto &mark2_array = (this+mark2Array); + for (const auto _ : + mark2_iter) { + unsigned row = _.second; + + bool non_empty = + hb_range ((unsigned) classCount) + | hb_filter (klass_mapping) + | hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); }) + | hb_any + ; + + if (!non_empty) continue; + + hb_codepoint_t new_g = glyph_map.get ( _.first); + new_coverage.push (new_g); + + hb_range ((unsigned) classCount) | hb_filter (klass_mapping) | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; }) @@ -216,6 +220,10 @@ struct MarkMarkPosFormat1_2 ; } + if (!new_coverage) return_trace (false); + if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ())) + return_trace (false); + return_trace (out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ())); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh index a8ea5f96c05..6e366a2a090 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -103,28 +103,24 @@ struct PairPosFormat1_3 const Coverage &get_coverage () const { return this+coverage; } - unsigned cache_cost () const - { - return (this+coverage).cost (); - } - static void * cache_func (void *p, hb_ot_lookup_cache_op_t op) + static void * cache_func (void *p, hb_ot_subtable_cache_op_t op) { switch (op) { - case hb_ot_lookup_cache_op_t::CREATE: + case hb_ot_subtable_cache_op_t::CREATE: { - hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t)); + hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) hb_malloc (sizeof (hb_ot_layout_mapping_cache_t)); if (likely (cache)) cache->clear (); return cache; } - case hb_ot_lookup_cache_op_t::ENTER: - return (void *) true; - case hb_ot_lookup_cache_op_t::LEAVE: + case hb_ot_subtable_cache_op_t::ENTER: + return nullptr; + case hb_ot_subtable_cache_op_t::LEAVE: return nullptr; - case hb_ot_lookup_cache_op_t::DESTROY: + case hb_ot_subtable_cache_op_t::DESTROY: { - hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p; + hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) p; hb_free (cache); return nullptr; } @@ -132,16 +128,14 @@ struct PairPosFormat1_3 return nullptr; } - bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } - bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } - bool _apply (hb_ot_apply_context_t *c, bool cached) const + bool apply (hb_ot_apply_context_t *c, void *external_cache) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr; + hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) external_cache; unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache); #else unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh index 59c018b9276..d251b1ff641 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -125,20 +125,16 @@ struct PairPosFormat2_4 : ValueBase struct pair_pos_cache_t { - hb_ot_lookup_cache_t coverage; - hb_ot_lookup_cache_t first; - hb_ot_lookup_cache_t second; + hb_ot_layout_mapping_cache_t coverage; + hb_ot_layout_mapping_cache_t first; + hb_ot_layout_mapping_cache_t second; }; - unsigned cache_cost () const - { - return (this+coverage).cost () + (this+classDef1).cost () + (this+classDef2).cost (); - } - static void * cache_func (void *p, hb_ot_lookup_cache_op_t op) + static void * cache_func (void *p, hb_ot_subtable_cache_op_t op) { switch (op) { - case hb_ot_lookup_cache_op_t::CREATE: + case hb_ot_subtable_cache_op_t::CREATE: { pair_pos_cache_t *cache = (pair_pos_cache_t *) hb_malloc (sizeof (pair_pos_cache_t)); if (likely (cache)) @@ -149,11 +145,11 @@ struct PairPosFormat2_4 : ValueBase } return cache; } - case hb_ot_lookup_cache_op_t::ENTER: - return (void *) true; - case hb_ot_lookup_cache_op_t::LEAVE: + case hb_ot_subtable_cache_op_t::ENTER: + return nullptr; + case hb_ot_subtable_cache_op_t::LEAVE: return nullptr; - case hb_ot_lookup_cache_op_t::DESTROY: + case hb_ot_subtable_cache_op_t::DESTROY: { pair_pos_cache_t *cache = (pair_pos_cache_t *) p; hb_free (cache); @@ -163,16 +159,14 @@ struct PairPosFormat2_4 : ValueBase return nullptr; } - bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } - bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } - bool _apply (hb_ot_apply_context_t *c, bool cached) const + bool apply (hb_ot_apply_context_t *c, void *external_cache) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - pair_pos_cache_t *cache = cached ? (pair_pos_cache_t *) c->lookup_accel->cache : nullptr; + pair_pos_cache_t *cache = (pair_pos_cache_t *) external_cache; unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr); #else unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh index 2ef46145e98..95d282228c2 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/GSUB/LigatureSubstFormat1.hh @@ -78,28 +78,24 @@ struct LigatureSubstFormat1_2 return lig_set.would_apply (c); } - unsigned cache_cost () const - { - return (this+coverage).cost (); - } - static void * cache_func (void *p, hb_ot_lookup_cache_op_t op) + static void * cache_func (void *p, hb_ot_subtable_cache_op_t op) { switch (op) { - case hb_ot_lookup_cache_op_t::CREATE: + case hb_ot_subtable_cache_op_t::CREATE: { - hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t)); + hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) hb_malloc (sizeof (hb_ot_layout_mapping_cache_t)); if (likely (cache)) cache->clear (); return cache; } - case hb_ot_lookup_cache_op_t::ENTER: - return (void *) true; - case hb_ot_lookup_cache_op_t::LEAVE: + case hb_ot_subtable_cache_op_t::ENTER: + return nullptr; + case hb_ot_subtable_cache_op_t::LEAVE: return nullptr; - case hb_ot_lookup_cache_op_t::DESTROY: + case hb_ot_subtable_cache_op_t::DESTROY: { - hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p; + hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) p; hb_free (cache); return nullptr; } @@ -107,15 +103,13 @@ struct LigatureSubstFormat1_2 return nullptr; } - bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } - bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } - bool _apply (hb_ot_apply_context_t *c, bool cached) const + bool apply (hb_ot_apply_context_t *c, void *external_cache) const { TRACE_APPLY (this); hb_buffer_t *buffer = c->buffer; #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr; + hb_ot_layout_mapping_cache_t *cache = (hb_ot_layout_mapping_cache_t *) external_cache; unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache); #else unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint); diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh b/src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh index 527f64114b4..6e412e5fe92 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Layout/types.hh @@ -29,8 +29,8 @@ #ifndef OT_LAYOUT_TYPES_HH #define OT_LAYOUT_TYPES_HH -using hb_ot_lookup_cache_t = hb_cache_t<15, 8, 7>; -static_assert (sizeof (hb_ot_lookup_cache_t) == 256, ""); +using hb_ot_layout_mapping_cache_t = hb_cache_t<15, 8, 7>; +static_assert (sizeof (hb_ot_layout_mapping_cache_t) == 256, ""); namespace OT { namespace Layout { diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.cc b/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.cc index 9e4fa3c2440..1a22f1d8124 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.cc +++ b/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.cc @@ -11,6 +11,8 @@ namespace OT { //namespace Var { +#ifndef HB_NO_DRAW + struct hb_transforming_pen_context_t { hb_transform_t<> transform; @@ -411,6 +413,8 @@ VARC::get_path_at (const hb_varc_context_t &c, return true; } +#endif + //} // namespace Var } // namespace OT diff --git a/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.hh b/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.hh index a372701cde9..719302c93e4 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/Var/VARC/VARC.hh @@ -194,6 +194,7 @@ struct VARC hb_codepoint_t gid, hb_glyph_extents_t *extents) const { +#ifndef HB_NO_DRAW if (!table->has_data ()) return false; hb_extents_t<> f_extents; @@ -207,6 +208,9 @@ struct VARC *extents = f_extents.to_glyph_extents (font->x_scale < 0, font->y_scale < 0); return ret; +#else + return false; +#endif } private: diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh index f8a396bf9bd..a3ec885e64c 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh @@ -533,7 +533,11 @@ struct Glyph bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator, hb_glyph_extents_t *extents) const { - if (type == EMPTY) return true; /* Empty glyph; zero extents. */ + if (type == EMPTY) + { + *extents = {0, 0, 0, 0}; + return true; /* Empty glyph; zero extents. */ + } return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents); } diff --git a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh index b821dd32258..71989d8df4a 100644 --- a/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh +++ b/src/3rdparty/harfbuzz-ng/src/OT/glyf/glyf.hh @@ -445,8 +445,7 @@ struct glyf_accelerator_t if (coords) { hb_glyf_scratch_t *scratch = acquire_scratch (); - if (unlikely (!scratch)) - return false; + if (unlikely (!scratch)) return false; bool ret = get_points (font, gid, points_aggregator_t (font, extents, nullptr, true), @@ -493,8 +492,7 @@ struct glyf_accelerator_t if (!has_data ()) return false; hb_glyf_scratch_t *scratch = acquire_scratch (); - if (unlikely (!scratch)) - return true; + if (unlikely (!scratch)) return true; bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), hb_array (font->coords, @@ -523,6 +521,7 @@ struct glyf_accelerator_t hb_glyf_scratch_t *acquire_scratch () const { + if (!has_data ()) return nullptr; hb_glyf_scratch_t *scratch = cached_scratch.get_acquire (); if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr))) { @@ -534,6 +533,8 @@ struct glyf_accelerator_t } void release_scratch (hb_glyf_scratch_t *scratch) const { + if (!scratch) + return; if (!cached_scratch.cmpexch (nullptr, scratch)) { scratch->~hb_glyf_scratch_t (); diff --git a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh index 332f27169df..0b538c3d2e3 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/graph.hh @@ -965,9 +965,9 @@ struct graph_t */ template<typename O> unsigned move_child (unsigned old_parent_idx, - const O* old_offset, - unsigned new_parent_idx, - const O* new_offset) + const O* old_offset, + unsigned new_parent_idx, + const O* new_offset) { distance_invalid = true; positions_invalid = true; @@ -993,6 +993,50 @@ struct graph_t } /* + * Moves all outgoing links in old parent that have + * a link position between [old_post_start, old_pos_end) + * to the new parent. Links are placed serially in the new + * parent starting at new_pos_start. + */ + template<typename O> + void move_children (unsigned old_parent_idx, + unsigned old_pos_start, + unsigned old_pos_end, + unsigned new_parent_idx, + unsigned new_pos_start) + { + distance_invalid = true; + positions_invalid = true; + + auto& old_v = vertices_[old_parent_idx]; + auto& new_v = vertices_[new_parent_idx]; + + hb_vector_t<hb_serialize_context_t::object_t::link_t> old_links; + for (const auto& l : old_v.obj.real_links) + { + if (l.position < old_pos_start || l.position >= old_pos_end) + { + old_links.push(l); + continue; + } + + unsigned array_pos = l.position - old_pos_start; + + unsigned child_id = l.objidx; + auto* new_link = new_v.obj.real_links.push (); + new_link->width = O::static_size; + new_link->objidx = child_id; + new_link->position = new_pos_start + array_pos; + + auto& child = vertices_[child_id]; + child.add_parent (new_parent_idx, false); + child.remove_parent (old_parent_idx); + } + + old_v.obj.real_links = std::move (old_links); + } + + /* * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign * links. index_map is updated with mappings from old id to new id. If a duplication has already * been performed for a given index, then it will be skipped. diff --git a/src/3rdparty/harfbuzz-ng/src/graph/ligature-graph.hh b/src/3rdparty/harfbuzz-ng/src/graph/ligature-graph.hh index 611ab686e9b..fd170bd9ccb 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/ligature-graph.hh +++ b/src/3rdparty/harfbuzz-ng/src/graph/ligature-graph.hh @@ -105,6 +105,23 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1 return result; } + hb_vector_t<unsigned> ligature_index_to_object_id(const graph_t::vertex_and_table_t<LigatureSet>& liga_set) const { + hb_vector_t<unsigned> map; + map.resize_exact(liga_set.table->ligature.len); + if (map.in_error()) return map; + + for (unsigned i = 0; i < map.length; i++) { + map[i] = (unsigned) -1; + } + + for (const auto& l : liga_set.vertex->obj.real_links) { + if (l.position < 2) continue; + unsigned array_index = (l.position - 2) / 2; + map[array_index] = l.objidx; + } + return map; + } + hb_vector_t<unsigned> compute_split_points(gsubgpos_graph_context_t& c, unsigned parent_index, unsigned this_index) const @@ -128,9 +145,16 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1 return hb_vector_t<unsigned> {}; } + // Finding the object id associated with an array index is O(n) + // so to avoid O(n^2), precompute the mapping by scanning through + // all links + auto index_to_id = ligature_index_to_object_id(liga_set); + if (index_to_id.in_error()) return hb_vector_t<unsigned>(); + for (unsigned j = 0; j < liga_set.table->ligature.len; j++) { - const unsigned liga_id = c.graph.index_for_offset (liga_set.index, &liga_set.table->ligature[j]); + const unsigned liga_id = index_to_id[j]; + if (liga_id == (unsigned) -1) continue; // no outgoing link, ignore const unsigned liga_size = c.graph.vertices_[liga_id].table_size (); accumulated += OT::HBUINT16::static_size; // for ligature offset @@ -154,7 +178,6 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1 return split_points; } - struct split_context_t { gsubgpos_graph_context_t& c; @@ -323,19 +346,19 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1 { // This liga set partially overlaps [start, end). We'll need to create // a new liga set sub table and move the intersecting ligas to it. - unsigned liga_count = hb_min(end, current_end) - hb_max(start, current_start); + unsigned start_index = hb_max(start, current_start) - count; + unsigned end_index = hb_min(end, current_end) - count; + unsigned liga_count = end_index - start_index; auto result = new_liga_set(c, liga_count); liga_set_prime_id = result.first; - LigatureSet* prime = result.second; if (liga_set_prime_id == (unsigned) -1) return -1; - unsigned new_index = 0; - for (unsigned j = hb_max(start, current_start) - count; j < hb_min(end, current_end) - count; j++) { - c.graph.move_child<> (liga_set_index, - &liga_set.table->ligature[j], - liga_set_prime_id, - &prime->ligature[new_index++]); - } + c.graph.move_children<OT::Offset16>( + liga_set_index, + 2 + start_index * 2, + 2 + end_index * 2, + liga_set_prime_id, + 2); liga_set_end = i; if (i < liga_set_start) liga_set_start = i; @@ -392,8 +415,12 @@ struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1 // duplicated. Code later on will re-add the virtual links as needed (via retained_indices). clear_virtual_links(c, liga_set.index); retained_indices.add(liga_set.index); - for (const auto& liga_offset : liga_set.table->ligature) { - unsigned liga_index = c.graph.index_for_offset(liga_set.index, &liga_offset); + + auto index_to_id = ligature_index_to_object_id(liga_set); + if (index_to_id.in_error()) return false; + + for (unsigned i = 0; i < liga_set.table->ligature.len; i++) { + unsigned liga_index = index_to_id[i]; if (liga_index != (unsigned) -1) { clear_virtual_links(c, liga_index); retained_indices.add(liga_index); diff --git a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc index 2da93481115..d3e8d892b7b 100644 --- a/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc +++ b/src/3rdparty/harfbuzz-ng/src/graph/test-classdef-graph.cc @@ -38,7 +38,7 @@ static unsigned actual_class_def_size(It glyph_and_class) { hb_serialize_context_t serializer(buffer, 100); OT::ClassDef_serialize (&serializer, glyph_and_class); serializer.end_serialize (); - assert(!serializer.in_error()); + hb_always_assert(!serializer.in_error()); hb_blob_t* blob = serializer.copy_blob(); unsigned size = hb_blob_get_length(blob); @@ -66,7 +66,7 @@ static unsigned actual_coverage_size(It glyphs) { hb_serialize_context_t serializer(buffer, 100); OT::Layout::Common::Coverage_serialize (&serializer, glyphs); serializer.end_serialize (); - assert(!serializer.in_error()); + hb_always_assert(!serializer.in_error()); hb_blob_t* blob = serializer.copy_blob(); unsigned size = hb_blob_get_length(blob); @@ -101,9 +101,9 @@ static bool check_coverage_size(graph::class_def_size_estimator_t& estimator, return true; } -static bool check_add_class_def_size(graph::class_def_size_estimator_t& estimator, - const gid_and_class_list_t& map, - unsigned klass, hb_vector_t<unsigned> klasses) +static HB_UNUSED bool check_add_class_def_size(graph::class_def_size_estimator_t& estimator, + const gid_and_class_list_t& map, + unsigned klass, hb_vector_t<unsigned> klasses) { unsigned result = estimator.add_class_def_size(klass); unsigned expected = actual_class_def_size(map, klasses); @@ -115,7 +115,7 @@ static bool check_add_class_def_size(graph::class_def_size_estimator_t& estimato return check_coverage_size(estimator, map, klasses); } -static bool check_add_class_def_size (const gid_and_class_list_t& list, unsigned klass) +static HB_UNUSED bool check_add_class_def_size (const gid_and_class_list_t& list, unsigned klass) { graph::class_def_size_estimator_t estimator (list.iter ()); @@ -149,13 +149,13 @@ static void test_class_and_coverage_size_estimates () { gid_and_class_list_t empty = { }; - assert (check_add_class_def_size (empty, 0)); - assert (check_add_class_def_size (empty, 1)); + hb_always_assert (check_add_class_def_size (empty, 0)); + hb_always_assert (check_add_class_def_size (empty, 1)); gid_and_class_list_t class_zero = { {5, 0}, }; - assert (check_add_class_def_size (class_zero, 0)); + hb_always_assert (check_add_class_def_size (class_zero, 0)); gid_and_class_list_t consecutive = { {4, 0}, @@ -169,9 +169,9 @@ static void test_class_and_coverage_size_estimates () {10, 2}, {11, 2}, }; - assert (check_add_class_def_size (consecutive, 0)); - assert (check_add_class_def_size (consecutive, 1)); - assert (check_add_class_def_size (consecutive, 2)); + hb_always_assert (check_add_class_def_size (consecutive, 0)); + hb_always_assert (check_add_class_def_size (consecutive, 1)); + hb_always_assert (check_add_class_def_size (consecutive, 2)); gid_and_class_list_t non_consecutive = { {4, 0}, @@ -185,9 +185,9 @@ static void test_class_and_coverage_size_estimates () {11, 2}, {13, 2}, }; - assert (check_add_class_def_size (non_consecutive, 0)); - assert (check_add_class_def_size (non_consecutive, 1)); - assert (check_add_class_def_size (non_consecutive, 2)); + hb_always_assert (check_add_class_def_size (non_consecutive, 0)); + hb_always_assert (check_add_class_def_size (non_consecutive, 1)); + hb_always_assert (check_add_class_def_size (non_consecutive, 2)); gid_and_class_list_t multiple_ranges = { {4, 0}, @@ -202,8 +202,8 @@ static void test_class_and_coverage_size_estimates () {12, 1}, {13, 1}, }; - assert (check_add_class_def_size (multiple_ranges, 0)); - assert (check_add_class_def_size (multiple_ranges, 1)); + hb_always_assert (check_add_class_def_size (multiple_ranges, 0)); + hb_always_assert (check_add_class_def_size (multiple_ranges, 1)); } static void test_running_class_and_coverage_size_estimates () { @@ -229,14 +229,14 @@ static void test_running_class_and_coverage_size_estimates () { }; graph::class_def_size_estimator_t estimator1(consecutive_map.iter()); - assert(check_add_class_def_size(estimator1, consecutive_map, 1, {1})); - assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2})); - assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2})); // check that adding the same class again works - assert(check_add_class_def_size(estimator1, consecutive_map, 3, {1, 2, 3})); + hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 1, {1})); + hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2})); + hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 2, {1, 2})); // check that adding the same class again works + hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 3, {1, 2, 3})); estimator1.reset(); - assert(check_add_class_def_size(estimator1, consecutive_map, 2, {2})); - assert(check_add_class_def_size(estimator1, consecutive_map, 3, {2, 3})); + hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 2, {2})); + hb_always_assert(check_add_class_def_size(estimator1, consecutive_map, 3, {2, 3})); // #### With non-consecutive gids: always uses format 2 ### gid_and_class_list_t non_consecutive_map = { @@ -261,13 +261,13 @@ static void test_running_class_and_coverage_size_estimates () { }; graph::class_def_size_estimator_t estimator2(non_consecutive_map.iter()); - assert(check_add_class_def_size(estimator2, non_consecutive_map, 1, {1})); - assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {1, 2})); - assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {1, 2, 3})); + hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 1, {1})); + hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {1, 2})); + hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {1, 2, 3})); estimator2.reset(); - assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {2})); - assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {2, 3})); + hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 2, {2})); + hb_always_assert(check_add_class_def_size(estimator2, non_consecutive_map, 3, {2, 3})); } static void test_running_class_size_estimates_with_locally_consecutive_glyphs () { @@ -278,13 +278,13 @@ static void test_running_class_size_estimates_with_locally_consecutive_glyphs () }; graph::class_def_size_estimator_t estimator(map.iter()); - assert(check_add_class_def_size(estimator, map, 1, {1})); - assert(check_add_class_def_size(estimator, map, 2, {1, 2})); - assert(check_add_class_def_size(estimator, map, 3, {1, 2, 3})); + hb_always_assert(check_add_class_def_size(estimator, map, 1, {1})); + hb_always_assert(check_add_class_def_size(estimator, map, 2, {1, 2})); + hb_always_assert(check_add_class_def_size(estimator, map, 3, {1, 2, 3})); estimator.reset(); - assert(check_add_class_def_size(estimator, map, 2, {2})); - assert(check_add_class_def_size(estimator, map, 3, {2, 3})); + hb_always_assert(check_add_class_def_size(estimator, map, 2, {2})); + hb_always_assert(check_add_class_def_size(estimator, map, 3, {2, 3})); } int diff --git a/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc b/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc index 79fac9e62d5..f6a5a319c97 100644 --- a/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc +++ b/src/3rdparty/harfbuzz-ng/src/harfbuzz-subset.cc @@ -62,6 +62,11 @@ #include "hb-subset-plan-var.cc" #include "hb-subset-plan.cc" #include "hb-subset-serialize.cc" +#include "hb-subset-table-cff.cc" +#include "hb-subset-table-color.cc" +#include "hb-subset-table-layout.cc" +#include "hb-subset-table-other.cc" +#include "hb-subset-table-var.cc" #include "hb-subset.cc" #include "hb-ucd.cc" #include "hb-unicode.cc" diff --git a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh index 1941009f800..e84557984a7 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh @@ -290,7 +290,7 @@ struct hb_bit_page_t 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]) + for (const elt_t *p = &vv; i < len (); p = ((const elt_t *) &v[0]) + (++i)) if (*p) { *codepoint = i * ELT_BITS + elt_get_min (*p); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh index 26ec0b42257..0bb00c4c2e5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer-deserialize-text-unicode.hh @@ -32,7 +32,7 @@ #include "hb.hh" -#line 36 "hb-buffer-deserialize-text-unicode.hh" +#line 33 "hb-buffer-deserialize-text-unicode.hh" static const unsigned char _deserialize_text_unicode_trans_keys[] = { 0u, 0u, 43u, 102u, 48u, 102u, 48u, 124u, 48u, 57u, 62u, 124u, 48u, 124u, 60u, 117u, 85u, 117u, 85u, 117u, 0 @@ -150,12 +150,12 @@ _hb_buffer_deserialize_text_unicode (hb_buffer_t *buffer, hb_glyph_info_t info = {0}; const hb_glyph_position_t pos = {0}; -#line 154 "hb-buffer-deserialize-text-unicode.hh" +#line 147 "hb-buffer-deserialize-text-unicode.hh" { cs = deserialize_text_unicode_start; } -#line 159 "hb-buffer-deserialize-text-unicode.hh" +#line 150 "hb-buffer-deserialize-text-unicode.hh" { int _slen; int _trans; @@ -215,7 +215,7 @@ _resume: hb_memset (&info, 0, sizeof (info)); } break; -#line 219 "hb-buffer-deserialize-text-unicode.hh" +#line 203 "hb-buffer-deserialize-text-unicode.hh" } _again: @@ -238,7 +238,7 @@ _again: *end_ptr = p; } break; -#line 242 "hb-buffer-deserialize-text-unicode.hh" +#line 224 "hb-buffer-deserialize-text-unicode.hh" } } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh index ac76deb725e..b1a6ebf06b9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cache.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cache.hh @@ -75,6 +75,8 @@ struct hb_cache_t static_assert ((key_bits >= cache_bits), ""); static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), ""); + static constexpr unsigned MAX_VALUE = (1u << value_bits) - 1; + hb_cache_t () { clear (); } void clear () @@ -100,6 +102,12 @@ struct hb_cache_t { if (unlikely ((key >> key_bits) || (value >> value_bits))) return; /* Overflows */ + set_unchecked (key, value); + } + + HB_HOT + void set_unchecked (unsigned int key, unsigned int value) + { unsigned int k = key & ((1u<<cache_bits)-1); unsigned int v = ((key>>cache_bits)<<value_bits) | value; values[k] = v; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh b/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh index 22871e30c90..27a0c8cf920 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-cff2-interp-cs.hh @@ -72,7 +72,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs> cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd, const int *coords_=nullptr, unsigned int num_coords_=0) : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs), - cached_scalars_vector (&acc.cached_scalars_vector) + region_count (0), cached_scalars_vector (&acc.cached_scalars_vector) { coords = coords_; num_coords = num_coords_; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-config.hh b/src/3rdparty/harfbuzz-ng/src/hb-config.hh index 3956690da35..68bc7a1a57f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-config.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-config.hh @@ -91,7 +91,10 @@ #ifdef HB_MINI #define HB_NO_AAT #define HB_NO_LEGACY -#define HB_NO_BORING_EXPANSION +#define HB_NO_BEYOND_64K +#define HB_NO_CUBIC_GLYF +#define HB_NO_VAR_COMPOSITES +#define HB_NO_VAR_HVF #endif #ifdef __OPTIMIZE_SIZE__ @@ -109,12 +112,6 @@ /* Closure of options. */ -#ifdef HB_NO_BORING_EXPANSION -#define HB_NO_BEYOND_64K -#define HB_NO_CUBIC_GLYF -#define HB_NO_VAR_COMPOSITES -#endif - #ifdef HB_NO_VAR #define HB_NO_VAR_COMPOSITES #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh index f79b42bc4b3..1f7a7f925a2 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-debug.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-debug.hh @@ -394,6 +394,10 @@ struct hb_no_trace_t { #define HB_DEBUG_WASM (HB_DEBUG+0) #endif +#ifndef HB_DEBUG_KBTS +#define HB_DEBUG_KBTS (HB_DEBUG+0) +#endif + /* * With tracing. */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-face.cc b/src/3rdparty/harfbuzz-ng/src/hb-face.cc index 3a504510921..b0cc787d0d1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-face.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-face.cc @@ -84,8 +84,7 @@ hb_face_count (hb_blob_t *blob) hb_sanitize_context_t c (blob); - const char *start = hb_blob_get_data (blob, nullptr); - auto *ot = reinterpret_cast<OT::OpenTypeFontFile *> (const_cast<char *> (start)); + auto *ot = blob->as<OT::OpenTypeFontFile> (); if (unlikely (!ot->sanitize (&c))) return 0; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc index c547134d5f3..e2acdffb1db 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-graphite2.cc @@ -266,7 +266,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, gr_segment *seg = nullptr; const gr_slot *is; unsigned int ci = 0, ic = 0; - unsigned int curradvx = 0, curradvy = 0; + int curradvx = 0, curradvy = 0; unsigned int scratch_size; hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-harfrust.cc b/src/3rdparty/harfbuzz-ng/src/hb-harfrust.cc index 2f3eb259612..38c9c89d81d 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-harfrust.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-harfrust.cc @@ -30,6 +30,16 @@ /* + * buffer + */ +extern "C" void * +_hb_harfrust_buffer_create_rs (void); + +extern "C" void +_hb_harfrust_buffer_destroy_rs (void *data); + + +/* * shaper face data */ @@ -75,6 +85,7 @@ _hb_harfrust_shaper_font_data_destroy (hb_harfrust_font_data_t *data) _hb_harfrust_shaper_font_data_destroy_rs (data); } + /* * shape plan */ @@ -98,12 +109,13 @@ extern "C" hb_bool_t _hb_harfrust_shape_rs (const void *font_data, const void *face_data, const void *rs_shape_plan, + const void *rs_buffer, hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features); -static hb_user_data_key_t hr_shape_plan_key = {0}; +static hb_user_data_key_t hb_object_key = {0}; hb_bool_t _hb_harfrust_shape (hb_shape_plan_t *shape_plan, @@ -115,13 +127,31 @@ _hb_harfrust_shape (hb_shape_plan_t *shape_plan, const hb_harfrust_font_data_t *font_data = font->data.harfrust; const hb_harfrust_face_data_t *face_data = font->face->data.harfrust; +retry_buffer: + void *hr_buffer = hb_buffer_get_user_data (buffer, &hb_object_key); + if (unlikely (!hr_buffer)) + { + hr_buffer = _hb_harfrust_buffer_create_rs (); + if (unlikely (!hr_buffer)) + return false; + + if (!hb_buffer_set_user_data (buffer, + &hb_object_key, + hr_buffer, + _hb_harfrust_buffer_destroy_rs, + false)) + { + _hb_harfrust_buffer_destroy_rs (hr_buffer); + goto retry_buffer; + } + } + void *hr_shape_plan = nullptr; if (!num_features) { - retry: - hr_shape_plan = hb_shape_plan_get_user_data (shape_plan, - &hr_shape_plan_key); + retry_shape_plan: + hr_shape_plan = hb_shape_plan_get_user_data (shape_plan, &hb_object_key); if (unlikely (!hr_shape_plan)) { hr_shape_plan = _hb_harfrust_shape_plan_create_rs (font_data, face_data, @@ -130,13 +160,13 @@ _hb_harfrust_shape (hb_shape_plan_t *shape_plan, shape_plan->key.props.direction); if (hr_shape_plan && !hb_shape_plan_set_user_data (shape_plan, - &hr_shape_plan_key, + &hb_object_key, hr_shape_plan, _hb_harfrust_shape_plan_destroy_rs, false)) { _hb_harfrust_shape_plan_destroy_rs (hr_shape_plan); - goto retry; + goto retry_shape_plan; } } } @@ -144,6 +174,7 @@ _hb_harfrust_shape (hb_shape_plan_t *shape_plan, return _hb_harfrust_shape_rs (font_data, face_data, hr_shape_plan, + hr_buffer, font, buffer, features, diff --git a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh index 04d09940aef..a9541597eb9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-iter.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-iter.hh @@ -972,7 +972,7 @@ struct Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (!hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it))) + if (!hb_match (p, hb_get (f, *it))) return false; return true; } @@ -989,7 +989,7 @@ struct Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it))) + if (hb_match (p, hb_get (f, *it))) return true; return false; } @@ -1006,7 +1006,7 @@ struct Proj&& f = hb_identity) const { for (auto it = hb_iter (c); it; ++it) - if (hb_match (std::forward<Pred> (p), hb_get (std::forward<Proj> (f), *it))) + if (hb_match (p, hb_get (f, *it))) return false; return true; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-kbts.cc b/src/3rdparty/harfbuzz-ng/src/hb-kbts.cc new file mode 100644 index 00000000000..eb3bfc22576 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-kbts.cc @@ -0,0 +1,259 @@ +/* + * 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. + * + * Author(s): Khaled Hosny + */ + +#include "hb.hh" + +#if HAVE_KBTS + +#include "hb-shaper-impl.hh" + +#define KB_TEXT_SHAPE_IMPLEMENTATION +#define KB_TEXT_SHAPE_STATIC +#define KB_TEXT_SHAPE_NO_CRT +#define KBTS_MEMSET hb_memset + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wsign-compare" +#include "kb_text_shape.h" +#pragma GCC diagnostic pop + + +hb_kbts_face_data_t * +_hb_kbts_shaper_face_data_create (hb_face_t *face) +{ + hb_blob_t *blob = hb_face_reference_blob (face); + + unsigned int blob_length; + const char *blob_data = hb_blob_get_data (blob, &blob_length); + if (unlikely (!blob_length)) + { + DEBUG_MSG (KBTS, blob, "Empty blob"); + hb_blob_destroy (blob); + return nullptr; + } + + void *data = hb_malloc (blob_length); + if (likely (data)) + hb_memcpy (data, blob_data, blob_length); + + hb_blob_destroy (blob); + blob = nullptr; + + if (unlikely (!data)) + { + DEBUG_MSG (KBTS, face, "Failed to allocate memory for font data"); + return nullptr; + } + + kbts_font *kb_font = (kbts_font *) hb_calloc (1, sizeof (kbts_font)); + if (unlikely (!kb_font)) + { + hb_free (data); + return nullptr; + } + + size_t memory_size; + { + unsigned scratch_size = kbts_ReadFontHeader (kb_font, data, blob_length); + void *scratch = hb_malloc (scratch_size); + memory_size = kbts_ReadFontData (kb_font, scratch, scratch_size); + hb_free (scratch); + } + + void *memory = hb_malloc (memory_size); + if (unlikely (!kbts_PostReadFontInitialize (kb_font, memory, memory_size))) + { + DEBUG_MSG (KBTS, face, "kbts_PostReadFontInitialize failed"); + hb_free (memory); + hb_free (data); + hb_free (kb_font); + return nullptr; + } + + return (hb_kbts_face_data_t *) kb_font; +} + +void +_hb_kbts_shaper_face_data_destroy (hb_kbts_face_data_t *data) +{ + kbts_font *font = (kbts_font *) data; + + assert (kbts_FontIsValid (font)); + + hb_free (font->FileBase); + hb_free (font->GlyphLookupMatrix); + hb_free (font); +} + +hb_kbts_font_data_t * +_hb_kbts_shaper_font_data_create (hb_font_t *font) +{ + return (hb_kbts_font_data_t *) HB_SHAPER_DATA_SUCCEEDED; +} + +void +_hb_kbts_shaper_font_data_destroy (hb_kbts_font_data_t *data) +{ +} + +hb_bool_t +_hb_kbts_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; + kbts_font *kb_font = (kbts_font *) (const void *) face->data.kbts; + + kbts_direction kb_direction; + switch (buffer->props.direction) + { + case HB_DIRECTION_LTR: kb_direction = KBTS_DIRECTION_LTR; break; + case HB_DIRECTION_RTL: kb_direction = KBTS_DIRECTION_RTL; break; + case HB_DIRECTION_TTB: + case HB_DIRECTION_BTT: + DEBUG_MSG (KBTS, face, "Vertical direction is not supported"); + return false; + default: + case HB_DIRECTION_INVALID: + DEBUG_MSG (KBTS, face, "Invalid direction"); + return false; + } + + kbts_script kb_script = KBTS_SCRIPT_DONT_KNOW; + kbts_language kb_language = KBTS_LANGUAGE_DEFAULT; + { + hb_tag_t scripts[HB_OT_MAX_TAGS_PER_SCRIPT]; + hb_tag_t language; + unsigned int script_count = ARRAY_LENGTH (scripts); + unsigned int language_count = 1; + + hb_ot_tags_from_script_and_language (buffer->props.script, buffer->props.language, + &script_count, scripts, + &language_count, &language); + + for (unsigned int i = 0; i < script_count && scripts[i] != HB_TAG_NONE; ++i) + { + kb_script = kbts_ScriptTagToScript (hb_uint32_swap (scripts[i])); + if (kb_script != KBTS_SCRIPT_DONT_KNOW) + break; + } + + if (language_count) + kb_language = (kbts_language) hb_uint32_swap (language); + } + + hb_vector_t<kbts_glyph> kb_glyphs; + if (unlikely (!kb_glyphs.resize_exact (buffer->len, false))) + return false; + + for (size_t i = 0; i < buffer->len; ++i) + kb_glyphs.arrayZ[i] = kbts_CodepointToGlyph (kb_font, buffer->info[i].codepoint); + + if (num_features) + { + for (unsigned int i = 0; i < num_features; ++i) + { + hb_feature_t feature = features[i]; + for (unsigned int j = 0; j < buffer->len; ++j) + { + kbts_glyph *kb_glyph = &kb_glyphs.arrayZ[j]; + if (hb_in_range (j, feature.start, feature.end)) + { + if (!kb_glyph->Config) + kb_glyph->Config = (kbts_glyph_config *) hb_calloc (1, sizeof (kbts_glyph_config)); + kbts_glyph_config *config = kb_glyph->Config; + while (!kbts_GlyphConfigOverrideFeatureFromTag (config, hb_uint32_swap (feature.tag), + feature.value > 1, feature.value)) + { + config->FeatureOverrides = (kbts_feature_override *) hb_realloc (config->FeatureOverrides, + config->RequiredFeatureOverrideCapacity); + config->FeatureOverrideCapacity += 1; + } + } + } + } + } + + kbts_shape_state *kb_shape_state; + { + size_t kb_shape_state_size = kbts_SizeOfShapeState (kb_font); + void *kb_shape_state_buffer = hb_malloc (kb_shape_state_size); + if (unlikely (!kb_shape_state_buffer)) + { + DEBUG_MSG (KBTS, face, "Failed to allocate memory for shape state"); + return false; + } + kb_shape_state = kbts_PlaceShapeState (kb_shape_state_buffer, kb_shape_state_size); + } + kbts_shape_config kb_shape_config = kbts_ShapeConfig (kb_font, kb_script, kb_language); + uint32_t glyph_count = buffer->len; + uint32_t glyph_capacity = kb_glyphs.length; + while (kbts_Shape (kb_shape_state, &kb_shape_config, KBTS_DIRECTION_LTR, kb_direction, + kb_glyphs.arrayZ, &glyph_count, glyph_capacity)) + { + glyph_capacity = kb_shape_state->RequiredGlyphCapacity; + /* kb increases capacity by a fixed number only. We increase it by 50% to + * avoid O(n^2) behavior in case of expanding text. + * + * https://github.com/JimmyLefevre/kb/issues/32 + */ + glyph_capacity += glyph_capacity / 2; + if (unlikely (!kb_glyphs.resize_exact (glyph_capacity, false))) + return false; + } + + hb_buffer_set_content_type (buffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); + hb_buffer_set_length (buffer, glyph_count); + + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; + + buffer->clear_positions (); + for (size_t i = 0; i < glyph_count; ++i) + { + kbts_glyph kb_glyph = kb_glyphs.arrayZ[i]; + info[i].codepoint = kb_glyph.Id; + info[i].cluster = 0; // FIXME + pos[i].x_advance = font->em_scalef_x (kb_glyph.AdvanceX); + pos[i].y_advance = font->em_scalef_y (kb_glyph.AdvanceY); + pos[i].x_offset = font->em_scalef_x (kb_glyph.OffsetX); + pos[i].y_offset = font->em_scalef_y (kb_glyph.OffsetY); + + if (kb_glyph.Config) + hb_free (kb_glyph.Config->FeatureOverrides); + } + + hb_free (kb_shape_state); + + buffer->clear_glyph_flags (); + buffer->unsafe_to_break (); + + return true; +} + +#endif
\ No newline at end of file diff --git a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh index 4916765e8fd..869fdba0ffc 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-machinery.hh @@ -70,11 +70,18 @@ static inline Type& StructAtOffsetUnaligned(void *P, unsigned int offset) * Any extra arguments are forwarded to get_size, so for example * it can work with UnsizedArrayOf<> as well. */ template <typename Type, typename TObject, typename ...Ts> -static inline const Type& StructAfter(const TObject &X, Ts... args) -{ return StructAtOffset<Type>(&X, X.get_size(args...)); } +static inline auto StructAfter(const TObject &X, Ts... args) HB_AUTO_RETURN(( + StructAtOffset<Type>(&X, X.get_size(std::forward<Ts> (args)...)) +)) +/* The is_const shenanigans is to avoid ambiguous overload with gcc-8. + * It disables this path when TObject is const. + * See: https://github.com/harfbuzz/harfbuzz/issues/5429 */ template <typename Type, typename TObject, typename ...Ts> -static inline Type& StructAfter(TObject &X, Ts... args) -{ return StructAtOffset<Type>(&X, X.get_size(args...)); } +static inline auto StructAfter(TObject &X, Ts... args) HB_AUTO_RETURN(( + sizeof(int[std::is_const<TObject>::value ? -1 : +1]) > 0 ? + StructAtOffset<Type>(&X, X.get_size(std::forward<Ts> (args)...)) + : *reinterpret_cast<Type*> (0) +)) /* diff --git a/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh b/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh index 1a9dbba6dd3..ec68c3a7281 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-number-parser.hh @@ -31,7 +31,7 @@ #include "hb.hh" -#line 35 "hb-number-parser.hh" +#line 32 "hb-number-parser.hh" static const unsigned char _double_parser_trans_keys[] = { 0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u, 46u, 101u, 0 @@ -135,12 +135,12 @@ strtod_rl (const char *p, const char **end_ptr /* IN/OUT */) int cs; -#line 139 "hb-number-parser.hh" +#line 132 "hb-number-parser.hh" { cs = double_parser_start; } -#line 144 "hb-number-parser.hh" +#line 135 "hb-number-parser.hh" { int _slen; int _trans; @@ -198,7 +198,7 @@ _resume: exp_overflow = true; } break; -#line 202 "hb-number-parser.hh" +#line 187 "hb-number-parser.hh" } _again: diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh index b49c0be5171..4308a73442b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff-common.hh @@ -79,7 +79,7 @@ struct Dict : UnsizedByteStr { TRACE_SERIALIZE (this); for (unsigned int i = 0; i < dictval.get_count (); i++) - if (unlikely (!opszr.serialize (c, dictval[i], std::forward<Ts> (ds)...))) + if (unlikely (!opszr.serialize (c, dictval[i], ds...))) return_trace (false); return_trace (true); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-std-str.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-std-str.hh index 65d56ae18b5..bf56abb975c 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-std-str.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cff1-std-str.hh @@ -30,396 +30,396 @@ #include "hb.hh" #endif -_S(".notdef") -_S("space") -_S("exclam") -_S("quotedbl") -_S("numbersign") -_S("dollar") -_S("percent") -_S("ampersand") -_S("quoteright") -_S("parenleft") -_S("parenright") -_S("asterisk") -_S("plus") -_S("comma") -_S("hyphen") -_S("period") -_S("slash") -_S("zero") -_S("one") -_S("two") -_S("three") -_S("four") -_S("five") -_S("six") -_S("seven") -_S("eight") -_S("nine") -_S("colon") -_S("semicolon") -_S("less") -_S("equal") -_S("greater") -_S("question") -_S("at") -_S("A") -_S("B") -_S("C") -_S("D") -_S("E") -_S("F") -_S("G") -_S("H") -_S("I") -_S("J") -_S("K") -_S("L") -_S("M") -_S("N") -_S("O") -_S("P") -_S("Q") -_S("R") -_S("S") -_S("T") -_S("U") -_S("V") -_S("W") -_S("X") -_S("Y") -_S("Z") -_S("bracketleft") -_S("backslash") -_S("bracketright") -_S("asciicircum") -_S("underscore") -_S("quoteleft") -_S("a") -_S("b") -_S("c") -_S("d") -_S("e") -_S("f") -_S("g") -_S("h") -_S("i") -_S("j") -_S("k") -_S("l") -_S("m") -_S("n") -_S("o") -_S("p") -_S("q") -_S("r") -_S("s") -_S("t") -_S("u") -_S("v") -_S("w") -_S("x") -_S("y") -_S("z") -_S("braceleft") -_S("bar") -_S("braceright") -_S("asciitilde") -_S("exclamdown") -_S("cent") -_S("sterling") -_S("fraction") -_S("yen") -_S("florin") -_S("section") -_S("currency") -_S("quotesingle") -_S("quotedblleft") -_S("guillemotleft") -_S("guilsinglleft") -_S("guilsinglright") -_S("fi") -_S("fl") -_S("endash") -_S("dagger") -_S("daggerdbl") -_S("periodcentered") -_S("paragraph") -_S("bullet") -_S("quotesinglbase") -_S("quotedblbase") -_S("quotedblright") -_S("guillemotright") -_S("ellipsis") -_S("perthousand") -_S("questiondown") -_S("grave") -_S("acute") -_S("circumflex") -_S("tilde") -_S("macron") -_S("breve") -_S("dotaccent") -_S("dieresis") -_S("ring") -_S("cedilla") -_S("hungarumlaut") -_S("ogonek") -_S("caron") -_S("emdash") -_S("AE") -_S("ordfeminine") -_S("Lslash") -_S("Oslash") -_S("OE") -_S("ordmasculine") -_S("ae") -_S("dotlessi") -_S("lslash") -_S("oslash") -_S("oe") -_S("germandbls") -_S("onesuperior") -_S("logicalnot") -_S("mu") -_S("trademark") -_S("Eth") -_S("onehalf") -_S("plusminus") -_S("Thorn") -_S("onequarter") -_S("divide") -_S("brokenbar") -_S("degree") -_S("thorn") -_S("threequarters") -_S("twosuperior") -_S("registered") -_S("minus") -_S("eth") -_S("multiply") -_S("threesuperior") -_S("copyright") -_S("Aacute") -_S("Acircumflex") -_S("Adieresis") -_S("Agrave") -_S("Aring") -_S("Atilde") -_S("Ccedilla") -_S("Eacute") -_S("Ecircumflex") -_S("Edieresis") -_S("Egrave") -_S("Iacute") -_S("Icircumflex") -_S("Idieresis") -_S("Igrave") -_S("Ntilde") -_S("Oacute") -_S("Ocircumflex") -_S("Odieresis") -_S("Ograve") -_S("Otilde") -_S("Scaron") -_S("Uacute") -_S("Ucircumflex") -_S("Udieresis") -_S("Ugrave") -_S("Yacute") -_S("Ydieresis") -_S("Zcaron") -_S("aacute") -_S("acircumflex") -_S("adieresis") -_S("agrave") -_S("aring") -_S("atilde") -_S("ccedilla") -_S("eacute") -_S("ecircumflex") -_S("edieresis") -_S("egrave") -_S("iacute") -_S("icircumflex") -_S("idieresis") -_S("igrave") -_S("ntilde") -_S("oacute") -_S("ocircumflex") -_S("odieresis") -_S("ograve") -_S("otilde") -_S("scaron") -_S("uacute") -_S("ucircumflex") -_S("udieresis") -_S("ugrave") -_S("yacute") -_S("ydieresis") -_S("zcaron") -_S("exclamsmall") -_S("Hungarumlautsmall") -_S("dollaroldstyle") -_S("dollarsuperior") -_S("ampersandsmall") -_S("Acutesmall") -_S("parenleftsuperior") -_S("parenrightsuperior") -_S("twodotenleader") -_S("onedotenleader") -_S("zerooldstyle") -_S("oneoldstyle") -_S("twooldstyle") -_S("threeoldstyle") -_S("fouroldstyle") -_S("fiveoldstyle") -_S("sixoldstyle") -_S("sevenoldstyle") -_S("eightoldstyle") -_S("nineoldstyle") -_S("commasuperior") -_S("threequartersemdash") -_S("periodsuperior") -_S("questionsmall") -_S("asuperior") -_S("bsuperior") -_S("centsuperior") -_S("dsuperior") -_S("esuperior") -_S("isuperior") -_S("lsuperior") -_S("msuperior") -_S("nsuperior") -_S("osuperior") -_S("rsuperior") -_S("ssuperior") -_S("tsuperior") -_S("ff") -_S("ffi") -_S("ffl") -_S("parenleftinferior") -_S("parenrightinferior") -_S("Circumflexsmall") -_S("hyphensuperior") -_S("Gravesmall") -_S("Asmall") -_S("Bsmall") -_S("Csmall") -_S("Dsmall") -_S("Esmall") -_S("Fsmall") -_S("Gsmall") -_S("Hsmall") -_S("Ismall") -_S("Jsmall") -_S("Ksmall") -_S("Lsmall") -_S("Msmall") -_S("Nsmall") -_S("Osmall") -_S("Psmall") -_S("Qsmall") -_S("Rsmall") -_S("Ssmall") -_S("Tsmall") -_S("Usmall") -_S("Vsmall") -_S("Wsmall") -_S("Xsmall") -_S("Ysmall") -_S("Zsmall") -_S("colonmonetary") -_S("onefitted") -_S("rupiah") -_S("Tildesmall") -_S("exclamdownsmall") -_S("centoldstyle") -_S("Lslashsmall") -_S("Scaronsmall") -_S("Zcaronsmall") -_S("Dieresissmall") -_S("Brevesmall") -_S("Caronsmall") -_S("Dotaccentsmall") -_S("Macronsmall") -_S("figuredash") -_S("hypheninferior") -_S("Ogoneksmall") -_S("Ringsmall") -_S("Cedillasmall") -_S("questiondownsmall") -_S("oneeighth") -_S("threeeighths") -_S("fiveeighths") -_S("seveneighths") -_S("onethird") -_S("twothirds") -_S("zerosuperior") -_S("foursuperior") -_S("fivesuperior") -_S("sixsuperior") -_S("sevensuperior") -_S("eightsuperior") -_S("ninesuperior") -_S("zeroinferior") -_S("oneinferior") -_S("twoinferior") -_S("threeinferior") -_S("fourinferior") -_S("fiveinferior") -_S("sixinferior") -_S("seveninferior") -_S("eightinferior") -_S("nineinferior") -_S("centinferior") -_S("dollarinferior") -_S("periodinferior") -_S("commainferior") -_S("Agravesmall") -_S("Aacutesmall") -_S("Acircumflexsmall") -_S("Atildesmall") -_S("Adieresissmall") -_S("Aringsmall") -_S("AEsmall") -_S("Ccedillasmall") -_S("Egravesmall") -_S("Eacutesmall") -_S("Ecircumflexsmall") -_S("Edieresissmall") -_S("Igravesmall") -_S("Iacutesmall") -_S("Icircumflexsmall") -_S("Idieresissmall") -_S("Ethsmall") -_S("Ntildesmall") -_S("Ogravesmall") -_S("Oacutesmall") -_S("Ocircumflexsmall") -_S("Otildesmall") -_S("Odieresissmall") -_S("OEsmall") -_S("Oslashsmall") -_S("Ugravesmall") -_S("Uacutesmall") -_S("Ucircumflexsmall") -_S("Udieresissmall") -_S("Yacutesmall") -_S("Thornsmall") -_S("Ydieresissmall") -_S("001.000") -_S("001.001") -_S("001.002") -_S("001.003") -_S("Black") -_S("Bold") -_S("Book") -_S("Light") -_S("Medium") -_S("Regular") -_S("Roman") -_S("Semibold") +HB_STR(".notdef") +HB_STR("space") +HB_STR("exclam") +HB_STR("quotedbl") +HB_STR("numbersign") +HB_STR("dollar") +HB_STR("percent") +HB_STR("ampersand") +HB_STR("quoteright") +HB_STR("parenleft") +HB_STR("parenright") +HB_STR("asterisk") +HB_STR("plus") +HB_STR("comma") +HB_STR("hyphen") +HB_STR("period") +HB_STR("slash") +HB_STR("zero") +HB_STR("one") +HB_STR("two") +HB_STR("three") +HB_STR("four") +HB_STR("five") +HB_STR("six") +HB_STR("seven") +HB_STR("eight") +HB_STR("nine") +HB_STR("colon") +HB_STR("semicolon") +HB_STR("less") +HB_STR("equal") +HB_STR("greater") +HB_STR("question") +HB_STR("at") +HB_STR("A") +HB_STR("B") +HB_STR("C") +HB_STR("D") +HB_STR("E") +HB_STR("F") +HB_STR("G") +HB_STR("H") +HB_STR("I") +HB_STR("J") +HB_STR("K") +HB_STR("L") +HB_STR("M") +HB_STR("N") +HB_STR("O") +HB_STR("P") +HB_STR("Q") +HB_STR("R") +HB_STR("S") +HB_STR("T") +HB_STR("U") +HB_STR("V") +HB_STR("W") +HB_STR("X") +HB_STR("Y") +HB_STR("Z") +HB_STR("bracketleft") +HB_STR("backslash") +HB_STR("bracketright") +HB_STR("asciicircum") +HB_STR("underscore") +HB_STR("quoteleft") +HB_STR("a") +HB_STR("b") +HB_STR("c") +HB_STR("d") +HB_STR("e") +HB_STR("f") +HB_STR("g") +HB_STR("h") +HB_STR("i") +HB_STR("j") +HB_STR("k") +HB_STR("l") +HB_STR("m") +HB_STR("n") +HB_STR("o") +HB_STR("p") +HB_STR("q") +HB_STR("r") +HB_STR("s") +HB_STR("t") +HB_STR("u") +HB_STR("v") +HB_STR("w") +HB_STR("x") +HB_STR("y") +HB_STR("z") +HB_STR("braceleft") +HB_STR("bar") +HB_STR("braceright") +HB_STR("asciitilde") +HB_STR("exclamdown") +HB_STR("cent") +HB_STR("sterling") +HB_STR("fraction") +HB_STR("yen") +HB_STR("florin") +HB_STR("section") +HB_STR("currency") +HB_STR("quotesingle") +HB_STR("quotedblleft") +HB_STR("guillemotleft") +HB_STR("guilsinglleft") +HB_STR("guilsinglright") +HB_STR("fi") +HB_STR("fl") +HB_STR("endash") +HB_STR("dagger") +HB_STR("daggerdbl") +HB_STR("periodcentered") +HB_STR("paragraph") +HB_STR("bullet") +HB_STR("quotesinglbase") +HB_STR("quotedblbase") +HB_STR("quotedblright") +HB_STR("guillemotright") +HB_STR("ellipsis") +HB_STR("perthousand") +HB_STR("questiondown") +HB_STR("grave") +HB_STR("acute") +HB_STR("circumflex") +HB_STR("tilde") +HB_STR("macron") +HB_STR("breve") +HB_STR("dotaccent") +HB_STR("dieresis") +HB_STR("ring") +HB_STR("cedilla") +HB_STR("hungarumlaut") +HB_STR("ogonek") +HB_STR("caron") +HB_STR("emdash") +HB_STR("AE") +HB_STR("ordfeminine") +HB_STR("Lslash") +HB_STR("Oslash") +HB_STR("OE") +HB_STR("ordmasculine") +HB_STR("ae") +HB_STR("dotlessi") +HB_STR("lslash") +HB_STR("oslash") +HB_STR("oe") +HB_STR("germandbls") +HB_STR("onesuperior") +HB_STR("logicalnot") +HB_STR("mu") +HB_STR("trademark") +HB_STR("Eth") +HB_STR("onehalf") +HB_STR("plusminus") +HB_STR("Thorn") +HB_STR("onequarter") +HB_STR("divide") +HB_STR("brokenbar") +HB_STR("degree") +HB_STR("thorn") +HB_STR("threequarters") +HB_STR("twosuperior") +HB_STR("registered") +HB_STR("minus") +HB_STR("eth") +HB_STR("multiply") +HB_STR("threesuperior") +HB_STR("copyright") +HB_STR("Aacute") +HB_STR("Acircumflex") +HB_STR("Adieresis") +HB_STR("Agrave") +HB_STR("Aring") +HB_STR("Atilde") +HB_STR("Ccedilla") +HB_STR("Eacute") +HB_STR("Ecircumflex") +HB_STR("Edieresis") +HB_STR("Egrave") +HB_STR("Iacute") +HB_STR("Icircumflex") +HB_STR("Idieresis") +HB_STR("Igrave") +HB_STR("Ntilde") +HB_STR("Oacute") +HB_STR("Ocircumflex") +HB_STR("Odieresis") +HB_STR("Ograve") +HB_STR("Otilde") +HB_STR("Scaron") +HB_STR("Uacute") +HB_STR("Ucircumflex") +HB_STR("Udieresis") +HB_STR("Ugrave") +HB_STR("Yacute") +HB_STR("Ydieresis") +HB_STR("Zcaron") +HB_STR("aacute") +HB_STR("acircumflex") +HB_STR("adieresis") +HB_STR("agrave") +HB_STR("aring") +HB_STR("atilde") +HB_STR("ccedilla") +HB_STR("eacute") +HB_STR("ecircumflex") +HB_STR("edieresis") +HB_STR("egrave") +HB_STR("iacute") +HB_STR("icircumflex") +HB_STR("idieresis") +HB_STR("igrave") +HB_STR("ntilde") +HB_STR("oacute") +HB_STR("ocircumflex") +HB_STR("odieresis") +HB_STR("ograve") +HB_STR("otilde") +HB_STR("scaron") +HB_STR("uacute") +HB_STR("ucircumflex") +HB_STR("udieresis") +HB_STR("ugrave") +HB_STR("yacute") +HB_STR("ydieresis") +HB_STR("zcaron") +HB_STR("exclamsmall") +HB_STR("Hungarumlautsmall") +HB_STR("dollaroldstyle") +HB_STR("dollarsuperior") +HB_STR("ampersandsmall") +HB_STR("Acutesmall") +HB_STR("parenleftsuperior") +HB_STR("parenrightsuperior") +HB_STR("twodotenleader") +HB_STR("onedotenleader") +HB_STR("zerooldstyle") +HB_STR("oneoldstyle") +HB_STR("twooldstyle") +HB_STR("threeoldstyle") +HB_STR("fouroldstyle") +HB_STR("fiveoldstyle") +HB_STR("sixoldstyle") +HB_STR("sevenoldstyle") +HB_STR("eightoldstyle") +HB_STR("nineoldstyle") +HB_STR("commasuperior") +HB_STR("threequartersemdash") +HB_STR("periodsuperior") +HB_STR("questionsmall") +HB_STR("asuperior") +HB_STR("bsuperior") +HB_STR("centsuperior") +HB_STR("dsuperior") +HB_STR("esuperior") +HB_STR("isuperior") +HB_STR("lsuperior") +HB_STR("msuperior") +HB_STR("nsuperior") +HB_STR("osuperior") +HB_STR("rsuperior") +HB_STR("ssuperior") +HB_STR("tsuperior") +HB_STR("ff") +HB_STR("ffi") +HB_STR("ffl") +HB_STR("parenleftinferior") +HB_STR("parenrightinferior") +HB_STR("Circumflexsmall") +HB_STR("hyphensuperior") +HB_STR("Gravesmall") +HB_STR("Asmall") +HB_STR("Bsmall") +HB_STR("Csmall") +HB_STR("Dsmall") +HB_STR("Esmall") +HB_STR("Fsmall") +HB_STR("Gsmall") +HB_STR("Hsmall") +HB_STR("Ismall") +HB_STR("Jsmall") +HB_STR("Ksmall") +HB_STR("Lsmall") +HB_STR("Msmall") +HB_STR("Nsmall") +HB_STR("Osmall") +HB_STR("Psmall") +HB_STR("Qsmall") +HB_STR("Rsmall") +HB_STR("Ssmall") +HB_STR("Tsmall") +HB_STR("Usmall") +HB_STR("Vsmall") +HB_STR("Wsmall") +HB_STR("Xsmall") +HB_STR("Ysmall") +HB_STR("Zsmall") +HB_STR("colonmonetary") +HB_STR("onefitted") +HB_STR("rupiah") +HB_STR("Tildesmall") +HB_STR("exclamdownsmall") +HB_STR("centoldstyle") +HB_STR("Lslashsmall") +HB_STR("Scaronsmall") +HB_STR("Zcaronsmall") +HB_STR("Dieresissmall") +HB_STR("Brevesmall") +HB_STR("Caronsmall") +HB_STR("Dotaccentsmall") +HB_STR("Macronsmall") +HB_STR("figuredash") +HB_STR("hypheninferior") +HB_STR("Ogoneksmall") +HB_STR("Ringsmall") +HB_STR("Cedillasmall") +HB_STR("questiondownsmall") +HB_STR("oneeighth") +HB_STR("threeeighths") +HB_STR("fiveeighths") +HB_STR("seveneighths") +HB_STR("onethird") +HB_STR("twothirds") +HB_STR("zerosuperior") +HB_STR("foursuperior") +HB_STR("fivesuperior") +HB_STR("sixsuperior") +HB_STR("sevensuperior") +HB_STR("eightsuperior") +HB_STR("ninesuperior") +HB_STR("zeroinferior") +HB_STR("oneinferior") +HB_STR("twoinferior") +HB_STR("threeinferior") +HB_STR("fourinferior") +HB_STR("fiveinferior") +HB_STR("sixinferior") +HB_STR("seveninferior") +HB_STR("eightinferior") +HB_STR("nineinferior") +HB_STR("centinferior") +HB_STR("dollarinferior") +HB_STR("periodinferior") +HB_STR("commainferior") +HB_STR("Agravesmall") +HB_STR("Aacutesmall") +HB_STR("Acircumflexsmall") +HB_STR("Atildesmall") +HB_STR("Adieresissmall") +HB_STR("Aringsmall") +HB_STR("AEsmall") +HB_STR("Ccedillasmall") +HB_STR("Egravesmall") +HB_STR("Eacutesmall") +HB_STR("Ecircumflexsmall") +HB_STR("Edieresissmall") +HB_STR("Igravesmall") +HB_STR("Iacutesmall") +HB_STR("Icircumflexsmall") +HB_STR("Idieresissmall") +HB_STR("Ethsmall") +HB_STR("Ntildesmall") +HB_STR("Ogravesmall") +HB_STR("Oacutesmall") +HB_STR("Ocircumflexsmall") +HB_STR("Otildesmall") +HB_STR("Odieresissmall") +HB_STR("OEsmall") +HB_STR("Oslashsmall") +HB_STR("Ugravesmall") +HB_STR("Uacutesmall") +HB_STR("Ucircumflexsmall") +HB_STR("Udieresissmall") +HB_STR("Yacutesmall") +HB_STR("Thornsmall") +HB_STR("Ydieresissmall") +HB_STR("001.000") +HB_STR("001.001") +HB_STR("001.002") +HB_STR("001.003") +HB_STR("Black") +HB_STR("Bold") +HB_STR("Book") +HB_STR("Light") +HB_STR("Medium") +HB_STR("Regular") +HB_STR("Roman") +HB_STR("Semibold") #endif /* HB_OT_CFF1_STD_STR_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc index 0f19b55614f..76c4bf28d9b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-font.cc @@ -466,6 +466,11 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, { const auto &glyf = *ot_face->glyf; auto *scratch = glyf.acquire_scratch (); + if (unlikely (!scratch)) + { + ot_font->h.release_advance_cache (advance_cache); + goto fallback; + } OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar); for (unsigned int i = 0; i < count; i++) @@ -586,6 +591,11 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, { const auto &glyf = *ot_face->glyf; auto *scratch = glyf.acquire_scratch (); + if (unlikely (!scratch)) + { + ot_font->v.release_advance_cache (advance_cache); + goto fallback; + } OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar); for (unsigned int i = 0; i < count; i++) @@ -664,7 +674,7 @@ hb_ot_get_glyph_v_origins (hb_font_t *font, hb_position_t origin; unsigned cv; if (origin_cache->get (*first_glyph, &cv)) - origin = font->y_scale < 0 ? -cv : cv; + origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); else { origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph)); @@ -688,7 +698,7 @@ hb_ot_get_glyph_v_origins (hb_font_t *font, hb_position_t origin; unsigned cv; if (origin_cache->get (*first_glyph, &cv)) - origin = font->y_scale < 0 ? -cv : cv; + origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); else { origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph) + @@ -717,6 +727,11 @@ hb_ot_get_glyph_v_origins (hb_font_t *font, if (origin_cache && vmtx.has_data() && glyf.has_data ()) { auto *scratch = glyf.acquire_scratch (); + if (unlikely (!scratch)) + { + ot_font->v_origin.release_origin_cache (origin_cache); + return false; + } OT::hb_scalar_cache_t *gvar_cache = font->has_nonzero_coords ? ot_font->draw.acquire_gvar_cache (*ot_face->gvar) : nullptr; @@ -726,7 +741,7 @@ hb_ot_get_glyph_v_origins (hb_font_t *font, hb_position_t origin; unsigned cv; if (origin_cache->get (*first_glyph, &cv)) - origin = font->y_scale < 0 ? -cv : cv; + origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); else { origin = font->em_scalef_y (glyf.get_v_origin_with_var_unscaled (*first_glyph, font, *scratch, gvar_cache)); @@ -760,7 +775,7 @@ hb_ot_get_glyph_v_origins (hb_font_t *font, unsigned cv; if (origin_cache->get (*first_glyph, &cv)) - origin = font->y_scale < 0 ? -cv : cv; + origin = font->y_scale < 0 ? -static_cast<hb_position_t>(cv) : static_cast<hb_position_t>(cv); else { hb_glyph_extents_t extents = {0}; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh index 43a2d9cf76a..99ea3804263 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh @@ -371,9 +371,9 @@ struct hmtxvmtx hb_scalar_cache_t *store_cache = nullptr) const { unsigned int advance = get_advance_without_var_unscaled (glyph); - return advance + roundf (var_table->get_advance_delta_unscaled (glyph, + return hb_max(0.0f, advance + roundf (var_table->get_advance_delta_unscaled (glyph, font->coords, font->num_coords, - store_cache)); + store_cache))); } #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh index 06c3c0ee976..53c186f5c2e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common.hh @@ -1337,7 +1337,7 @@ struct Lookup TRACE_DISPATCH (this, lookup_type); unsigned int count = get_subtable_count (); for (unsigned int i = 0; i < count; i++) { - typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, std::forward<Ts> (ds)...); + typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...); if (c->stop_sublookup_iteration (r)) return_trace (r); } @@ -2078,7 +2078,7 @@ struct ClassDef } } unsigned int get_class (hb_codepoint_t glyph_id, - hb_ot_lookup_cache_t *cache) const + hb_ot_layout_mapping_cache_t *cache) const { unsigned klass; if (cache && cache->get (glyph_id, &klass)) return klass; @@ -2575,7 +2575,7 @@ struct hb_scalar_cache_t return scratch_cache; } - auto *cache = (hb_scalar_cache_t *) hb_malloc (sizeof (hb_scalar_cache_t) - sizeof (values) + sizeof (values[0]) * count); + auto *cache = (hb_scalar_cache_t *) hb_malloc (sizeof (hb_scalar_cache_t) - sizeof (static_values) + sizeof (static_values[0]) * count); if (unlikely (!cache)) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t); cache->length = count; @@ -2593,6 +2593,7 @@ struct hb_scalar_cache_t void clear () { + auto *values = &static_values[0]; for (unsigned i = 0; i < length; i++) values[i] = INVALID; } @@ -2605,6 +2606,7 @@ struct hb_scalar_cache_t *value = 0.f; return true; } + auto *values = &static_values[0]; auto *cached_value = &values[i]; if (*cached_value != INVALID) { @@ -2618,13 +2620,14 @@ struct hb_scalar_cache_t void set (unsigned i, float value) { if (unlikely (i >= length)) return; + auto *values = &static_values[0]; auto *cached_value = &values[i]; *cached_value = roundf(value * MULTIPLIER); } private: unsigned length; - mutable hb_atomic_t<int> values[STATIC_LENGTH]; + mutable hb_atomic_t<int> static_values[STATIC_LENGTH]; }; struct VarRegionList @@ -3439,7 +3442,7 @@ struct ItemVariationStore for (unsigned i = 0; i < count; i++) { hb_inc_bimap_t *map = inner_maps.push (); - if (!c->propagate_error(inner_maps)) + if (unlikely (!c->propagate_error(inner_maps))) return_trace(nullptr); auto &data = this+dataSets[i]; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh index 83325548ded..6f9bb18cd27 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-gsubgpos.hh @@ -455,7 +455,7 @@ struct matcher_t HB_ALWAYS_INLINE #endif may_skip_t may_skip (const context_t *c, - const hb_glyph_info_t &info) const + const hb_glyph_info_t &info) const { if (!c->check_glyph_property (&info, lookup_props)) return SKIP_YES; @@ -470,7 +470,7 @@ struct matcher_t } public: - unsigned int lookup_props = 0; + unsigned int lookup_props = (unsigned) -1; hb_mask_t mask = -1; bool ignore_zwnj = false; bool ignore_zwj = false; @@ -670,8 +670,14 @@ struct hb_ot_apply_context_t : { const char *get_name () { return "APPLY"; } typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index); + + template <typename T> + static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (return_t, obj.apply (c, nullptr) ) + template <typename T> + static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (return_t, obj.apply (c) ) template <typename T> - return_t dispatch (const T &obj) { return obj.apply (this); } + return_t dispatch (const T &obj) { return apply_(obj, this, hb_prioritize); } + static return_t default_return_value () { return false; } bool stop_sublookup_iteration (return_t r) const { return r; } return_t recurse (unsigned int sub_lookup_index) @@ -706,7 +712,8 @@ struct hb_ot_apply_context_t : hb_direction_t direction; hb_mask_t lookup_mask = 1; unsigned int lookup_index = (unsigned) -1; - unsigned int lookup_props = 0; + unsigned int lookup_props = (unsigned) -1; + unsigned int cached_props = (unsigned) -1; /* Cached glyph properties for the current lookup. */ unsigned int nesting_level_left = HB_MAX_NESTING_LEVEL; bool has_glyph_classes; @@ -772,15 +779,22 @@ struct hb_ot_apply_context_t : return buffer->random_state; } - bool match_properties_mark (hb_codepoint_t glyph, + HB_ALWAYS_INLINE + HB_HOT + bool match_properties_mark (const hb_glyph_info_t *info, unsigned int glyph_props, - unsigned int match_props) const + unsigned int match_props, + bool cached) const { /* If using mark filtering sets, the high short of * match_props has the set index. */ if (match_props & LookupFlag::UseMarkFilteringSet) - return gdef_accel.mark_set_covers (match_props >> 16, glyph); + { + if (cached && match_props == cached_props) + return _hb_glyph_info_matches (info); + return gdef_accel.mark_set_covers (match_props >> 16, info->codepoint); + } /* The second byte of match_props has the meaning * "ignore marks of attachment type different than @@ -796,7 +810,8 @@ struct hb_ot_apply_context_t : HB_ALWAYS_INLINE #endif bool check_glyph_property (const hb_glyph_info_t *info, - unsigned int match_props) const + unsigned match_props, + bool cached = true) const { unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info); @@ -807,7 +822,7 @@ struct hb_ot_apply_context_t : return false; if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) - return match_properties_mark (info->codepoint, glyph_props, match_props); + return match_properties_mark (info, glyph_props, match_props, cached); return true; } @@ -849,6 +864,10 @@ struct hb_ot_apply_context_t : } else _hb_glyph_info_set_glyph_props (&buffer->cur(), props); + + if (cached_props != (unsigned) -1) + _hb_glyph_info_set_match (&buffer->cur(), + check_glyph_property (&buffer->cur(), cached_props, false)); } void replace_glyph (hb_codepoint_t glyph_index) @@ -875,7 +894,7 @@ struct hb_ot_apply_context_t : } }; -enum class hb_ot_lookup_cache_op_t +enum class hb_ot_subtable_cache_op_t { CREATE, ENTER, @@ -886,43 +905,49 @@ enum class hb_ot_lookup_cache_op_t struct hb_accelerate_subtables_context_t : hb_dispatch_context_t<hb_accelerate_subtables_context_t> { - template <typename Type> - static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c) + template <typename T> + static inline auto apply_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<1>) HB_RETURN (bool, obj->apply (c, external_cache) ) + template <typename T> + static inline auto apply_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<0>) HB_RETURN (bool, obj->apply (c) ) + template <typename T> + static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache) { - const Type *typed_obj = (const Type *) obj; - return typed_obj->apply (c); + const T *typed_obj = (const T *) obj; + return apply_ (typed_obj, c, external_cache, hb_prioritize); } #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE template <typename T> - static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply_cached (c) ) + static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<2>) HB_RETURN (bool, obj->apply_cached (c, external_cache) ) template <typename T> - static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) ) - template <typename Type> - static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c) + static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<1>) HB_RETURN (bool, obj->apply (c, external_cache) ) + template <typename T> + static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<0>) HB_RETURN (bool, obj->apply (c) ) + template <typename T> + static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache) { - const Type *typed_obj = (const Type *) obj; - return apply_cached_ (typed_obj, c, hb_prioritize); + const T *typed_obj = (const T *) obj; + return apply_cached_ (typed_obj, c, external_cache, hb_prioritize); } template <typename T> static inline auto cache_func_ (void *p, - hb_ot_lookup_cache_op_t op, + hb_ot_subtable_cache_op_t op, hb_priority<1>) HB_RETURN (void *, T::cache_func (p, op) ) template <typename T=void> static inline void * cache_func_ (void *p, - hb_ot_lookup_cache_op_t op HB_UNUSED, - hb_priority<0>) { return (void *) false; } + hb_ot_subtable_cache_op_t op HB_UNUSED, + hb_priority<0>) { return nullptr; } template <typename Type> static inline void * cache_func_to (void *p, - hb_ot_lookup_cache_op_t op) + hb_ot_subtable_cache_op_t op) { return cache_func_<Type> (p, op, hb_prioritize); } #endif - typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c); - typedef void * (*hb_cache_func_t) (void *p, hb_ot_lookup_cache_op_t op); + typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c, void *external_cache); + typedef void * (*hb_cache_func_t) (void *p, hb_ot_subtable_cache_op_t op); struct hb_applicable_t { @@ -943,27 +968,37 @@ struct hb_accelerate_subtables_context_t : #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE apply_cached_func = apply_cached_func_; cache_func = cache_func_; + external_cache = cache_create (); #endif digest.init (); obj_.get_coverage ().collect_coverage (&digest); } +#ifdef HB_NO_OT_LAYOUT_LOOKUP_CACHE bool apply (hb_ot_apply_context_t *c) const { - return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c); + return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, nullptr); + } +#else + bool apply (hb_ot_apply_context_t *c) const + { + return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, external_cache); } -#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE bool apply_cached (hb_ot_apply_context_t *c) const { - return digest.may_have (c->buffer->cur().codepoint) && apply_cached_func (obj, c); + return digest.may_have (c->buffer->cur().codepoint) && apply_cached_func (obj, c, external_cache); + } + void *cache_create () const + { + return cache_func (nullptr, hb_ot_subtable_cache_op_t::CREATE); } bool cache_enter (hb_ot_apply_context_t *c) const { - return (bool) cache_func (c, hb_ot_lookup_cache_op_t::ENTER); + return (bool) cache_func (c, hb_ot_subtable_cache_op_t::ENTER); } void cache_leave (hb_ot_apply_context_t *c) const { - cache_func (c, hb_ot_lookup_cache_op_t::LEAVE); + cache_func (c, hb_ot_subtable_cache_op_t::LEAVE); } #endif @@ -973,6 +1008,7 @@ struct hb_accelerate_subtables_context_t : #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE hb_apply_func_t apply_cached_func; hb_cache_func_t cache_func; + void *external_cache; #endif hb_set_digest_t digest; }; @@ -1008,10 +1044,10 @@ struct hb_accelerate_subtables_context_t : * and we allocate the cache opportunity to the costliest subtable. */ unsigned cost = cache_cost (obj, hb_prioritize); - if (cost > cache_user_cost) + if (cost > subtable_cache_user_cost) { - cache_user_idx = i - 1; - cache_user_cost = cost; + subtable_cache_user_idx = i - 1; + subtable_cache_user_cost = cost; } #endif @@ -1026,8 +1062,8 @@ struct hb_accelerate_subtables_context_t : unsigned i = 0; #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - unsigned cache_user_idx = (unsigned) -1; - unsigned cache_user_cost = 0; + unsigned subtable_cache_user_idx = (unsigned) -1; + unsigned subtable_cache_user_cost = 0; #endif }; @@ -1176,38 +1212,50 @@ static inline bool match_class (hb_glyph_info_t &info, unsigned value, const voi const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); return class_def.get_class (info.codepoint) == value; } -static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data) +static inline unsigned get_class_cached (const ClassDef &class_def, hb_glyph_info_t &info) { unsigned klass = info.syllable(); if (klass < 255) - return klass == value; - const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); + return klass; klass = class_def.get_class (info.codepoint); if (likely (klass < 255)) info.syllable() = klass; - return klass == value; + return klass; } -static inline bool match_class_cached1 (hb_glyph_info_t &info, unsigned value, const void *data) +static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data) +{ + const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); + return get_class_cached (class_def, info) == value; +} +static inline unsigned get_class_cached1 (const ClassDef &class_def, hb_glyph_info_t &info) { unsigned klass = info.syllable() & 0x0F; if (klass < 15) - return klass == value; - const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); + return klass; klass = class_def.get_class (info.codepoint); if (likely (klass < 15)) info.syllable() = (info.syllable() & 0xF0) | klass; - return klass == value; + return klass; } -static inline bool match_class_cached2 (hb_glyph_info_t &info, unsigned value, const void *data) +static inline bool match_class_cached1 (hb_glyph_info_t &info, unsigned value, const void *data) +{ + const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); + return get_class_cached1 (class_def, info) == value; +} +static inline unsigned get_class_cached2 (const ClassDef &class_def, hb_glyph_info_t &info) { unsigned klass = (info.syllable() & 0xF0) >> 4; if (klass < 15) - return klass == value; - const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); + return klass; klass = class_def.get_class (info.codepoint); if (likely (klass < 15)) info.syllable() = (info.syllable() & 0x0F) | (klass << 4); - return klass == value; + return klass; +} +static inline bool match_class_cached2 (hb_glyph_info_t &info, unsigned value, const void *data) +{ + const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data); + return get_class_cached2 (class_def, info) == value; } static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data) { @@ -1321,7 +1369,7 @@ static bool match_input (hb_ot_apply_context_t *c, if (ligbase == LIGBASE_NOT_CHECKED) { bool found = false; - const auto *out = buffer->out_info; + auto *out = buffer->out_info; unsigned int j = buffer->out_len; while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id) { @@ -1979,6 +2027,37 @@ static bool context_apply_lookup (hb_ot_apply_context_t *c, return ret; } +static inline void * context_cache_func (void *p, hb_ot_subtable_cache_op_t op) +{ + switch (op) + { + case hb_ot_subtable_cache_op_t::CREATE: + return nullptr; + case hb_ot_subtable_cache_op_t::ENTER: + { + hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p; + if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable)) + return (void *) false; + auto &info = c->buffer->info; + unsigned count = c->buffer->len; + for (unsigned i = 0; i < count; i++) + info[i].syllable() = 255; + c->new_syllables = 255; + return (void *) true; + } + case hb_ot_subtable_cache_op_t::LEAVE: + { + hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p; + c->new_syllables = (unsigned) -1; + HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable); + return nullptr; + } + case hb_ot_subtable_cache_op_t::DESTROY: + return nullptr; + } + return nullptr; +} + template <typename Types> struct Rule { @@ -2607,41 +2686,14 @@ struct ContextFormat2_5 unsigned cache_cost () const { - unsigned c = (this+classDef).cost () * ruleSet.len; - return c >= 4 ? c : 0; + return (this+classDef).cost (); } - static void * cache_func (void *p, hb_ot_lookup_cache_op_t op) + static void * cache_func (void *p, hb_ot_subtable_cache_op_t op) { - switch (op) - { - case hb_ot_lookup_cache_op_t::CREATE: - return (void *) true; - case hb_ot_lookup_cache_op_t::ENTER: - { - hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p; - if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable)) - return (void *) false; - auto &info = c->buffer->info; - unsigned count = c->buffer->len; - for (unsigned i = 0; i < count; i++) - info[i].syllable() = 255; - c->new_syllables = 255; - return (void *) true; - } - case hb_ot_lookup_cache_op_t::LEAVE: - { - hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p; - c->new_syllables = (unsigned) -1; - HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable); - return nullptr; - } - case hb_ot_lookup_cache_op_t::DESTROY: - return nullptr; - } - return nullptr; + return context_cache_func (p, op); } - bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } + bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); } bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } bool _apply (hb_ot_apply_context_t *c, bool cached) const { @@ -2656,10 +2708,7 @@ struct ContextFormat2_5 &class_def }; - if (cached && c->buffer->cur().syllable() < 255) - index = c->buffer->cur().syllable (); - else - index = class_def.get_class (c->buffer->cur().codepoint); + index = cached ? get_class_cached (class_def, c->buffer->cur()) : class_def.get_class (c->buffer->cur().codepoint); const RuleSet &rule_set = this+ruleSet[index]; return_trace (rule_set.apply (c, lookup_context)); } @@ -3858,40 +3907,14 @@ struct ChainContextFormat2_5 unsigned cache_cost () const { - return (this+lookaheadClassDef).cost () * ruleSet.len; + return (this+inputClassDef).cost () + (this+lookaheadClassDef).cost (); } - static void * cache_func (void *p, hb_ot_lookup_cache_op_t op) + static void * cache_func (void *p, hb_ot_subtable_cache_op_t op) { - switch (op) - { - case hb_ot_lookup_cache_op_t::CREATE: - return (void *) true; - case hb_ot_lookup_cache_op_t::ENTER: - { - hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p; - if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable)) - return (void *) false; - auto &info = c->buffer->info; - unsigned count = c->buffer->len; - for (unsigned i = 0; i < count; i++) - info[i].syllable() = 255; - c->new_syllables = 255; - return (void *) true; - } - case hb_ot_lookup_cache_op_t::LEAVE: - { - hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p; - c->new_syllables = (unsigned) -1; - HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable); - return nullptr; - } - case hb_ot_lookup_cache_op_t::DESTROY: - return nullptr; - } - return nullptr; + return context_cache_func (p, op); } - bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); } + bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); } bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); } bool _apply (hb_ot_apply_context_t *c, bool cached) const { @@ -3914,11 +3937,9 @@ struct ChainContextFormat2_5 &lookahead_class_def} }; - // Note: Corresponds to match_class_cached2 - if (cached && ((c->buffer->cur().syllable() & 0xF0) >> 4) < 15) - index = (c->buffer->cur().syllable () & 0xF0) >> 4; - else - index = input_class_def.get_class (c->buffer->cur().codepoint); + index = cached + ? get_class_cached2 (input_class_def, c->buffer->cur()) + : input_class_def.get_class (c->buffer->cur().codepoint); const ChainRuleSet &rule_set = this+ruleSet[index]; return_trace (rule_set.apply (c, lookup_context)); } @@ -4414,21 +4435,12 @@ struct hb_ot_layout_lookup_accelerator_t thiz->digest.union_ (subtable.digest); #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - if (c_accelerate_subtables.cache_user_cost < 4) - c_accelerate_subtables.cache_user_idx = (unsigned) -1; - - thiz->cache_user_idx = c_accelerate_subtables.cache_user_idx; - - if (thiz->cache_user_idx != (unsigned) -1) - { - thiz->cache = thiz->subtables[thiz->cache_user_idx].cache_func (nullptr, hb_ot_lookup_cache_op_t::CREATE); - if (!thiz->cache) - thiz->cache_user_idx = (unsigned) -1; - } + thiz->count = count; + thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx; for (unsigned i = 0; i < count; i++) - if (i != thiz->cache_user_idx) - thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func; + if (i != thiz->subtable_cache_user_idx) + thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func; #endif return thiz; @@ -4437,11 +4449,9 @@ struct hb_ot_layout_lookup_accelerator_t void fini () { #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - if (cache) - { - assert (cache_user_idx != (unsigned) -1); - subtables[cache_user_idx].cache_func (cache, hb_ot_lookup_cache_op_t::DESTROY); - } + for (unsigned i = 0; i < count; i++) + if (subtables[i].external_cache) + subtables[i].cache_func (subtables[i].external_cache, hb_ot_subtable_cache_op_t::DESTROY); #endif } @@ -4478,8 +4488,8 @@ struct hb_ot_layout_lookup_accelerator_t bool cache_enter (hb_ot_apply_context_t *c) const { #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - return cache_user_idx != (unsigned) -1 && - subtables[cache_user_idx].cache_enter (c); + return subtable_cache_user_idx != (unsigned) -1 && + subtables[subtable_cache_user_idx].cache_enter (c); #else return false; #endif @@ -4487,17 +4497,16 @@ struct hb_ot_layout_lookup_accelerator_t void cache_leave (hb_ot_apply_context_t *c) const { #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - subtables[cache_user_idx].cache_leave (c); + subtables[subtable_cache_user_idx].cache_leave (c); #endif } hb_set_digest_t digest; #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE - public: - void *cache = nullptr; private: - unsigned cache_user_idx = (unsigned) -1; + unsigned count = 0; /* Number of subtables in the array. */ + unsigned subtable_cache_user_idx = (unsigned) -1; #endif private: hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY]; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc index 51572ce4b03..bc6ba54833b 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc @@ -1918,7 +1918,7 @@ apply_forward (OT::hb_ot_apply_context_t *c, const OT::hb_ot_layout_lookup_accelerator_t &accel, unsigned subtable_count) { - bool use_cache = accel.cache_enter (c); + bool use_hot_subtable_cache = accel.cache_enter (c); bool ret = false; hb_buffer_t *buffer = c->buffer; @@ -1930,7 +1930,7 @@ apply_forward (OT::hb_ot_apply_context_t *c, (cur.mask & c->lookup_mask) && c->check_glyph_property (&cur, c->lookup_props)) { - applied = accel.apply (c, subtable_count, use_cache); + applied = accel.apply (c, subtable_count, use_hot_subtable_cache); } if (applied) @@ -1939,7 +1939,7 @@ apply_forward (OT::hb_ot_apply_context_t *c, (void) buffer->next_glyph (); } - if (use_cache) + if (use_hot_subtable_cache) accel.cache_leave (c); return ret; @@ -1982,7 +1982,22 @@ apply_string (OT::hb_ot_apply_context_t *c, bool ret = false; - c->set_lookup_props (lookup.get_props ()); + unsigned lookup_props = lookup.get_props (); + if (lookup_props != c->cached_props) + { + bool cache_it = subtable_count > 1 && (lookup_props & OT::LookupFlag::UseMarkFilteringSet); + if (cache_it) + { + auto &info = buffer->info; + for (unsigned int i = 0; i < buffer->len; i++) + _hb_glyph_info_set_match (&info[i], + c->check_glyph_property (&info[i], lookup_props, false)); + c->cached_props = lookup_props; + } + else + c->cached_props = (unsigned) -1; + } + c->set_lookup_props (lookup_props); if (likely (!lookup.is_reverse ())) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh index a42212f291f..72de36bbb3e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.hh @@ -81,9 +81,10 @@ enum hb_ot_layout_glyph_props_flags_t HB_OT_LAYOUT_GLYPH_PROPS_MARK = 0x08u, /* The following are used internally; not derived from GDEF. */ - HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u, - HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u, - HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x40u, + HB_OT_LAYOUT_GLYPH_PROPS_MATCHES = 0x10u, + HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x20u, + HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x40u, + HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x80u, HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED | HB_OT_LAYOUT_GLYPH_PROPS_LIGATED | @@ -610,6 +611,20 @@ _hb_clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED, return false; } +static inline bool +_hb_glyph_info_matches (const hb_glyph_info_t *info) +{ + return info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MATCHES; +} +static inline void +_hb_glyph_info_set_match (hb_glyph_info_t *info, bool match) +{ + if (match) + info->glyph_props() |= HB_OT_LAYOUT_GLYPH_PROPS_MATCHES; + else + info->glyph_props() &= ~HB_OT_LAYOUT_GLYPH_PROPS_MATCHES; +} + /* Allocation / deallocation. */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-macroman.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-macroman.hh index b4df8aaeeab..269b4d3fe45 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-post-macroman.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-post-macroman.hh @@ -31,264 +31,264 @@ #endif -_S(".notdef") -_S(".null") -_S("nonmarkingreturn") -_S("space") -_S("exclam") -_S("quotedbl") -_S("numbersign") -_S("dollar") -_S("percent") -_S("ampersand") -_S("quotesingle") -_S("parenleft") -_S("parenright") -_S("asterisk") -_S("plus") -_S("comma") -_S("hyphen") -_S("period") -_S("slash") -_S("zero") -_S("one") -_S("two") -_S("three") -_S("four") -_S("five") -_S("six") -_S("seven") -_S("eight") -_S("nine") -_S("colon") -_S("semicolon") -_S("less") -_S("equal") -_S("greater") -_S("question") -_S("at") -_S("A") -_S("B") -_S("C") -_S("D") -_S("E") -_S("F") -_S("G") -_S("H") -_S("I") -_S("J") -_S("K") -_S("L") -_S("M") -_S("N") -_S("O") -_S("P") -_S("Q") -_S("R") -_S("S") -_S("T") -_S("U") -_S("V") -_S("W") -_S("X") -_S("Y") -_S("Z") -_S("bracketleft") -_S("backslash") -_S("bracketright") -_S("asciicircum") -_S("underscore") -_S("grave") -_S("a") -_S("b") -_S("c") -_S("d") -_S("e") -_S("f") -_S("g") -_S("h") -_S("i") -_S("j") -_S("k") -_S("l") -_S("m") -_S("n") -_S("o") -_S("p") -_S("q") -_S("r") -_S("s") -_S("t") -_S("u") -_S("v") -_S("w") -_S("x") -_S("y") -_S("z") -_S("braceleft") -_S("bar") -_S("braceright") -_S("asciitilde") -_S("Adieresis") -_S("Aring") -_S("Ccedilla") -_S("Eacute") -_S("Ntilde") -_S("Odieresis") -_S("Udieresis") -_S("aacute") -_S("agrave") -_S("acircumflex") -_S("adieresis") -_S("atilde") -_S("aring") -_S("ccedilla") -_S("eacute") -_S("egrave") -_S("ecircumflex") -_S("edieresis") -_S("iacute") -_S("igrave") -_S("icircumflex") -_S("idieresis") -_S("ntilde") -_S("oacute") -_S("ograve") -_S("ocircumflex") -_S("odieresis") -_S("otilde") -_S("uacute") -_S("ugrave") -_S("ucircumflex") -_S("udieresis") -_S("dagger") -_S("degree") -_S("cent") -_S("sterling") -_S("section") -_S("bullet") -_S("paragraph") -_S("germandbls") -_S("registered") -_S("copyright") -_S("trademark") -_S("acute") -_S("dieresis") -_S("notequal") -_S("AE") -_S("Oslash") -_S("infinity") -_S("plusminus") -_S("lessequal") -_S("greaterequal") -_S("yen") -_S("mu") -_S("partialdiff") -_S("summation") -_S("product") -_S("pi") -_S("integral") -_S("ordfeminine") -_S("ordmasculine") -_S("Omega") -_S("ae") -_S("oslash") -_S("questiondown") -_S("exclamdown") -_S("logicalnot") -_S("radical") -_S("florin") -_S("approxequal") -_S("Delta") -_S("guillemotleft") -_S("guillemotright") -_S("ellipsis") -_S("nonbreakingspace") -_S("Agrave") -_S("Atilde") -_S("Otilde") -_S("OE") -_S("oe") -_S("endash") -_S("emdash") -_S("quotedblleft") -_S("quotedblright") -_S("quoteleft") -_S("quoteright") -_S("divide") -_S("lozenge") -_S("ydieresis") -_S("Ydieresis") -_S("fraction") -_S("currency") -_S("guilsinglleft") -_S("guilsinglright") -_S("fi") -_S("fl") -_S("daggerdbl") -_S("periodcentered") -_S("quotesinglbase") -_S("quotedblbase") -_S("perthousand") -_S("Acircumflex") -_S("Ecircumflex") -_S("Aacute") -_S("Edieresis") -_S("Egrave") -_S("Iacute") -_S("Icircumflex") -_S("Idieresis") -_S("Igrave") -_S("Oacute") -_S("Ocircumflex") -_S("apple") -_S("Ograve") -_S("Uacute") -_S("Ucircumflex") -_S("Ugrave") -_S("dotlessi") -_S("circumflex") -_S("tilde") -_S("macron") -_S("breve") -_S("dotaccent") -_S("ring") -_S("cedilla") -_S("hungarumlaut") -_S("ogonek") -_S("caron") -_S("Lslash") -_S("lslash") -_S("Scaron") -_S("scaron") -_S("Zcaron") -_S("zcaron") -_S("brokenbar") -_S("Eth") -_S("eth") -_S("Yacute") -_S("yacute") -_S("Thorn") -_S("thorn") -_S("minus") -_S("multiply") -_S("onesuperior") -_S("twosuperior") -_S("threesuperior") -_S("onehalf") -_S("onequarter") -_S("threequarters") -_S("franc") -_S("Gbreve") -_S("gbreve") -_S("Idotaccent") -_S("Scedilla") -_S("scedilla") -_S("Cacute") -_S("cacute") -_S("Ccaron") -_S("ccaron") -_S("dcroat") +HB_STR(".notdef") +HB_STR(".null") +HB_STR("nonmarkingreturn") +HB_STR("space") +HB_STR("exclam") +HB_STR("quotedbl") +HB_STR("numbersign") +HB_STR("dollar") +HB_STR("percent") +HB_STR("ampersand") +HB_STR("quotesingle") +HB_STR("parenleft") +HB_STR("parenright") +HB_STR("asterisk") +HB_STR("plus") +HB_STR("comma") +HB_STR("hyphen") +HB_STR("period") +HB_STR("slash") +HB_STR("zero") +HB_STR("one") +HB_STR("two") +HB_STR("three") +HB_STR("four") +HB_STR("five") +HB_STR("six") +HB_STR("seven") +HB_STR("eight") +HB_STR("nine") +HB_STR("colon") +HB_STR("semicolon") +HB_STR("less") +HB_STR("equal") +HB_STR("greater") +HB_STR("question") +HB_STR("at") +HB_STR("A") +HB_STR("B") +HB_STR("C") +HB_STR("D") +HB_STR("E") +HB_STR("F") +HB_STR("G") +HB_STR("H") +HB_STR("I") +HB_STR("J") +HB_STR("K") +HB_STR("L") +HB_STR("M") +HB_STR("N") +HB_STR("O") +HB_STR("P") +HB_STR("Q") +HB_STR("R") +HB_STR("S") +HB_STR("T") +HB_STR("U") +HB_STR("V") +HB_STR("W") +HB_STR("X") +HB_STR("Y") +HB_STR("Z") +HB_STR("bracketleft") +HB_STR("backslash") +HB_STR("bracketright") +HB_STR("asciicircum") +HB_STR("underscore") +HB_STR("grave") +HB_STR("a") +HB_STR("b") +HB_STR("c") +HB_STR("d") +HB_STR("e") +HB_STR("f") +HB_STR("g") +HB_STR("h") +HB_STR("i") +HB_STR("j") +HB_STR("k") +HB_STR("l") +HB_STR("m") +HB_STR("n") +HB_STR("o") +HB_STR("p") +HB_STR("q") +HB_STR("r") +HB_STR("s") +HB_STR("t") +HB_STR("u") +HB_STR("v") +HB_STR("w") +HB_STR("x") +HB_STR("y") +HB_STR("z") +HB_STR("braceleft") +HB_STR("bar") +HB_STR("braceright") +HB_STR("asciitilde") +HB_STR("Adieresis") +HB_STR("Aring") +HB_STR("Ccedilla") +HB_STR("Eacute") +HB_STR("Ntilde") +HB_STR("Odieresis") +HB_STR("Udieresis") +HB_STR("aacute") +HB_STR("agrave") +HB_STR("acircumflex") +HB_STR("adieresis") +HB_STR("atilde") +HB_STR("aring") +HB_STR("ccedilla") +HB_STR("eacute") +HB_STR("egrave") +HB_STR("ecircumflex") +HB_STR("edieresis") +HB_STR("iacute") +HB_STR("igrave") +HB_STR("icircumflex") +HB_STR("idieresis") +HB_STR("ntilde") +HB_STR("oacute") +HB_STR("ograve") +HB_STR("ocircumflex") +HB_STR("odieresis") +HB_STR("otilde") +HB_STR("uacute") +HB_STR("ugrave") +HB_STR("ucircumflex") +HB_STR("udieresis") +HB_STR("dagger") +HB_STR("degree") +HB_STR("cent") +HB_STR("sterling") +HB_STR("section") +HB_STR("bullet") +HB_STR("paragraph") +HB_STR("germandbls") +HB_STR("registered") +HB_STR("copyright") +HB_STR("trademark") +HB_STR("acute") +HB_STR("dieresis") +HB_STR("notequal") +HB_STR("AE") +HB_STR("Oslash") +HB_STR("infinity") +HB_STR("plusminus") +HB_STR("lessequal") +HB_STR("greaterequal") +HB_STR("yen") +HB_STR("mu") +HB_STR("partialdiff") +HB_STR("summation") +HB_STR("product") +HB_STR("pi") +HB_STR("integral") +HB_STR("ordfeminine") +HB_STR("ordmasculine") +HB_STR("Omega") +HB_STR("ae") +HB_STR("oslash") +HB_STR("questiondown") +HB_STR("exclamdown") +HB_STR("logicalnot") +HB_STR("radical") +HB_STR("florin") +HB_STR("approxequal") +HB_STR("Delta") +HB_STR("guillemotleft") +HB_STR("guillemotright") +HB_STR("ellipsis") +HB_STR("nonbreakingspace") +HB_STR("Agrave") +HB_STR("Atilde") +HB_STR("Otilde") +HB_STR("OE") +HB_STR("oe") +HB_STR("endash") +HB_STR("emdash") +HB_STR("quotedblleft") +HB_STR("quotedblright") +HB_STR("quoteleft") +HB_STR("quoteright") +HB_STR("divide") +HB_STR("lozenge") +HB_STR("ydieresis") +HB_STR("Ydieresis") +HB_STR("fraction") +HB_STR("currency") +HB_STR("guilsinglleft") +HB_STR("guilsinglright") +HB_STR("fi") +HB_STR("fl") +HB_STR("daggerdbl") +HB_STR("periodcentered") +HB_STR("quotesinglbase") +HB_STR("quotedblbase") +HB_STR("perthousand") +HB_STR("Acircumflex") +HB_STR("Ecircumflex") +HB_STR("Aacute") +HB_STR("Edieresis") +HB_STR("Egrave") +HB_STR("Iacute") +HB_STR("Icircumflex") +HB_STR("Idieresis") +HB_STR("Igrave") +HB_STR("Oacute") +HB_STR("Ocircumflex") +HB_STR("apple") +HB_STR("Ograve") +HB_STR("Uacute") +HB_STR("Ucircumflex") +HB_STR("Ugrave") +HB_STR("dotlessi") +HB_STR("circumflex") +HB_STR("tilde") +HB_STR("macron") +HB_STR("breve") +HB_STR("dotaccent") +HB_STR("ring") +HB_STR("cedilla") +HB_STR("hungarumlaut") +HB_STR("ogonek") +HB_STR("caron") +HB_STR("Lslash") +HB_STR("lslash") +HB_STR("Scaron") +HB_STR("scaron") +HB_STR("Zcaron") +HB_STR("zcaron") +HB_STR("brokenbar") +HB_STR("Eth") +HB_STR("eth") +HB_STR("Yacute") +HB_STR("yacute") +HB_STR("Thorn") +HB_STR("thorn") +HB_STR("minus") +HB_STR("multiply") +HB_STR("onesuperior") +HB_STR("twosuperior") +HB_STR("threesuperior") +HB_STR("onehalf") +HB_STR("onequarter") +HB_STR("threequarters") +HB_STR("franc") +HB_STR("Gbreve") +HB_STR("gbreve") +HB_STR("Idotaccent") +HB_STR("Scedilla") +HB_STR("scedilla") +HB_STR("Cacute") +HB_STR("cacute") +HB_STR("Ccaron") +HB_STR("ccaron") +HB_STR("dcroat") #endif /* HB_OT_POST_MACROMAN_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc index 2d093f78b33..e9dbcd77aea 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.cc @@ -78,14 +78,14 @@ static inline void set_glyph (hb_glyph_info_t &info, hb_font_t *font) { - (void) font->get_nominal_glyph (info.codepoint, &info.glyph_index()); + (void) font->get_nominal_glyph (info.codepoint, &info.normalizer_glyph_index()); } static inline void output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph) { /* This is very confusing indeed. */ - buffer->cur().glyph_index() = glyph; + buffer->cur().normalizer_glyph_index() = glyph; (void) buffer->output_glyph (unichar); _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer); } @@ -93,7 +93,7 @@ output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph) static inline void next_char (hb_buffer_t *buffer, hb_codepoint_t glyph) { - buffer->cur().glyph_index() = glyph; + buffer->cur().normalizer_glyph_index() = glyph; (void) buffer->next_glyph (); } @@ -210,7 +210,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, hb_font_t * const font = c->font; for (; buffer->idx < end - 1 && buffer->successful;) { if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { - if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) + if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().normalizer_glyph_index())) { hb_codepoint_t unicode = buffer->cur().codepoint; (void) buffer->replace_glyphs (2, 1, &unicode); @@ -342,7 +342,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, unsigned int done = font->get_nominal_glyphs (end - buffer->idx, &buffer->cur().codepoint, sizeof (buffer->info[0]), - &buffer->cur().glyph_index(), + &buffer->cur().normalizer_glyph_index(), sizeof (buffer->info[0])); if (unlikely (!buffer->next_glyphs (done))) break; } @@ -456,7 +456,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer->out_len--; /* Remove the second composable. */ /* Modify starter and carry on. */ buffer->out_info[starter].codepoint = composed; - buffer->out_info[starter].glyph_index() = glyph; + buffer->out_info[starter].normalizer_glyph_index() = glyph; _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer); continue; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh index f12cb35c0fe..2f282f34754 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape-normalize.hh @@ -32,7 +32,7 @@ /* buffer var allocations, used during the normalization process */ -#define glyph_index() var1.u32 +#define normalizer_glyph_index() var1.u32 struct hb_ot_shape_plan_t; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc index 6ee0e2b7f9d..dd2c576fd04 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc @@ -614,14 +614,14 @@ hb_ensure_native_direction (hb_buffer_t *buffer) for (unsigned i = 0; i < count; i++) { auto gc = _hb_glyph_info_get_general_category (&info[i]); - if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) - found_number = true; - else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc)) + if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc)) { found_letter = true; break; } - else if (_hb_codepoint_is_regional_indicator (info[i].codepoint)) + else if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) + found_number = true; + else if (unlikely (_hb_codepoint_is_regional_indicator (info[i].codepoint))) found_ri = true; } if ((found_number || found_ri) && !found_letter) @@ -843,11 +843,11 @@ hb_ot_hide_default_ignorables (hb_buffer_t *buffer, static inline void hb_ot_map_glyphs_fast (hb_buffer_t *buffer) { - /* Normalization process sets up glyph_index(), we just copy it. */ + /* Normalization process sets up normalizer_glyph_index(), we just copy it. */ unsigned int count = buffer->len; hb_glyph_info_t *info = buffer->info; for (unsigned int i = 0; i < count; i++) - info[i].codepoint = info[i].glyph_index(); + info[i].codepoint = info[i].normalizer_glyph_index(); buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; } @@ -885,7 +885,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c) hb_ot_rotate_chars (c); - HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); + HB_BUFFER_ALLOCATE_VAR (buffer, normalizer_glyph_index); _hb_ot_shape_normalize (c->plan, buffer, c->font); @@ -897,7 +897,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c) hb_ot_map_glyphs_fast (buffer); - HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index); + HB_BUFFER_DEALLOCATE_VAR (buffer, normalizer_glyph_index); } static inline void diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh index 6ff65c30a33..92fb64ad07e 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-indic-machine.hh @@ -53,7 +53,7 @@ enum indic_syllable_type_t { }; -#line 57 "hb-ot-shaper-indic-machine.hh" +#line 54 "hb-ot-shaper-indic-machine.hh" #define indic_syllable_machine_ex_A 9u #define indic_syllable_machine_ex_C 1u #define indic_syllable_machine_ex_CM 16u @@ -77,7 +77,7 @@ enum indic_syllable_type_t { #define indic_syllable_machine_ex_ZWNJ 5u -#line 81 "hb-ot-shaper-indic-machine.hh" +#line 76 "hb-ot-shaper-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { 8u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 8u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 4u, 57u, @@ -1126,7 +1126,7 @@ find_syllables_indic (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 1130 "hb-ot-shaper-indic-machine.hh" +#line 1119 "hb-ot-shaper-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -1142,7 +1142,7 @@ find_syllables_indic (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 1146 "hb-ot-shaper-indic-machine.hh" +#line 1131 "hb-ot-shaper-indic-machine.hh" { int _slen; int _trans; @@ -1156,7 +1156,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 1160 "hb-ot-shaper-indic-machine.hh" +#line 1143 "hb-ot-shaper-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -1268,7 +1268,7 @@ _eof_trans: #line 117 "hb-ot-shaper-indic-machine.rl" {act = 7;} break; -#line 1272 "hb-ot-shaper-indic-machine.hh" +#line 1232 "hb-ot-shaper-indic-machine.hh" } _again: @@ -1277,7 +1277,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1281 "hb-ot-shaper-indic-machine.hh" +#line 1239 "hb-ot-shaper-indic-machine.hh" } if ( ++p != pe ) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh index f1e7a91f050..848ed231f71 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-khmer-machine.hh @@ -48,7 +48,7 @@ enum khmer_syllable_type_t { }; -#line 52 "hb-ot-shaper-khmer-machine.hh" +#line 49 "hb-ot-shaper-khmer-machine.hh" #define khmer_syllable_machine_ex_C 1u #define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u #define khmer_syllable_machine_ex_H 4u @@ -66,7 +66,7 @@ enum khmer_syllable_type_t { #define khmer_syllable_machine_ex_ZWNJ 5u -#line 70 "hb-ot-shaper-khmer-machine.hh" +#line 65 "hb-ot-shaper-khmer-machine.hh" static const unsigned char _khmer_syllable_machine_trans_keys[] = { 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, @@ -294,7 +294,7 @@ find_syllables_khmer (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 298 "hb-ot-shaper-khmer-machine.hh" +#line 287 "hb-ot-shaper-khmer-machine.hh" { cs = khmer_syllable_machine_start; ts = 0; @@ -310,7 +310,7 @@ find_syllables_khmer (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 314 "hb-ot-shaper-khmer-machine.hh" +#line 299 "hb-ot-shaper-khmer-machine.hh" { int _slen; int _trans; @@ -324,7 +324,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 328 "hb-ot-shaper-khmer-machine.hh" +#line 311 "hb-ot-shaper-khmer-machine.hh" } _keys = _khmer_syllable_machine_trans_keys + (cs<<1); @@ -394,7 +394,7 @@ _eof_trans: #line 98 "hb-ot-shaper-khmer-machine.rl" {act = 3;} break; -#line 398 "hb-ot-shaper-khmer-machine.hh" +#line 368 "hb-ot-shaper-khmer-machine.hh" } _again: @@ -403,7 +403,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 407 "hb-ot-shaper-khmer-machine.hh" +#line 375 "hb-ot-shaper-khmer-machine.hh" } if ( ++p != pe ) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh index 4b8da586d37..292bc9f3dfc 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-myanmar-machine.hh @@ -50,7 +50,7 @@ enum myanmar_syllable_type_t { }; -#line 54 "hb-ot-shaper-myanmar-machine.hh" +#line 51 "hb-ot-shaper-myanmar-machine.hh" #define myanmar_syllable_machine_ex_A 9u #define myanmar_syllable_machine_ex_As 32u #define myanmar_syllable_machine_ex_C 1u @@ -78,7 +78,7 @@ enum myanmar_syllable_type_t { #define myanmar_syllable_machine_ex_ZWNJ 5u -#line 82 "hb-ot-shaper-myanmar-machine.hh" +#line 77 "hb-ot-shaper-myanmar-machine.hh" static const unsigned char _myanmar_syllable_machine_trans_keys[] = { 1u, 57u, 3u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 5u, 57u, 1u, 15u, 3u, 57u, 3u, 57u, 3u, 57u, @@ -549,7 +549,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 553 "hb-ot-shaper-myanmar-machine.hh" +#line 542 "hb-ot-shaper-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -565,7 +565,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 569 "hb-ot-shaper-myanmar-machine.hh" +#line 554 "hb-ot-shaper-myanmar-machine.hh" { int _slen; int _trans; @@ -579,7 +579,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 583 "hb-ot-shaper-myanmar-machine.hh" +#line 566 "hb-ot-shaper-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -649,7 +649,7 @@ _eof_trans: #line 113 "hb-ot-shaper-myanmar-machine.rl" {act = 3;} break; -#line 653 "hb-ot-shaper-myanmar-machine.hh" +#line 623 "hb-ot-shaper-myanmar-machine.hh" } _again: @@ -658,7 +658,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 662 "hb-ot-shaper-myanmar-machine.hh" +#line 630 "hb-ot-shaper-myanmar-machine.hh" } if ( ++p != pe ) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-thai.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-thai.cc index 6d293b5c489..90ef8e39b74 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-thai.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-thai.cc @@ -191,7 +191,7 @@ static const struct thai_above_state_machine_edge_t { }; -static enum thai_below_state_t +static const enum thai_below_state_t { B0, /* No descender */ B1, /* Removable descender */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh index 65b6adc36d9..5072e4d38ee 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-shaper-use-machine.hh @@ -53,7 +53,7 @@ enum use_syllable_type_t { }; -#line 57 "hb-ot-shaper-use-machine.hh" +#line 54 "hb-ot-shaper-use-machine.hh" #define use_syllable_machine_ex_B 1u #define use_syllable_machine_ex_CGJ 6u #define use_syllable_machine_ex_CMAbv 31u @@ -100,7 +100,7 @@ enum use_syllable_type_t { #define use_syllable_machine_ex_ZWNJ 14u -#line 104 "hb-ot-shaper-use-machine.hh" +#line 99 "hb-ot-shaper-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { 49u, 51u, 0u, 56u, 11u, 56u, 11u, 56u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, @@ -929,7 +929,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int act HB_UNUSED; int cs; -#line 933 "hb-ot-shaper-use-machine.hh" +#line 922 "hb-ot-shaper-use-machine.hh" { cs = use_syllable_machine_start; ts = 0; @@ -942,7 +942,7 @@ find_syllables_use (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 946 "hb-ot-shaper-use-machine.hh" +#line 931 "hb-ot-shaper-use-machine.hh" { int _slen; int _trans; @@ -956,7 +956,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 960 "hb-ot-shaper-use-machine.hh" +#line 943 "hb-ot-shaper-use-machine.hh" } _keys = _use_syllable_machine_trans_keys + (cs<<1); @@ -1078,7 +1078,7 @@ _eof_trans: #line 181 "hb-ot-shaper-use-machine.rl" {act = 9;} break; -#line 1082 "hb-ot-shaper-use-machine.hh" +#line 1039 "hb-ot-shaper-use-machine.hh" } _again: @@ -1087,7 +1087,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 1091 "hb-ot-shaper-use-machine.hh" +#line 1046 "hb-ot-shaper-use-machine.hh" } if ( ++p != pe ) diff --git a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh index c6dbf8db91c..cfc40924506 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-serialize.hh @@ -724,7 +724,7 @@ struct hb_serialize_context_t hb_requires (hb_is_iterator (Iterator)), typename ...Ts> void copy_all (Iterator it, Ts&&... ds) - { for (decltype (*it) _ : it) copy (_, std::forward<Ts> (ds)...); } + { for (decltype (*it) _ : it) copy (_, ds...); } template <typename Type> hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc index c62f8c6bcdd..db46e110ca5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shape.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-shape.cc @@ -199,6 +199,7 @@ hb_shape (hb_font_t *font, #ifdef HB_EXPERIMENTAL_API +#ifndef HB_NO_VAR static float buffer_advance (hb_buffer_t *buffer) @@ -440,7 +441,7 @@ hb_shape_justify (hb_font_t *font, return true; } - +#endif #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh b/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh index 41673a38441..cb386f26827 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-shaper-list.hh @@ -61,6 +61,10 @@ HB_SHAPER_IMPLEMENT (coretext) HB_SHAPER_IMPLEMENT (harfrust) #endif +#ifdef HAVE_KBTS +HB_SHAPER_IMPLEMENT (kbts) +#endif + #ifndef HB_NO_FALLBACK_SHAPE HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */ #endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-string-array.hh b/src/3rdparty/harfbuzz-ng/src/hb-string-array.hh index e7ac1192324..3a714889c20 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-string-array.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-string-array.hh @@ -45,25 +45,25 @@ static const union HB_STRING_ARRAY_TYPE_NAME { * but C++ does not allow that. * https://stackoverflow.com/q/28433862 */ -#define _S(s) char HB_PASTE (str, __LINE__)[sizeof (s)]; +#define HB_STR(s) char HB_PASTE (str, __LINE__)[sizeof (s)]; #include HB_STRING_ARRAY_LIST -#undef _S +#undef HB_STR } st; char str[HB_VAR_ARRAY]; } HB_STRING_ARRAY_POOL_NAME = { { -#define _S(s) s, +#define HB_STR(s) s, #include HB_STRING_ARRAY_LIST -#undef _S +#undef HB_STR } }; static const unsigned int HB_STRING_ARRAY_OFFS_NAME[] = { -#define _S(s) offsetof (union HB_STRING_ARRAY_TYPE_NAME, st.HB_PASTE(str, __LINE__)), +#define HB_STR(s) offsetof (union HB_STRING_ARRAY_TYPE_NAME, st.HB_PASTE(str, __LINE__)), #include HB_STRING_ARRAY_LIST -#undef _S +#undef HB_STR sizeof (HB_STRING_ARRAY_TYPE_NAME) }; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh index 335b750da35..30e8e639b90 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh @@ -300,6 +300,7 @@ struct hb_subset_plan_t // compile times more reasonable: // - hb-subset-plan.cc // - hb-subset-plan-layout.cc +// - hb-subset-plan-var.cc // // The functions below are those needed to connect the split files // above together. diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-table-cff.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-cff.cc new file mode 100644 index 00000000000..3984cfb8660 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-cff.cc @@ -0,0 +1,143 @@ +#include "hb-subset-table.hh" + +#include "hb-ot-cff1-table.hh" +#include "hb-ot-cff2-table.hh" +#include "hb-ot-vorg-table.hh" + + +#ifndef HB_NO_SUBSET_CFF +template<> +struct hb_subset_plan_t::source_table_loader<const OT::cff1> +{ + auto operator () (hb_subset_plan_t *plan) + HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff1_accel : + plan->inprogress_accelerator ? plan->inprogress_accelerator->cff1_accel : + plan->cff1_accel) +}; +template<> +struct hb_subset_plan_t::source_table_loader<const OT::cff2> +{ + auto operator () (hb_subset_plan_t *plan) + HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff2_accel : + plan->inprogress_accelerator ? plan->inprogress_accelerator->cff2_accel : + plan->cff2_accel) +}; +#endif + + +bool _hb_subset_table_cff (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success) +{ +#ifndef HB_NO_SUBSET_CFF + switch (tag) + { + case HB_TAG('C','F','F',' '): *success = _hb_subset_table<const OT::cff1> (plan, buf); return true; + case HB_TAG('C','F','F','2'): *success = _hb_subset_table<const OT::cff2> (plan, buf); return true; + case HB_TAG('V','O','R','G'): *success = _hb_subset_table<const OT::VORG> (plan, buf); return true; + } +#endif + return false; +} + + +#ifdef HB_EXPERIMENTAL_API +#ifndef HB_NO_CFF + +template<typename accel_t> +static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_index) { + if (!accel.is_valid()) { + return hb_blob_get_empty (); + } + + hb_ubytes_t bytes = (*accel.charStrings)[glyph_index]; + if (!bytes) { + return hb_blob_get_empty (); + } + + hb_blob_t* cff_blob = accel.get_blob(); + uint32_t length; + const char* cff_data = hb_blob_get_data(cff_blob, &length) ; + + long int offset = (const char*) bytes.arrayZ - cff_data; + if (offset < 0 || offset > INT32_MAX) { + return hb_blob_get_empty (); + } + + return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length); +} + +template<typename accel_t> +static hb_blob_t* get_charstrings_index(accel_t& accel) { + if (!accel.is_valid()) { + return hb_blob_get_empty (); + } + + const char* charstrings_start = (const char*) accel.charStrings; + unsigned charstrings_length = accel.charStrings->get_size(); + + hb_blob_t* cff_blob = accel.get_blob(); + uint32_t length; + const char* cff_data = hb_blob_get_data(cff_blob, &length) ; + + long int offset = charstrings_start - cff_data; + if (offset < 0 || offset > INT32_MAX) { + return hb_blob_get_empty (); + } + + return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length); +} + +/** + * hb_subset_cff_get_charstring_data: + * @face: A face object + * @glyph_index: Glyph index to get data for. + * + * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { + return get_charstrings_data(*face->table.cff1, glyph_index); +} + +/** + * hb_subset_cff_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF CharStrings INDEX from the CFF table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff1); +} + +/** + * hb_subset_cff2_get_charstring_data: + * @face: A face object + * @glyph_index: Glyph index to get data for. + * + * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { + return get_charstrings_data(*face->table.cff2, glyph_index); +} + +/** + * hb_subset_cff2_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF2 CharStrings INDEX from the CFF2 table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff2); +} +#endif +#endif diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-table-color.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-color.cc new file mode 100644 index 00000000000..e44305e7dd7 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-color.cc @@ -0,0 +1,21 @@ +#include "hb-subset-table.hh" + +#include "OT/Color/sbix/sbix.hh" +#include "OT/Color/CPAL/CPAL.hh" +#include "OT/Color/COLR/COLR.hh" +#include "OT/Color/CBDT/CBDT.hh" + +bool _hb_subset_table_color (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success) +{ +#ifndef HB_NO_COLOR + switch (tag) + { + case HB_TAG('s','b','i','x'): *success = _hb_subset_table<const OT::sbix> (plan, buf); return true; + case HB_TAG('C','O','L','R'): *success = _hb_subset_table<const OT::COLR> (plan, buf); return true; + case HB_TAG('C','P','A','L'): *success = _hb_subset_table<const OT::CPAL> (plan, buf); return true; + case HB_TAG('C','B','L','C'): *success = _hb_subset_table<const OT::CBLC> (plan, buf); return true; + case HB_TAG('C','B','D','T'): *success = true; return true; /* skip CBDT, handled by CBLC */ + } +#endif + return false; +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-table-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-layout.cc new file mode 100644 index 00000000000..765422e365b --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-layout.cc @@ -0,0 +1,22 @@ +#include "hb-subset-table.hh" + +#include "hb-ot-layout-gdef-table.hh" +#include "hb-ot-layout-gsub-table.hh" +#include "hb-ot-layout-gpos-table.hh" +#include "hb-ot-layout-base-table.hh" +#include "hb-ot-math-table.hh" + +bool _hb_subset_table_layout (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success) +{ +#ifndef HB_NO_SUBSET_LAYOUT + switch (tag) + { + case HB_TAG('G','D','E','F'): *success = _hb_subset_table<const OT::GDEF> (plan, buf); return true; + case HB_TAG('G','S','U','B'): *success = _hb_subset_table<const OT::Layout::GSUB> (plan, buf); return true; + case HB_TAG('G','P','O','S'): *success = _hb_subset_table<const OT::Layout::GPOS> (plan, buf); return true; + case HB_TAG('B','A','S','E'): *success = _hb_subset_table<const OT::BASE> (plan, buf); return true; + case HB_TAG('M','A','T','H'): *success = _hb_subset_table<const OT::MATH> (plan, buf); return true; + } +#endif + return false; +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-table-other.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-other.cc new file mode 100644 index 00000000000..3b7ff4b3264 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-other.cc @@ -0,0 +1,31 @@ +#include "hb-subset-table.hh" + +#include "hb-ot-cmap-table.hh" +#include "hb-ot-glyf-table.hh" +#include "hb-ot-hdmx-table.hh" +#include "hb-ot-hhea-table.hh" +#include "hb-ot-hmtx-table.hh" +#include "hb-ot-maxp-table.hh" +#include "hb-ot-os2-table.hh" +#include "hb-ot-name-table.hh" +#include "hb-ot-post-table.hh" + +bool _hb_subset_table_other (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success) +{ + switch (tag) + { + case HB_TAG('g','l','y','f'): *success = _hb_subset_table<const OT::glyf> (plan, buf); return true; + case HB_TAG('h','d','m','x'): *success = _hb_subset_table<const OT::hdmx> (plan, buf); return true; + case HB_TAG('n','a','m','e'): *success = _hb_subset_table<const OT::name> (plan, buf); return true; + case HB_TAG('h','h','e','a'): *success = true; return true; /* skip hhea, handled by hmtx */ + case HB_TAG('h','m','t','x'): *success = _hb_subset_table<const OT::hmtx> (plan, buf); return true; + case HB_TAG('v','h','e','a'): *success = true; return true; /* skip vhea, handled by vmtx */ + case HB_TAG('v','m','t','x'): *success = _hb_subset_table<const OT::vmtx> (plan, buf); return true; + case HB_TAG('m','a','x','p'): *success = _hb_subset_table<const OT::maxp> (plan, buf); return true; + case HB_TAG('l','o','c','a'): *success = true; return true; /* skip loca, handled by glyf */ + case HB_TAG('c','m','a','p'): *success = _hb_subset_table<const OT::cmap> (plan, buf); return true; + case HB_TAG('O','S','/','2'): *success = _hb_subset_table<const OT::OS2 > (plan, buf); return true; + case HB_TAG('p','o','s','t'): *success = _hb_subset_table<const OT::post> (plan, buf); return true; + } + return false; +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-table-var.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-var.cc new file mode 100644 index 00000000000..b569b08a008 --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-table-var.cc @@ -0,0 +1,45 @@ +#include "hb-subset-table.hh" + +#include "hb-ot-var-hvar-table.hh" +#include "hb-ot-var-gvar-table.hh" +#include "hb-ot-var-fvar-table.hh" +#include "hb-ot-var-avar-table.hh" +#include "hb-ot-var-cvar-table.hh" +#include "hb-ot-var-mvar-table.hh" + +bool _hb_subset_table_var (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success) +{ +#ifndef HB_NO_VAR + switch (tag) + { + case HB_TAG('H','V','A','R'): *success = _hb_subset_table<const OT::HVAR> (plan, buf); return true; + case HB_TAG('V','V','A','R'): *success = _hb_subset_table<const OT::VVAR> (plan, buf); return true; + case HB_TAG('g','v','a','r'): *success = _hb_subset_table<const OT::gvar> (plan, buf); return true; + case HB_TAG('f','v','a','r'): + if (plan->user_axes_location.is_empty ()) + *success = _hb_subset_table_passthrough (plan, tag); + else + *success = _hb_subset_table<const OT::fvar> (plan, buf); + return true; + case HB_TAG('a','v','a','r'): + if (plan->user_axes_location.is_empty ()) + *success = _hb_subset_table_passthrough (plan, tag); + else + *success = _hb_subset_table<const OT::avar> (plan, buf); + return true; + case HB_TAG('c','v','a','r'): + if (plan->user_axes_location.is_empty ()) + *success = _hb_subset_table_passthrough (plan, tag); + else + *success = _hb_subset_table<const OT::cvar> (plan, buf); + return true; + case HB_TAG('M','V','A','R'): + if (plan->user_axes_location.is_empty ()) + *success = _hb_subset_table_passthrough (plan, tag); + else + *success = _hb_subset_table<const OT::MVAR> (plan, buf); + return true; + } +#endif + return false; +} diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset-table.hh new file mode 100644 index 00000000000..66588ec6f8f --- /dev/null +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset-table.hh @@ -0,0 +1,217 @@ +/* + * Copyright © 2018 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Garret Rieger, Roderick Sheeter + */ + +#ifndef HB_SUBSET_TABLE_HH +#define HB_SUBSET_TABLE_HH + + +#include "hb.hh" + +#include "hb-subset.hh" +#include "hb-repacker.hh" + + +template<typename TableType> +static bool +_hb_subset_table_try (const TableType *table, + hb_vector_t<char>* buf, + hb_subset_context_t* c /* OUT */) +{ + c->serializer->start_serialize (); + if (c->serializer->in_error ()) return false; + + bool needed = table->subset (c); + if (!c->serializer->ran_out_of_room ()) + { + c->serializer->end_serialize (); + return needed; + } + + unsigned buf_size = buf->allocated; + buf_size = buf_size * 2 + 16; + + + + + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", + HB_UNTAG (c->table_tag), buf_size); + + if (unlikely (buf_size > c->source_blob->length * 256 || + !buf->alloc_exact (buf_size))) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", + HB_UNTAG (c->table_tag), buf_size); + return needed; + } + + c->serializer->reset (buf->arrayZ, buf->allocated); + return _hb_subset_table_try (table, buf, c); +} + +static HB_UNUSED unsigned +_hb_subset_estimate_table_size (hb_subset_plan_t *plan, + unsigned table_len, + hb_tag_t table_tag) +{ + unsigned src_glyphs = plan->source->get_num_glyphs (); + unsigned dst_glyphs = plan->glyphset ()->get_population (); + + unsigned bulk = 8192; + /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's + * because those are expensive to subset, so giving them more room is fine. */ + bool same_size = table_tag == HB_TAG('G','S','U','B') || + table_tag == HB_TAG('G','P','O','S') || + table_tag == HB_TAG('G','D','E','F') || + table_tag == HB_TAG('n','a','m','e'); + + if (plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS) + { + if (table_tag == HB_TAG('C','F','F',' ')) + { + /* Add some extra room for the CFF charset. */ + bulk += src_glyphs * 16; + } + else if (table_tag == HB_TAG('C','F','F','2')) + { + /* Just extra CharString offsets. */ + bulk += src_glyphs * 4; + } + } + + if (unlikely (!src_glyphs) || same_size) + return bulk + table_len; + + return bulk + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs)); +} + +/* + * Repack the serialization buffer if any offset overflows exist. + */ +static HB_UNUSED hb_blob_t* +_hb_subset_repack (hb_tag_t tag, const hb_serialize_context_t& c) +{ + if (!c.offset_overflow ()) + return c.copy_blob (); + + hb_blob_t* result = hb_resolve_overflows (c.object_graph (), tag); + + if (unlikely (!result)) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c offset overflow resolution failed.", + HB_UNTAG (tag)); + return nullptr; + } + + return result; +} + +template <typename T> +static HB_UNUSED auto _hb_do_destroy (T &t, hb_priority<1>) HB_RETURN (void, t.destroy ()) + +template <typename T> +static HB_UNUSED void _hb_do_destroy (T &t, hb_priority<0>) {} + +template<typename TableType> +static bool +_hb_subset_table (hb_subset_plan_t *plan, hb_vector_t<char> &buf) +{ + auto &&source_blob = plan->source_table<TableType> (); + auto *table = source_blob.get (); + + hb_tag_t tag = TableType::tableTag; + hb_blob_t *blob = source_blob.get_blob(); + if (unlikely (!blob || !blob->data)) + { + DEBUG_MSG (SUBSET, nullptr, + "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); + _hb_do_destroy (source_blob, hb_prioritize); + return false; + } + + unsigned buf_size = _hb_subset_estimate_table_size (plan, blob->length, TableType::tableTag); + DEBUG_MSG (SUBSET, nullptr, + "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); + if (unlikely (!buf.alloc (buf_size))) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size); + _hb_do_destroy (source_blob, hb_prioritize); + return false; + } + + bool needed = false; + hb_serialize_context_t serializer (buf.arrayZ, buf.allocated); + { + hb_subset_context_t c (blob, plan, &serializer, tag); + needed = _hb_subset_table_try (table, &buf, &c); + } + _hb_do_destroy (source_blob, hb_prioritize); + + if (serializer.in_error () && !serializer.only_offset_overflow ()) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag)); + return false; + } + + if (!needed) + { + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag)); + return true; + } + + bool result = false; + hb_blob_t *dest_blob = _hb_subset_repack (tag, serializer); + if (dest_blob) + { + DEBUG_MSG (SUBSET, nullptr, + "OT::%c%c%c%c final subset table size: %u bytes.", + HB_UNTAG (tag), dest_blob->length); + result = plan->add_table (tag, dest_blob); + hb_blob_destroy (dest_blob); + } + + DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", + HB_UNTAG (tag), result ? "success" : "FAILED!"); + return result; +} + +static HB_UNUSED bool +_hb_subset_table_passthrough (hb_subset_plan_t *plan, hb_tag_t tag) +{ + hb_blob_t *source_table = hb_face_reference_table (plan->source, tag); + bool result = plan->add_table (tag, source_table); + hb_blob_destroy (source_table); + return result; +} + + +HB_INTERNAL bool _hb_subset_table_layout (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success); +HB_INTERNAL bool _hb_subset_table_var (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success); +HB_INTERNAL bool _hb_subset_table_cff (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success); +HB_INTERNAL bool _hb_subset_table_color (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success); +HB_INTERNAL bool _hb_subset_table_other (hb_subset_plan_t *plan, hb_vector_t<char> &buf, hb_tag_t tag, bool *success); + + +#endif /* HB_SUBSET_TABLE_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc index 7f9dc34ded8..d1ca60e63e5 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.cc @@ -25,65 +25,19 @@ */ #include "hb.hh" + #include "hb-open-type.hh" +#include "hb-open-file.hh" #include "hb-subset.hh" +#include "hb-subset-table.hh" +#include "hb-subset-accelerator.hh" -#include "hb-open-file.hh" #include "hb-ot-cmap-table.hh" -#include "hb-ot-glyf-table.hh" -#include "hb-ot-hdmx-table.hh" -#include "hb-ot-head-table.hh" -#include "hb-ot-hhea-table.hh" -#include "hb-ot-hmtx-table.hh" -#include "hb-ot-maxp-table.hh" -#include "OT/Color/CBDT/CBDT.hh" -#include "OT/Color/COLR/COLR.hh" -#include "OT/Color/CPAL/CPAL.hh" -#include "OT/Color/sbix/sbix.hh" -#include "hb-ot-os2-table.hh" -#include "hb-ot-post-table.hh" -#include "hb-ot-post-table-v2subset.hh" -#include "hb-ot-cff1-table.hh" -#include "hb-ot-cff2-table.hh" -#include "hb-ot-vorg-table.hh" -#include "hb-ot-name-table.hh" -#include "hb-ot-layout-base-table.hh" -#include "hb-ot-layout-gsub-table.hh" -#include "hb-ot-layout-gpos-table.hh" -#include "hb-ot-var-avar-table.hh" #include "hb-ot-var-cvar-table.hh" -#include "hb-ot-var-fvar-table.hh" -#include "hb-ot-var-gvar-table.hh" -#include "hb-ot-var-hvar-table.hh" -#include "hb-ot-var-mvar-table.hh" -#include "hb-ot-math-table.hh" +#include "hb-ot-head-table.hh" #include "hb-ot-stat-table.hh" -#include "hb-repacker.hh" -#include "hb-subset-accelerator.hh" - -using OT::Layout::GSUB; -using OT::Layout::GPOS; - - -#ifndef HB_NO_SUBSET_CFF -template<> -struct hb_subset_plan_t::source_table_loader<const OT::cff1> -{ - auto operator () (hb_subset_plan_t *plan) - HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff1_accel : - plan->inprogress_accelerator ? plan->inprogress_accelerator->cff1_accel : - plan->cff1_accel) -}; -template<> -struct hb_subset_plan_t::source_table_loader<const OT::cff2> -{ - auto operator () (hb_subset_plan_t *plan) - HB_AUTO_RETURN (plan->accelerator ? plan->accelerator->cff2_accel : - plan->inprogress_accelerator ? plan->inprogress_accelerator->cff2_accel : - plan->cff2_accel) -}; -#endif +#include "hb-ot-post-table-v2subset.hh" /** @@ -116,56 +70,56 @@ hb_user_data_key_t _hb_subset_accelerator_user_data_key = {}; * if we are unable to list the tables in a face. */ static hb_tag_t known_tables[] { - HB_TAG ('a', 'v', 'a', 'r'), - HB_OT_TAG_BASE, - HB_OT_TAG_CBDT, - HB_OT_TAG_CBLC, - HB_OT_TAG_CFF1, - HB_OT_TAG_CFF2, - HB_OT_TAG_cmap, - HB_OT_TAG_COLR, - HB_OT_TAG_CPAL, - HB_TAG ('c', 'v', 'a', 'r'), - HB_TAG ('c', 'v', 't', ' '), - HB_TAG ('D', 'S', 'I', 'G'), - HB_TAG ('E', 'B', 'D', 'T'), - HB_TAG ('E', 'B', 'L', 'C'), - HB_TAG ('E', 'B', 'S', 'C'), - HB_TAG ('f', 'p', 'g', 'm'), - HB_TAG ('f', 'v', 'a', 'r'), - HB_TAG ('g', 'a', 's', 'p'), - HB_OT_TAG_GDEF, - HB_OT_TAG_glyf, - HB_OT_TAG_GPOS, - HB_OT_TAG_GSUB, - HB_OT_TAG_gvar, - HB_OT_TAG_hdmx, - HB_OT_TAG_head, - HB_OT_TAG_hhea, - HB_OT_TAG_hmtx, - HB_OT_TAG_HVAR, - HB_OT_TAG_JSTF, - HB_TAG ('k', 'e', 'r', 'n'), - HB_OT_TAG_loca, - HB_TAG ('L', 'T', 'S', 'H'), - HB_OT_TAG_MATH, - HB_OT_TAG_maxp, - HB_TAG ('M', 'E', 'R', 'G'), - HB_TAG ('m', 'e', 't', 'a'), - HB_TAG ('M', 'V', 'A', 'R'), - HB_TAG ('P', 'C', 'L', 'T'), - HB_OT_TAG_post, - HB_TAG ('p', 'r', 'e', 'p'), - HB_OT_TAG_sbix, - HB_TAG ('S', 'T', 'A', 'T'), - HB_TAG ('S', 'V', 'G', ' '), - HB_TAG ('V', 'D', 'M', 'X'), - HB_OT_TAG_vhea, - HB_OT_TAG_vmtx, - HB_OT_TAG_VORG, - HB_OT_TAG_VVAR, - HB_OT_TAG_name, - HB_OT_TAG_OS2 + HB_TAG('a','v','a','r'), + HB_TAG('B','A','S','E'), + HB_TAG('C','B','D','T'), + HB_TAG('C','B','L','C'), + HB_TAG('C','F','F',' '), + HB_TAG('C','F','F','2'), + HB_TAG('c','m','a','p'), + HB_TAG('C','O','L','R'), + HB_TAG('C','P','A','L'), + HB_TAG('c','v','a','r'), + HB_TAG('c','v','t',' '), + HB_TAG('D','S','I','G'), + HB_TAG('E','B','D','T'), + HB_TAG('E','B','L','C'), + HB_TAG('E','B','S','C'), + HB_TAG('f','p','g','m'), + HB_TAG('f','v','a','r'), + HB_TAG('g','a','s','p'), + HB_TAG('G','D','E','F'), + HB_TAG('g','l','y','f'), + HB_TAG('G','P','O','S'), + HB_TAG('G','S','U','B'), + HB_TAG('g','v','a','r'), + HB_TAG('h','d','m','x'), + HB_TAG('h','e','a','d'), + HB_TAG('h','h','e','a'), + HB_TAG('h','m','t','x'), + HB_TAG('H','V','A','R'), + HB_TAG('J','S','T','F'), + HB_TAG('k','e','r','n'), + HB_TAG('l','o','c','a'), + HB_TAG('L','T','S','H'), + HB_TAG('M','A','T','H'), + HB_TAG('m','a','x','p'), + HB_TAG('M','E','R','G'), + HB_TAG('m','e','t','a'), + HB_TAG('M','V','A','R'), + HB_TAG('P','C','L','T'), + HB_TAG('p','o','s','t'), + HB_TAG('p','r','e','p'), + HB_TAG('s','b','i','x'), + HB_TAG('S','T','A','T'), + HB_TAG('S','V','G',' '), + HB_TAG('V','D','M','X'), + HB_TAG('v','h','e','a'), + HB_TAG('v','m','t','x'), + HB_TAG('V','O','R','G'), + HB_TAG('V','V','A','R'), + HB_TAG('n','a','m','e'), + HB_TAG('O','S','/','2') }; static bool _table_is_empty (const hb_face_t *face, hb_tag_t tag) @@ -213,169 +167,6 @@ _get_table_tags (const hb_subset_plan_t* plan, } -static unsigned -_plan_estimate_subset_table_size (hb_subset_plan_t *plan, - unsigned table_len, - hb_tag_t table_tag) -{ - unsigned src_glyphs = plan->source->get_num_glyphs (); - unsigned dst_glyphs = plan->glyphset ()->get_population (); - - unsigned bulk = 8192; - /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's - * because those are expensive to subset, so giving them more room is fine. */ - bool same_size = table_tag == HB_OT_TAG_GSUB || - table_tag == HB_OT_TAG_GPOS || - table_tag == HB_OT_TAG_name; - - if (plan->flags & HB_SUBSET_FLAGS_RETAIN_GIDS) - { - if (table_tag == HB_OT_TAG_CFF1) - { - /* Add some extra room for the CFF charset. */ - bulk += src_glyphs * 16; - } - else if (table_tag == HB_OT_TAG_CFF2) - { - /* Just extra CharString offsets. */ - bulk += src_glyphs * 4; - } - } - - if (unlikely (!src_glyphs) || same_size) - return bulk + table_len; - - return bulk + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs)); -} - -/* - * Repack the serialization buffer if any offset overflows exist. - */ -static hb_blob_t* -_repack (hb_tag_t tag, const hb_serialize_context_t& c) -{ - if (!c.offset_overflow ()) - return c.copy_blob (); - - hb_blob_t* result = hb_resolve_overflows (c.object_graph (), tag); - - if (unlikely (!result)) - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c offset overflow resolution failed.", - HB_UNTAG (tag)); - return nullptr; - } - - return result; -} - -template<typename TableType> -static -bool -_try_subset (const TableType *table, - hb_vector_t<char>* buf, - hb_subset_context_t* c /* OUT */) -{ - c->serializer->start_serialize (); - if (c->serializer->in_error ()) return false; - - bool needed = table->subset (c); - if (!c->serializer->ran_out_of_room ()) - { - c->serializer->end_serialize (); - return needed; - } - - unsigned buf_size = buf->allocated; - buf_size = buf_size * 2 + 16; - - - - - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", - HB_UNTAG (c->table_tag), buf_size); - - if (unlikely (buf_size > c->source_blob->length * 256 || - !buf->alloc_exact (buf_size))) - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", - HB_UNTAG (c->table_tag), buf_size); - return needed; - } - - c->serializer->reset (buf->arrayZ, buf->allocated); - return _try_subset (table, buf, c); -} - -template <typename T> -static auto _do_destroy (T &t, hb_priority<1>) HB_RETURN (void, t.destroy ()) - -template <typename T> -static void _do_destroy (T &t, hb_priority<0>) {} - -template<typename TableType> -static bool -_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf) -{ - auto &&source_blob = plan->source_table<TableType> (); - auto *table = source_blob.get (); - - hb_tag_t tag = TableType::tableTag; - hb_blob_t *blob = source_blob.get_blob(); - if (unlikely (!blob || !blob->data)) - { - DEBUG_MSG (SUBSET, nullptr, - "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); - _do_destroy (source_blob, hb_prioritize); - return false; - } - - unsigned buf_size = _plan_estimate_subset_table_size (plan, blob->length, TableType::tableTag); - DEBUG_MSG (SUBSET, nullptr, - "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); - if (unlikely (!buf.alloc (buf_size))) - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size); - _do_destroy (source_blob, hb_prioritize); - return false; - } - - bool needed = false; - hb_serialize_context_t serializer (buf.arrayZ, buf.allocated); - { - hb_subset_context_t c (blob, plan, &serializer, tag); - needed = _try_subset (table, &buf, &c); - } - _do_destroy (source_blob, hb_prioritize); - - if (serializer.in_error () && !serializer.only_offset_overflow ()) - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset FAILED!", HB_UNTAG (tag)); - return false; - } - - if (!needed) - { - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag)); - return true; - } - - bool result = false; - hb_blob_t *dest_blob = _repack (tag, serializer); - if (dest_blob) - { - DEBUG_MSG (SUBSET, nullptr, - "OT::%c%c%c%c final subset table size: %u bytes.", - HB_UNTAG (tag), dest_blob->length); - result = plan->add_table (tag, dest_blob); - hb_blob_destroy (dest_blob); - } - - DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", - HB_UNTAG (tag), result ? "success" : "FAILED!"); - return result; -} - static bool _is_table_present (hb_face_t *source, hb_tag_t tag) { @@ -407,34 +198,34 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag) switch (tag) { - case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */ + case HB_TAG('c','v','a','r'): /* hint table, fallthrough */ return plan->all_axes_pinned || (plan->flags & HB_SUBSET_FLAGS_NO_HINTING); - case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */ - case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */ - case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */ - case HB_TAG ('h','d','m','x'): /* hint table, fallthrough */ - case HB_TAG ('V','D','M','X'): /* hint table, fallthrough */ + case HB_TAG('c','v','t',' '): /* hint table, fallthrough */ + case HB_TAG('f','p','g','m'): /* hint table, fallthrough */ + case HB_TAG('p','r','e','p'): /* hint table, fallthrough */ + case HB_TAG('h','d','m','x'): /* hint table, fallthrough */ + case HB_TAG('V','D','M','X'): /* hint table, fallthrough */ return plan->flags & HB_SUBSET_FLAGS_NO_HINTING; #ifdef HB_NO_SUBSET_LAYOUT // Drop Layout Tables if requested. - case HB_OT_TAG_GDEF: - case HB_OT_TAG_GPOS: - case HB_OT_TAG_GSUB: - case HB_TAG ('m','o','r','x'): - case HB_TAG ('m','o','r','t'): - case HB_TAG ('k','e','r','x'): - case HB_TAG ('k','e','r','n'): + case HB_TAG('G','D','E','F'): + case HB_TAG('G','P','O','S'): + case HB_TAG('G','S','U','B'): + case HB_TAG('m','o','r','x'): + case HB_TAG('m','o','r','t'): + case HB_TAG('k','e','r','x'): + case HB_TAG('k','e','r','n'): return true; #endif - case HB_TAG ('a','v','a','r'): - case HB_TAG ('f','v','a','r'): - case HB_TAG ('g','v','a','r'): - case HB_OT_TAG_HVAR: - case HB_OT_TAG_VVAR: - case HB_TAG ('M','V','A','R'): + case HB_TAG('a','v','a','r'): + case HB_TAG('f','v','a','r'): + case HB_TAG('g','v','a','r'): + case HB_TAG('H','V','A','R'): + case HB_TAG('V','V','A','R'): + case HB_TAG('M','V','A','R'): return plan->all_axes_pinned; default: @@ -443,28 +234,19 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag) } static bool -_passthrough (hb_subset_plan_t *plan, hb_tag_t tag) -{ - hb_blob_t *source_table = hb_face_reference_table (plan->source, tag); - bool result = plan->add_table (tag, source_table); - hb_blob_destroy (source_table); - return result; -} - -static bool _dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag, const hb_set_t &subsetted_tags, const hb_set_t &pending_subset_tags) { switch (tag) { - case HB_OT_TAG_hmtx: - case HB_OT_TAG_vmtx: - case HB_OT_TAG_maxp: - case HB_OT_TAG_OS2: - return !plan->normalized_coords || !pending_subset_tags.has (HB_OT_TAG_glyf); - case HB_OT_TAG_GPOS: - return plan->all_axes_pinned || !pending_subset_tags.has (HB_OT_TAG_GDEF); + case HB_TAG('h','m','t','x'): + case HB_TAG('v','m','t','x'): + case HB_TAG('m','a','x','p'): + case HB_TAG('O','S','/','2'): + return !plan->normalized_coords || !pending_subset_tags.has (HB_TAG('g','l','y','f')); + case HB_TAG('G','P','O','S'): + return plan->all_axes_pinned || !pending_subset_tags.has (HB_TAG('G','D','E','F')); default: return true; } @@ -476,88 +258,48 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag) { if (plan->no_subset_tables.has (tag)) { - return _passthrough (plan, tag); + return _hb_subset_table_passthrough (plan, tag); } DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag)); + + bool success; + if (_hb_subset_table_layout (plan, buf, tag, &success) || + _hb_subset_table_var (plan, buf, tag, &success) || + _hb_subset_table_cff (plan, buf, tag, &success) || + _hb_subset_table_color (plan, buf, tag, &success) || + _hb_subset_table_other (plan, buf, tag, &success)) + return success; + + switch (tag) { - case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan, buf); - case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan, buf); - case HB_OT_TAG_name: return _subset<const OT::name> (plan, buf); - case HB_OT_TAG_head: - if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf)) + case HB_TAG('h','e','a','d'): + if (_is_table_present (plan->source, HB_TAG('g','l','y','f')) && !_should_drop_table (plan, HB_TAG('g','l','y','f'))) return true; /* skip head, handled by glyf */ - return _subset<const OT::head> (plan, buf); - case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */ - case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan, buf); - case HB_OT_TAG_vhea: return true; /* skip vhea, handled by vmtx */ - case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan, buf); - case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan, buf); - case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan, buf); - case HB_OT_TAG_loca: return true; /* skip loca, handled by glyf */ - case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan, buf); - case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan, buf); - case HB_OT_TAG_post: return _subset<const OT::post> (plan, buf); - case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan, buf); - case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan, buf); - case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan, buf); - case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */ - case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan, buf); - case HB_OT_TAG_BASE: return _subset<const OT::BASE> (plan, buf); - -#ifndef HB_NO_SUBSET_CFF - case HB_OT_TAG_CFF1: return _subset<const OT::cff1> (plan, buf); - case HB_OT_TAG_CFF2: return _subset<const OT::cff2> (plan, buf); - case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan, buf); -#endif + return _hb_subset_table<const OT::head> (plan, buf); -#ifndef HB_NO_SUBSET_LAYOUT - case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan, buf); - case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan, buf); - case HB_OT_TAG_GPOS: return _subset<const GPOS> (plan, buf); - case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan, buf); - case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf); - case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf); -#endif + case HB_TAG('S','T','A','T'): + if (!plan->user_axes_location.is_empty ()) return _hb_subset_table<const OT::STAT> (plan, buf); + else return _hb_subset_table_passthrough (plan, tag); + case HB_TAG('c','v','t',' '): #ifndef HB_NO_VAR - case HB_OT_TAG_fvar: - if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag); - return _subset<const OT::fvar> (plan, buf); - case HB_OT_TAG_avar: - if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag); - return _subset<const OT::avar> (plan, buf); - case HB_OT_TAG_cvar: - if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag); - return _subset<const OT::cvar> (plan, buf); - case HB_OT_TAG_MVAR: - if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag); - return _subset<const OT::MVAR> (plan, buf); -#endif - - case HB_OT_TAG_STAT: - if (!plan->user_axes_location.is_empty ()) return _subset<const OT::STAT> (plan, buf); - else return _passthrough (plan, tag); - - case HB_TAG ('c', 'v', 't', ' '): -#ifndef HB_NO_VAR - if (_is_table_present (plan->source, HB_OT_TAG_cvar) && + if (_is_table_present (plan->source, HB_TAG('c','v','a','r')) && plan->normalized_coords && !plan->pinned_at_default) { auto &cvar = *plan->source->table.cvar; return OT::cvar::add_cvt_and_apply_deltas (plan, cvar.get_tuple_var_data (), &cvar); } #endif - return _passthrough (plan, tag); + return _hb_subset_table_passthrough (plan, tag); + } - default: - if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED) - return _passthrough (plan, tag); + if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED) + return _hb_subset_table_passthrough (plan, tag); - // Drop table - return true; - } + // Drop table + return true; } static void _attach_accelerator_data (hb_subset_plan_t* plan, @@ -707,108 +449,4 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan) end: return success ? hb_face_reference (plan->dest) : nullptr; -} - - -#ifdef HB_EXPERIMENTAL_API - -#include "hb-ot-cff1-table.hh" - -template<typename accel_t> -static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_index) { - if (!accel.is_valid()) { - return hb_blob_get_empty (); - } - - hb_ubytes_t bytes = (*accel.charStrings)[glyph_index]; - if (!bytes) { - return hb_blob_get_empty (); - } - - hb_blob_t* cff_blob = accel.get_blob(); - uint32_t length; - const char* cff_data = hb_blob_get_data(cff_blob, &length) ; - - long int offset = (const char*) bytes.arrayZ - cff_data; - if (offset < 0 || offset > INT32_MAX) { - return hb_blob_get_empty (); - } - - return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length); -} - -template<typename accel_t> -static hb_blob_t* get_charstrings_index(accel_t& accel) { - if (!accel.is_valid()) { - return hb_blob_get_empty (); - } - - const char* charstrings_start = (const char*) accel.charStrings; - unsigned charstrings_length = accel.charStrings->get_size(); - - hb_blob_t* cff_blob = accel.get_blob(); - uint32_t length; - const char* cff_data = hb_blob_get_data(cff_blob, &length) ; - - long int offset = charstrings_start - cff_data; - if (offset < 0 || offset > INT32_MAX) { - return hb_blob_get_empty (); - } - - return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length); -} - -/** - * hb_subset_cff_get_charstring_data: - * @face: A face object - * @glyph_index: Glyph index to get data for. - * - * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. - * - * XSince: EXPERIMENTAL - **/ -HB_EXTERN hb_blob_t* -hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { - return get_charstrings_data(*face->table.cff1, glyph_index); -} - -/** - * hb_subset_cff_get_charstrings_index: - * @face: A face object - * - * Returns the raw CFF CharStrings INDEX from the CFF table. - * - * XSince: EXPERIMENTAL - **/ -HB_EXTERN hb_blob_t* -hb_subset_cff_get_charstrings_index (hb_face_t* face) { - return get_charstrings_index (*face->table.cff1); -} - -/** - * hb_subset_cff2_get_charstring_data: - * @face: A face object - * @glyph_index: Glyph index to get data for. - * - * Returns the raw outline data from the CFF/CFF2 table associated with the given glyph index. - * - * XSince: EXPERIMENTAL - **/ -HB_EXTERN hb_blob_t* -hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { - return get_charstrings_data(*face->table.cff2, glyph_index); -} - -/** - * hb_subset_cff2_get_charstrings_index: - * @face: A face object - * - * Returns the raw CFF2 CharStrings INDEX from the CFF2 table. - * - * XSince: EXPERIMENTAL - **/ -HB_EXTERN hb_blob_t* -hb_subset_cff2_get_charstrings_index (hb_face_t* face) { - return get_charstrings_index (*face->table.cff2); -} -#endif
\ No newline at end of file +}
\ No newline at end of file diff --git a/src/3rdparty/harfbuzz-ng/src/hb-subset.hh b/src/3rdparty/harfbuzz-ng/src/hb-subset.hh index 4f192aae406..fca378de173 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-subset.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-subset.hh @@ -70,5 +70,4 @@ struct hb_subset_context_t : table_tag (table_tag_) {} }; - #endif /* HB_SUBSET_HH */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-version.h b/src/3rdparty/harfbuzz-ng/src/hb-version.h index aaf0b01d412..2d2dab45aba 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-version.h +++ b/src/3rdparty/harfbuzz-ng/src/hb-version.h @@ -47,20 +47,20 @@ HB_BEGIN_DECLS * * The minor component of the library version available at compile-time. */ -#define HB_VERSION_MINOR 3 +#define HB_VERSION_MINOR 4 /** * HB_VERSION_MICRO: * * The micro component of the library version available at compile-time. */ -#define HB_VERSION_MICRO 3 +#define HB_VERSION_MICRO 1 /** * HB_VERSION_STRING: * * A string literal containing the library version available at compile-time. */ -#define HB_VERSION_STRING "11.3.3" +#define HB_VERSION_STRING "11.4.1" /** * HB_VERSION_ATLEAST: diff --git a/src/3rdparty/harfbuzz-ng/src/hb.hh b/src/3rdparty/harfbuzz-ng/src/hb.hh index 47b710e6740..ba18e36b9f9 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb.hh @@ -136,6 +136,7 @@ #pragma GCC diagnostic ignored "-Wformat-nonliteral" #pragma GCC diagnostic ignored "-Wformat-zero-length" #pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang #pragma GCC diagnostic ignored "-Wrange-loop-analysis" // https://github.com/harfbuzz/harfbuzz/issues/2834 #pragma GCC diagnostic ignored "-Wstrict-aliasing" @@ -239,6 +240,8 @@ // clang defines it so no need. #ifdef __has_builtin #define hb_has_builtin __has_builtin +#elif defined(_MSC_VER) +#define hb_has_builtin(x) 0 #else #define hb_has_builtin(x) ((defined(__GNUC__) && __GNUC__ >= 5)) #endif @@ -557,4 +560,13 @@ extern "C" void hb_free_impl(void *ptr); #include "hb-vector.hh" // Requires: hb-array hb-null #include "hb-object.hh" // Requires: hb-atomic hb-mutex hb-vector + +/* Our src/test-*.cc use hb_assert(), such that it's not compiled out under NDEBUG. + * https://github.com/harfbuzz/harfbuzz/issues/5418 */ +#define hb_always_assert(x) \ + HB_STMT_START { \ + if (!(x)) { fprintf(stderr, "Assertion failed: %s, at %s:%d\n", #x, __FILE__, __LINE__); abort(); } \ + } HB_STMT_END + + #endif /* HB_HH */ diff --git a/src/corelib/kernel/qpermissions.cpp b/src/corelib/kernel/qpermissions.cpp index c5062860ea1..8c95431d01f 100644 --- a/src/corelib/kernel/qpermissions.cpp +++ b/src/corelib/kernel/qpermissions.cpp @@ -102,7 +102,7 @@ Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg); application, please \l{Information Property List Files} {point the build system to your custom \c Info.plist}. - \sa {Information Property List Files}. + \sa {Information Property List Files} \section3 Android \target android-uses-permission @@ -124,7 +124,7 @@ Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg); The relevant permission names are described in the documentation for each permission type. - \sa {Qt Creator: Editing Manifest Files}. + \sa {Qt Creator: Editing Manifest Files} \section1 Available Permissions diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 4238400b358..1da1704619f 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -1080,7 +1080,7 @@ QString QPropertyBindingError::description() const long as the returned \c QPropertyChangeHandler and the property are kept alive. On each value change, the handler is either called immediately, or deferred, depending on the context. - \sa onValueChanged(), subscribe() + \sa QProperty::onValueChanged(), subscribe() */ /*! diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 3b68ba4b71b..edaf73fbe57 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -3518,7 +3518,6 @@ QXmlStreamWriter::QXmlStreamWriter(QByteArray *array) /*! Constructs a stream writer that writes into \a string. - * */ QXmlStreamWriter::QXmlStreamWriter(QString *string) : d_ptr(new QXmlStreamWriterPrivate(this)) diff --git a/src/corelib/text/qvsnprintf.cpp b/src/corelib/text/qvsnprintf.cpp index 522c56fb800..abe3dd6772d 100644 --- a/src/corelib/text/qvsnprintf.cpp +++ b/src/corelib/text/qvsnprintf.cpp @@ -5,10 +5,10 @@ #include "qplatformdefs.h" #include "qbytearray.h" -#include <QtCore/private/qnumeric_p.h> #include "qstring.h" #include <cerrno> +#include <QtCore/q26numeric.h> #include "string.h" @@ -68,7 +68,7 @@ int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap) const auto realSize = ba.size(); int result; if constexpr (sizeof(int) != sizeof(realSize)) { - result = qt_saturate<int>(realSize); + result = q26::saturate_cast<int>(realSize); if (result != realSize) { errno = EOVERFLOW; return -1; diff --git a/src/network/doc/snippets/code/src_network_kernel_qnetworkinformation_metering.cpp b/src/network/doc/snippets/code/src_network_kernel_qnetworkinformation_metering.cpp new file mode 100644 index 00000000000..edbe0e063d7 --- /dev/null +++ b/src/network/doc/snippets/code/src_network_kernel_qnetworkinformation_metering.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +//![file] +#include <QCoreApplication> +#include <QNetworkInformation> +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#include <QNetworkReply> +#include <QFile> +#include <QDebug> +#include <QTimer> + +//! [0] +void uploadLogFile() +{ +//! [0] + // Hardcoded log file path (can be replaced with config or env variable) + QString logFilePath = QCoreApplication::applicationDirPath() + "/log.txt"; + + QFile *file = new QFile(logFilePath); + if (!file->exists()) { + qWarning() << "Log file does not exist:" << logFilePath; + return; + } + + if (!file->open(QIODevice::ReadOnly)) { + qWarning() << "Could not open log file for reading:" << logFilePath; + return; + } + + QNetworkRequest request(QUrl("http://localhost:8080/upload")); // Replace it with an actual upload URL + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); + + QNetworkAccessManager *manager = new QNetworkAccessManager(file); + QNetworkReply *reply = manager->post(request, file); + + QObject::connect(reply, &QNetworkReply::finished, [=]() { + if (reply->error() == QNetworkReply::NoError) + qDebug() << "Log file upload successful."; + else + qWarning() << "Log file upload failed:" << reply->errorString(); + + file->deleteLater(); + reply->deleteLater(); + QCoreApplication::quit(); + }); +//! [1] +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); +//! [1] + + if (!QNetworkInformation::loadDefaultBackend()) { + qWarning() << "Failed to load QNetworkInformation backend. Exiting."; + return 1; + } + + QNetworkInformation *netInfo = QNetworkInformation::instance(); + + QTimer::singleShot(0, [&]() { +//! [2] + if (netInfo->isMetered()) { + qWarning() << "Log upload skipped: Current network is metered."; + app.quit(); + } else { + uploadLogFile(); + } +//! [2] + }); + + return app.exec(); +//! [3] +} +//! [3] +//![file] diff --git a/src/network/doc/snippets/code/src_network_kernel_qnetworkinformation_reachability.cpp b/src/network/doc/snippets/code/src_network_kernel_qnetworkinformation_reachability.cpp new file mode 100644 index 00000000000..2c736f40c9a --- /dev/null +++ b/src/network/doc/snippets/code/src_network_kernel_qnetworkinformation_reachability.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +//![file] +#include <QCoreApplication> +#include <QNetworkInformation> +#include <QHostAddress> +#include <QDebug> + +//! [0] +// Simple helper to decide whether an IP address is "local" +bool isLocalAddress(const QHostAddress &address) +{ + return address.isInSubnet(QHostAddress("192.168.0.0"), 16) || + address.isInSubnet(QHostAddress("10.0.0.0"), 8) || + address.isInSubnet(QHostAddress("172.16.0.0"), 12) || + address.isLoopback(); +} + + +int main(int argc, char *argv[]) +{ +//! [0] + QCoreApplication app(argc, argv); + + // Load the default backend for QNetworkInformation + if (!QNetworkInformation::loadDefaultBackend()) { + qWarning() << "Failed to load QNetworkInformation backend. Exiting."; + return 1; + } + + QNetworkInformation *networkInfo = QNetworkInformation::instance(); +//! [1] + // Target IP address (default: Google DNS) + QString targetIpStr = argc > 1 ? argv[1] : "8.8.8.8"; + QHostAddress targetIp(targetIpStr); + + if (targetIp.isNull()) { + qWarning() << "Invalid IP address:" << targetIpStr; + return 1; + } + + // Decide what level of reachability is needed for the target + QNetworkInformation::Reachability requiredReachability = + isLocalAddress(targetIp) + ? QNetworkInformation::Reachability::Local + : QNetworkInformation::Reachability::Online; + + // Fetch the current system-reported reachability + QNetworkInformation::Reachability currentReachability = networkInfo->reachability(); + + qDebug() << "Target IP:" << targetIp.toString(); + qDebug() << "Target is considered" + << (isLocalAddress(targetIp) ? "local/site." : "external/online."); + qDebug() << "Required reachability level:" << requiredReachability; + qDebug() << "Current reachability:" << currentReachability; + + if (currentReachability < requiredReachability) { + qWarning() << "Current network state may not allow reaching the target address."; + } else { + qDebug() << "Target may be reachable based on current network state."; + } +//! [1] + return 0; +} +//![file] diff --git a/src/network/kernel/qnetworkinformation.cpp b/src/network/kernel/qnetworkinformation.cpp index a156dd08ece..66be77c383a 100644 --- a/src/network/kernel/qnetworkinformation.cpp +++ b/src/network/kernel/qnetworkinformation.cpp @@ -440,6 +440,36 @@ QNetworkInformationBackendFactory::~QNetworkInformationBackendFactory() object will also be destroyed in this thread, and various backend-specific components may rely on being destroyed in the same thread as it is created. + One possible use case for QNetworkInformation is to monitor network + connectivity status. reachability() provides an indication of whether the + system is considered online, based on information reported by the + underlying operating system or plugin. However, this information may not + always be accurate. For example, on Windows, the online check may rely on + connectivity to a Microsoft-owned server; if that server is unreachable + (e.g., due to firewall rules), the system may incorrectly report that it is + offline. As such, reachability() should not be used as a definitive + pre-check before attempting a network connection, but rather as a general + signal of connectivity state. + + To use reachability() effectively, the application must also understand + what kind of destination it is trying to reach. For example, if the target + is a local IP address, then Reachability::Local or Reachability::Site may + be sufficient. If the destination is on the public internet, then + Reachability::Online is required. Without this context, interpretring the + reported reachability may lead to incorrect assumptions about actual + network access. + + \warning Only Linux and Windows provide support for the finer-grained + Reachability::Site and Reachability::Local options. On Android and Apple + platforms reachability() is limited to reporting only Online, Offline or + Unknown. Therefore, any logic that relies on detecting Local or Site level + connectivity must include appropriate platform checks or fallbacks. + + \snippet code/src_network_kernel_qnetworkinformation_reachability.cpp 0 + \dots + \snippet code/src_network_kernel_qnetworkinformation_reachability.cpp 1 + \dots + \sa QNetworkInformation::Feature */ @@ -612,6 +642,14 @@ QNetworkInformation::TransportMedium QNetworkInformation::transportMedium() cons application should perform certain network requests or uploads. For instance, you may not want to upload logs or diagnostics while this property is \c true. + + \snippet code/src_network_kernel_qnetworkinformation_metering.cpp 0 + \dots + \snippet code/src_network_kernel_qnetworkinformation_metering.cpp 1 + \dots + \snippet code/src_network_kernel_qnetworkinformation_metering.cpp 2 + \dots + \snippet code/src_network_kernel_qnetworkinformation_metering.cpp 3 */ bool QNetworkInformation::isMetered() const { diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h index b120e8bc6d1..60d2ac12644 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h @@ -11,6 +11,8 @@ #include <QtCore/private/qcore_mac_p.h> #include <QtGui/qaccessible.h> +#import <AppKit/NSAccessibilityElement.h> + QT_DECLARE_NAMESPACED_OBJC_INTERFACE(QMacAccessibilityElement, NSObject <NSAccessibilityElement> - (instancetype)initWithId:(QAccessible::Id)anId; - (instancetype)initWithId:(QAccessible::Id)anId role:(NSAccessibilityRole)role; diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h index 5a5fdfe664e..65257399eec 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h @@ -22,6 +22,8 @@ #include "qcocoansmenu.h" +#import <AppKit/NSApplication.h> + QT_DECLARE_NAMESPACED_OBJC_INTERFACE(QCocoaApplicationDelegate, NSObject <NSApplicationDelegate> @property (nonatomic, retain) NSMenu *dockMenu; + (instancetype)sharedDelegate; diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 6a54a826c0a..e2b517f20a5 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -26,6 +26,10 @@ #if defined(__OBJC__) +#import <AppKit/NSDragging.h> +#import <AppKit/NSEvent.h> +#import <AppKit/NSButton.h> + Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSView)); struct mach_header; diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.h b/src/plugins/platforms/cocoa/qcocoamenuloader.h index 9c2fc842395..afcb6756ed9 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.h +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.h @@ -17,6 +17,8 @@ #include <QtCore/private/qcore_mac_p.h> +#import <AppKit/NSMenu.h> + QT_FORWARD_DECLARE_CLASS(QCocoaMenuItem); QT_DECLARE_NAMESPACED_OBJC_INTERFACE(QCocoaMenuLoader, NSObject diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.h b/src/plugins/platforms/cocoa/qcocoansmenu.h index 533aba1a21d..467115359b1 100644 --- a/src/plugins/platforms/cocoa/qcocoansmenu.h +++ b/src/plugins/platforms/cocoa/qcocoansmenu.h @@ -17,6 +17,8 @@ #include <QtCore/private/qcore_mac_p.h> +#import <AppKit/NSMenu.h> + QT_FORWARD_DECLARE_CLASS(QCocoaMenu); QT_FORWARD_DECLARE_CLASS(QCocoaMenuItem); diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h index 4898255e022..273d2c942eb 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.h +++ b/src/plugins/platforms/cocoa/qcocoascreen.h @@ -12,8 +12,8 @@ #include <CoreGraphics/CoreGraphics.h> #include <CoreVideo/CoreVideo.h> -Q_FORWARD_DECLARE_OBJC_CLASS(NSScreen); -Q_FORWARD_DECLARE_OBJC_CLASS(NSArray); +#import <AppKit/NSScreen.h> +#import <Foundation/NSArray.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 12ca6106732..7c55b38886b 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -196,6 +196,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSViewMenuHelper); - (void)removeFromSuperview { + qCDebug(lcQpaWindow) << "Removing" << self << "from" << self.superview; QMacAutoReleasePool pool; [super removeFromSuperview]; } diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h index e5b3c4b3a98..76fd3f13c90 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.h +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h @@ -6,6 +6,8 @@ #include <QtCore/private/qcore_mac_p.h> +#import <AppKit/NSWindow.h> + QT_BEGIN_NAMESPACE class QCocoaWindow; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp index c96ac2855b4..03d8d330578 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -333,7 +333,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, ::xdg_surface *s if (type == Qt::ToolTip) setPopup(transientParent); - else if (type == Qt::Popup || type == Qt::Tool) + else if (type == Qt::Popup) setGrabPopup(transientParent, display->lastInputDevice(), display->lastInputSerial()); else setToplevel(); @@ -599,10 +599,11 @@ bool QWaylandXdgSurface::requestActivate() bool QWaylandXdgSurface::requestActivateOnShow() { - const Qt::WindowFlags flags = m_window->window()->flags(); - if (flags.testFlag(Qt::Popup)) + const Qt::WindowType type = m_window->window()->type(); + if (type == Qt::ToolTip || type == Qt::Popup || type == Qt::SplashScreen) return false; + const Qt::WindowFlags flags = m_window->window()->flags(); if (flags & Qt::WindowDoesNotAcceptFocus) return false; diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp index 47fdf0e1ffc..90a5965bba6 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshellintegration.cpp @@ -55,7 +55,7 @@ QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWi return new QWaylandShellSurface(window); } - if ((type == Qt::Popup || type == Qt::Tool) && (!transientParent || !display->lastInputDevice())) { + if (type == Qt::Popup && (!transientParent || !display->lastInputDevice())) { qCWarning(lcQpaWayland) << "Failed to create grabbing popup. Ensure popup " << window->window() << "has a transientParent set and that parent window has received input."; QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::AsynchronousDelivery>(window->window()); return new QWaylandShellSurface(window); diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index ba98e579e39..cc32eb4d1e9 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -121,7 +121,7 @@ void QWaylandWindow::initWindow() Q_ASSERT(mShellIntegration); mTransientParent = guessTransientParent(); if (mTransientParent) { - if (window()->type() == Qt::Popup || window()->type() == Qt::Tool) { + if (window()->type() == Qt::Popup) { if (mTopPopup && mTopPopup != mTransientParent) { qCWarning(lcQpaWayland) << "Creating a popup with a parent," << mTransientParent->window() << "which does not match the current topmost grabbing popup," @@ -346,9 +346,7 @@ void QWaylandWindow::resetSurfaceRole() closeChildPopups(); if (mTopPopup == this) - mTopPopup = mTransientParent && - (mTransientParent->window()->type() == Qt::Popup || mTransientParent->window()->type() == Qt::Tool) - ? mTransientParent : nullptr; + mTopPopup = mTransientParent && (mTransientParent->window()->type() == Qt::Popup) ? mTransientParent : nullptr; if (mTransientParent) mTransientParent->removeChildPopup(this); mTransientParent = nullptr; @@ -479,7 +477,8 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect) void QWaylandWindow::setGeometry(const QRect &r) { auto rect = r; - if (fixedToplevelPositions && !QPlatformWindow::parent() && !window()->flags().testFlag(Qt::Popup)) { + if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup + && window()->type() != Qt::ToolTip && window()->type() != Qt::Tool) { rect.moveTo(screen()->geometry().topLeft()); } setGeometry_helper(rect); @@ -1219,12 +1218,12 @@ QWaylandWindow *QWaylandWindow::guessTransientParent() const if (auto transientParent = closestShellSurfaceWindow(window()->transientParent())) return transientParent; - if (window()->type() == Qt::Popup || window()->type() == Qt::Tool) { + if (window()->type() == Qt::Popup) { if (mTopPopup) return mTopPopup; } - if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup || window()->type() == Qt::Tool) { + if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup) { if (auto lastInputWindow = display()->lastInputWindow()) return closestShellSurfaceWindow(lastInputWindow->window()); } @@ -1499,7 +1498,8 @@ void QWaylandWindow::handleScreensChanged() QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->QPlatformScreen::screen()); - if (fixedToplevelPositions && !QPlatformWindow::parent() && !window()->flags().testFlag(Qt::Popup) + if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup + && window()->type() != Qt::ToolTip && window()->type() != Qt::Tool && geometry().topLeft() != newScreen->geometry().topLeft()) { auto geometry = this->geometry(); geometry.moveTo(newScreen->geometry().topLeft()); @@ -1649,7 +1649,7 @@ qreal QWaylandWindow::devicePixelRatio() const bool QWaylandWindow::setMouseGrabEnabled(bool grab) { - if (window()->type() != Qt::Popup && window()->type() != Qt::Tool) { + if (window()->type() != Qt::Popup) { qWarning("This plugin supports grabbing the mouse only for popup windows"); return false; } diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 83b2d284e86..2c07f4e387c 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1963,6 +1963,95 @@ void QMacStylePrivate::resolveCurrentNSView(QWindow *window) const backingStoreNSView = window ? (NSView *)window->winId() : nil; } +void QMacStylePrivate::drawProgressBar(QPainter* p, const QStyleOptionProgressBar *pb) const +{ + const qreal progress = pb->progress / double(pb->maximum - pb->minimum); + const bool indeterminate = (pb->minimum == 0 && pb->maximum == 0); + const bool vertical = !(pb->state & QStyle::State_Horizontal); + const bool inverted = pb->invertedAppearance || (!vertical && (pb->direction == Qt::RightToLeft)); + QRect rect = pb->rect; + + // The height of a (horizontal) progressbar is fixed, and is found to have + // a value of 8 (from eyeballing an NSProgressIndicator in XCode 26) + const qreal fixedSize = 8; + const qreal radius = fixedSize / 2.; + + QRectF groove; + QRectF track; + + if (vertical) + groove = QRectF((rect.width() - fixedSize) / 2, rect.y(), fixedSize, rect.height()); + else + groove = QRectF(rect.x(), (rect.height() - fixedSize) / 2, rect.width(), fixedSize); + + if (indeterminate) { + const qreal velocity = 100; + const qreal minBlockSize = 15; + const qreal maxBlockFraction = 0.25; + + // We use a static timer to dermine the progress position, since + // all indeterminate progressbars should animate in sync. + static QElapsedTimer timer; + if (!timer.isValid()) + timer.start(); + + const qreal time = (timer.elapsed() / (1000.0 / 60.0)); + const qreal normalizedPos = 0.5 - (0.5 * std::cos(time / velocity * 2 * M_PI)); // 0 -> 1 + + if (vertical) { + const qreal maxBlockSize = rect.height() * maxBlockFraction; + const qreal margin = (maxBlockSize - minBlockSize) / (2 * rect.height()); + const qreal pos = -margin + (normalizedPos * (1 + (margin * 2))); + const qreal pixelPos = pos * rect.height(); + const qreal top = pixelPos > (maxBlockSize / 2) ? pixelPos - (maxBlockSize / 2) : 0; + const qreal bottom = pixelPos > rect.height() - (maxBlockSize / 2) + ? rect.height() : pixelPos + (maxBlockSize / 2); + track = QRectF((rect.width() - fixedSize) / 2, top, fixedSize, bottom - top); + } else { + const qreal maxBlockSize = rect.width() * maxBlockFraction; + const qreal margin = (maxBlockSize - minBlockSize) / (2 * rect.width()); + const qreal pos = -margin + (normalizedPos * (1 + (margin * 2))); + const qreal pixelPos = pos * rect.width(); + const qreal left = pixelPos > (maxBlockSize / 2) ? pixelPos - (maxBlockSize / 2) : 0; + const qreal right = pixelPos > rect.width() - (maxBlockSize / 2) + ? rect.width() : pixelPos + (maxBlockSize / 2); + track = QRectF(left, (rect.height() - fixedSize) / 2, right - left, fixedSize); + } + } else { + if (vertical) { + const qreal trackSize = rect.height() * progress; + if (inverted) + track = QRectF((rect.width() - fixedSize) / 2, rect.y(), fixedSize, trackSize); + else + track = QRectF((rect.width() - fixedSize) / 2, rect.height() - trackSize, fixedSize, trackSize); + } else { + const qreal trackSize = rect.width() * progress; + if (inverted) + track = QRectF(rect.width() - trackSize, (rect.height() - fixedSize) / 2, trackSize, fixedSize); + else + track = QRectF(rect.x(), (rect.height() - fixedSize) / 2, trackSize, fixedSize); + } + } + + // Draw groove + p->save(); + p->setRenderHint(QPainter::Antialiasing, true); + if (@available(macOS 14.0, *)) { // silence compiler + p->setPen(qt_mac_toQBrush([NSColor secondarySystemFillColor]).color()); + p->setBrush(qt_mac_toQBrush([NSColor tertiarySystemFillColor]).color()); + } else { + p->setPen(Qt::NoPen); + p->setBrush(qt_mac_toQBrush([NSColor controlColor]).color()); + } + p->drawRoundedRect(groove, radius, radius); + + // Draw track / progress + p->setPen(Qt::NoPen); + p->setBrush(pb->state & QStyle::State_Active ? pb->palette.accent().color() : Qt::lightGray); + p->drawRoundedRect(track, radius, radius); + p->restore(); +} + QMacStyle *QMacStyle::create() { return new QMacApperanceStyle<QMacStyle>; @@ -4312,17 +4401,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter bool reverse = (!vertical && (pb->direction == Qt::RightToLeft)); if (inverted) reverse = !reverse; - QRect rect = pb->rect; - if (vertical) - rect = rect.transposed(); - const CGRect cgRect = rect.toCGRect(); const auto aquaSize = d->effectiveAquaSizeConstrain(opt, w); const QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject)); - QIndeterminateProgressIndicator *ipi = nil; - if (isIndeterminate || animation) - ipi = static_cast<QIndeterminateProgressIndicator *>(d->cocoaControl({ QMacStylePrivate::ProgressIndicator_Indeterminate, aquaSize })); if (isIndeterminate) { // QIndeterminateProgressIndicator derives from NSProgressIndicator. We use a single // instance that we start animating as soon as one of the progress bars is indeterminate. @@ -4336,28 +4418,45 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // NSProgressIndicator is heavier to draw than the HITheme API, so we reduce the frame rate a couple notches. animation->setFrameRate(QStyleAnimation::FifteenFps); d->startAnimation(animation); - [ipi startAnimation]; } - d->setupNSGraphicsContext(cg, NO); - d->setupVerticalInvertedXform(cg, reverse, vertical, cgRect); - [ipi drawWithFrame:cgRect inView:d->backingStoreNSView]; - d->restoreNSGraphicsContext(cg); + if (qt_apple_runningWithLiquidGlass()) { + d->drawProgressBar(p, pb); + } else { + if (vertical) + rect = rect.transposed(); + d->setupNSGraphicsContext(cg, NO); + d->setupVerticalInvertedXform(cg, reverse, vertical, rect.toCGRect()); + if (auto *ipi + = static_cast<QIndeterminateProgressIndicator *>( + d->cocoaControl({ QMacStylePrivate::ProgressIndicator_Indeterminate, aquaSize }))) { + [ipi startAnimation]; + [ipi drawWithFrame:rect.toCGRect() inView:d->backingStoreNSView]; + } + d->restoreNSGraphicsContext(cg); + } } else { if (animation) { d->stopAnimation(opt->styleObject); - [ipi stopAnimation]; + if (auto *ipi + = static_cast<QIndeterminateProgressIndicator *>( + d->cocoaControl({ QMacStylePrivate::ProgressIndicator_Indeterminate, aquaSize }))) + [ipi stopAnimation]; + } + if (qt_apple_runningWithLiquidGlass()) { + d->drawProgressBar(p, pb); + } else { + if (vertical) + rect = rect.transposed(); + const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize); + auto *pi = static_cast<NSProgressIndicator *>(d->cocoaControl(cw)); + d->drawNSViewInRect(pi, rect, p, ^(CGContextRef ctx, const CGRect &cgrect) { + d->setupVerticalInvertedXform(ctx, reverse, vertical, cgrect); + pi.minValue = pb->minimum; + pi.maxValue = pb->maximum; + pi.doubleValue = pb->progress; + [pi drawRect:cgrect]; }); } - - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize); - auto *pi = static_cast<NSProgressIndicator *>(d->cocoaControl(cw)); - d->drawNSViewInRect(pi, rect, p, ^(CGContextRef ctx, const CGRect &rect) { - d->setupVerticalInvertedXform(ctx, reverse, vertical, rect); - pi.minValue = pb->minimum; - pi.maxValue = pb->maximum; - pi.doubleValue = pb->progress; - [pi drawRect:rect]; - }); } } break; diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 3ad91df33fe..d702b9e30df 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -237,6 +237,7 @@ public: void drawNSViewInRect(NSView *view, const QRectF &rect, QPainter *p, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const; void resolveCurrentNSView(QWindow *window) const; + void drawProgressBar(QPainter *p, const QStyleOptionProgressBar *pb) const; void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const; void drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const; diff --git a/src/widgets/doc/snippets/itemselection/main.cpp b/src/widgets/doc/snippets/itemselection/main.cpp index 31908076055..ce277432100 100644 --- a/src/widgets/doc/snippets/itemselection/main.cpp +++ b/src/widgets/doc/snippets/itemselection/main.cpp @@ -13,29 +13,7 @@ #include <QItemSelectionModel> #include <QTableView> -class TableModel : public QAbstractTableModel -{ - Q_OBJECT -public: - TableModel(int rows, int columns, QObject *parent = nullptr) - : QAbstractTableModel(parent), m_rows(rows), m_columns(columns) {} - - int rowCount(const QModelIndex &parent = QModelIndex()) const override { - return m_rows; - } - - int columnCount(const QModelIndex &parent = QModelIndex()) const override { - return m_columns; - } - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { - return QVariant(); - } - -private: - int m_rows, m_columns; - -}; +#include "../common-table-model/model.h" int main(int argc, char *argv[]) { diff --git a/src/widgets/doc/snippets/reading-selections/window.cpp b/src/widgets/doc/snippets/reading-selections/window.cpp index c0c3bcbe6f4..1f219c861e1 100644 --- a/src/widgets/doc/snippets/reading-selections/window.cpp +++ b/src/widgets/doc/snippets/reading-selections/window.cpp @@ -17,25 +17,7 @@ #include <QTableView> #include "../include/mainwindow.h" - -class TableModel : public QAbstractTableModel -{ - Q_OBJECT -public: - TableModel(int rows, int columns, QObject *parent = nullptr) {} - - int rowCount(const QModelIndex &parent = QModelIndex()) const override { - return 0; - } - - int columnCount(const QModelIndex &parent = QModelIndex()) const override { - return 0; - } - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { - return QVariant(); - } -}; +#include "../common-table-model/model.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) diff --git a/src/widgets/doc/snippets/sharedtablemodel/main.cpp b/src/widgets/doc/snippets/sharedtablemodel/main.cpp index ab02094595d..76a4ebc6670 100644 --- a/src/widgets/doc/snippets/sharedtablemodel/main.cpp +++ b/src/widgets/doc/snippets/sharedtablemodel/main.cpp @@ -13,25 +13,7 @@ #include <QItemSelectionModel> #include <QTableView> -class TableModel : public QAbstractTableModel -{ - Q_OBJECT -public: - TableModel(int rows, int columns, QObject *parent = nullptr) - : QAbstractTableModel(parent), rowCount(rows), columnCount(columns) {} - - int rowCount(const QModelIndex &parent = QModelIndex()) const override { - return rowCount; - } - - int columnCount(const QModelIndex &parent = QModelIndex()) const override { - return columnCount; - } - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { - return QVariant(); - } -}; +#include "../common-table-model/model.h" int main(int argc, char *argv[]) { diff --git a/src/widgets/doc/snippets/updating-selections/window.cpp b/src/widgets/doc/snippets/updating-selections/window.cpp index d03a36d5fc3..a2dc44d1088 100644 --- a/src/widgets/doc/snippets/updating-selections/window.cpp +++ b/src/widgets/doc/snippets/updating-selections/window.cpp @@ -15,26 +15,7 @@ #include <QTableView> #include "../include/mainwindow.h" - -class TableModel : public QAbstractTableModel -{ - Q_OBJECT -public: - TableModel(int rows, int columns, QObject *parent = nullptr) - : QAbstractTableModel(parent) {} - - int rowCount(const QModelIndex &parent = QModelIndex()) const override { - return 0; - } - - int columnCount(const QModelIndex &parent = QModelIndex()) const override { - return 0; - } - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { - return QVariant(); - } -}; +#include "../common-table-model/model.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h index 0cbcc5321d4..262207f40c8 100644 --- a/src/widgets/kernel/qwindowcontainer_p.h +++ b/src/widgets/kernel/qwindowcontainer_p.h @@ -30,7 +30,7 @@ class Q_WIDGETS_EXPORT QWindowContainer : public QWidget public: explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = nullptr, Qt::WindowFlags f = { }); ~QWindowContainer(); - QWindow *containedWindow() const; + Q_INVOKABLE QWindow *containedWindow() const; QSize minimumSizeHint() const override; static void toplevelAboutToBeDestroyed(QWidget *parent); |