diff options
author | Fabian Guerra Soto <fabian.guerra@mapbox.com> | 2017-05-23 12:02:09 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-23 12:02:09 -0400 |
commit | fe17f7e8db266a125ac05d805003f5d2bf1548c6 (patch) | |
tree | 9d760b8f53dd60a363059ef6f776d8085be3990c /src/mbgl | |
parent | 71b686517298e100f8021dca62db65a2ca9baad2 (diff) | |
download | qtlocation-mapboxgl-fe17f7e8db266a125ac05d805003f5d2bf1548c6.tar.gz |
Cherry-pick arabic text to release branch v3.6.0 (#9071)
* [core] Throttle tiles to redo symbol placement at most once every 300ms.
Fixes issue #8435 and prepares for pitch-scaling changes in issue #8967.
* [core] Disable letter-spacing for Arabic labels (issue #9057)
Diffstat (limited to 'src/mbgl')
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.cpp | 12 | ||||
-rw-r--r-- | src/mbgl/tile/geometry_tile.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/util/i18n.cpp | 19 | ||||
-rw-r--r-- | src/mbgl/util/i18n.hpp | 4 | ||||
-rw-r--r-- | src/mbgl/util/throttler.cpp | 36 | ||||
-rw-r--r-- | src/mbgl/util/throttler.hpp | 22 |
7 files changed, 92 insertions, 8 deletions
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index aa91eb1688..2accac281b 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -237,7 +237,7 @@ void SymbolLayout::prepare(const GlyphPositionMap& glyphs, const IconMap& icons) /* horizontalAlign */ horizontalAlign, /* verticalAlign */ verticalAlign, /* justify */ justify, - /* spacing: ems */ layout.get<TextLetterSpacing>() * oneEm, + /* spacing: ems */ util::i18n::allowsLetterSpacing(*feature.text) ? layout.get<TextLetterSpacing>() * oneEm : 0.0f, /* translate */ Point<float>(layout.evaluate<TextOffset>(zoom, feature)[0] * oneEm, layout.evaluate<TextOffset>(zoom, feature)[1] * oneEm), /* verticalHeight */ oneEm, /* writingMode */ writingMode, diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index a8eda38284..29ba7d42cd 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -18,6 +18,7 @@ #include <mbgl/map/query.hpp> #include <mbgl/util/run_loop.hpp> #include <mbgl/style/filter_evaluator.hpp> +#include <mbgl/util/chrono.hpp> #include <mbgl/util/logging.hpp> #include <iostream> @@ -41,7 +42,8 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_, obsolete, parameters.mode), glyphAtlas(glyphAtlas_), - spriteAtlas(spriteAtlas_) { + spriteAtlas(spriteAtlas_), + placementThrottler(Milliseconds(300), [this] { invokePlacement(); }) { } GeometryTile::~GeometryTile() { @@ -81,7 +83,13 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) { ++correlationID; requestedConfig = desiredConfig; - worker.invoke(&GeometryTileWorker::setPlacementConfig, desiredConfig, correlationID); + placementThrottler.invoke(); +} + +void GeometryTile::invokePlacement() { + if (requestedConfig) { + worker.invoke(&GeometryTileWorker::setPlacementConfig, *requestedConfig, correlationID); + } } void GeometryTile::redoLayout() { diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index 594952d329..ed5d8d87bf 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -6,6 +6,7 @@ #include <mbgl/text/glyph_atlas.hpp> #include <mbgl/text/placement_config.hpp> #include <mbgl/util/feature.hpp> +#include <mbgl/util/throttler.hpp> #include <mbgl/actor/actor.hpp> #include <atomic> @@ -87,6 +88,8 @@ protected: } private: + void invokePlacement(); + const std::string sourceID; style::Style& style; @@ -108,6 +111,8 @@ private: std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets; std::unique_ptr<CollisionTile> collisionTile; + + util::Throttler placementThrottler; }; } // namespace mbgl diff --git a/src/mbgl/util/i18n.cpp b/src/mbgl/util/i18n.cpp index 8e56877a64..6cfdc697e3 100644 --- a/src/mbgl/util/i18n.cpp +++ b/src/mbgl/util/i18n.cpp @@ -1,5 +1,6 @@ #include "i18n.hpp" +#include <algorithm> #include <map> namespace { @@ -29,14 +30,14 @@ DEFINE_IS_IN_UNICODE_BLOCK(Latin1Supplement, 0x0080, 0x00FF) // DEFINE_IS_IN_UNICODE_BLOCK(CyrillicSupplement, 0x0500, 0x052F) // DEFINE_IS_IN_UNICODE_BLOCK(Armenian, 0x0530, 0x058F) // DEFINE_IS_IN_UNICODE_BLOCK(Hebrew, 0x0590, 0x05FF) -// DEFINE_IS_IN_UNICODE_BLOCK(Arabic, 0x0600, 0x06FF) +DEFINE_IS_IN_UNICODE_BLOCK(Arabic, 0x0600, 0x06FF) // DEFINE_IS_IN_UNICODE_BLOCK(Syriac, 0x0700, 0x074F) -// DEFINE_IS_IN_UNICODE_BLOCK(ArabicSupplement, 0x0750, 0x077F) +DEFINE_IS_IN_UNICODE_BLOCK(ArabicSupplement, 0x0750, 0x077F) // DEFINE_IS_IN_UNICODE_BLOCK(Thaana, 0x0780, 0x07BF) // DEFINE_IS_IN_UNICODE_BLOCK(NKo, 0x07C0, 0x07FF) // DEFINE_IS_IN_UNICODE_BLOCK(Samaritan, 0x0800, 0x083F) // DEFINE_IS_IN_UNICODE_BLOCK(Mandaic, 0x0840, 0x085F) -// DEFINE_IS_IN_UNICODE_BLOCK(ArabicExtendedA, 0x08A0, 0x08FF) +DEFINE_IS_IN_UNICODE_BLOCK(ArabicExtendedA, 0x08A0, 0x08FF) // DEFINE_IS_IN_UNICODE_BLOCK(Devanagari, 0x0900, 0x097F) // DEFINE_IS_IN_UNICODE_BLOCK(Bengali, 0x0980, 0x09FF) // DEFINE_IS_IN_UNICODE_BLOCK(Gurmukhi, 0x0A00, 0x0A7F) @@ -169,13 +170,13 @@ DEFINE_IS_IN_UNICODE_BLOCK(HangulJamoExtendedB, 0xD7B0, 0xD7FF) DEFINE_IS_IN_UNICODE_BLOCK(PrivateUseArea, 0xE000, 0xF8FF) DEFINE_IS_IN_UNICODE_BLOCK(CJKCompatibilityIdeographs, 0xF900, 0xFAFF) // DEFINE_IS_IN_UNICODE_BLOCK(AlphabeticPresentationForms, 0xFB00, 0xFB4F) -// DEFINE_IS_IN_UNICODE_BLOCK(ArabicPresentationFormsA, 0xFB50, 0xFDFF) +DEFINE_IS_IN_UNICODE_BLOCK(ArabicPresentationFormsA, 0xFB50, 0xFDFF) // DEFINE_IS_IN_UNICODE_BLOCK(VariationSelectors, 0xFE00, 0xFE0F) DEFINE_IS_IN_UNICODE_BLOCK(VerticalForms, 0xFE10, 0xFE1F) // DEFINE_IS_IN_UNICODE_BLOCK(CombiningHalfMarks, 0xFE20, 0xFE2F) DEFINE_IS_IN_UNICODE_BLOCK(CJKCompatibilityForms, 0xFE30, 0xFE4F) DEFINE_IS_IN_UNICODE_BLOCK(SmallFormVariants, 0xFE50, 0xFE6F) -// DEFINE_IS_IN_UNICODE_BLOCK(ArabicPresentationFormsB, 0xFE70, 0xFEFF) +DEFINE_IS_IN_UNICODE_BLOCK(ArabicPresentationFormsB, 0xFE70, 0xFEFF) DEFINE_IS_IN_UNICODE_BLOCK(HalfwidthandFullwidthForms, 0xFF00, 0xFFEF) // DEFINE_IS_IN_UNICODE_BLOCK(Specials, 0xFFF0, 0xFFFF) // DEFINE_IS_IN_UNICODE_BLOCK(LinearBSyllabary, 0x10000, 0x1007F) @@ -332,6 +333,14 @@ bool allowsWordBreaking(char16_t chr) { || chr == 0x2013 /* en dash */); } +bool charAllowsLetterSpacing(char16_t chr) { + return !(isInArabic(chr) || isInArabicSupplement(chr) || isInArabicExtendedA(chr) || isInArabicPresentationFormsA(chr) || isInArabicPresentationFormsB(chr)); +} + +bool allowsLetterSpacing(const std::u16string& string) { + return std::all_of(string.begin(), string.end(), charAllowsLetterSpacing); +} + bool allowsIdeographicBreaking(const std::u16string& string) { for (char16_t chr : string) { if (!allowsIdeographicBreaking(chr)) { diff --git a/src/mbgl/util/i18n.hpp b/src/mbgl/util/i18n.hpp index 186212f50d..61c5a1ea96 100644 --- a/src/mbgl/util/i18n.hpp +++ b/src/mbgl/util/i18n.hpp @@ -10,6 +10,10 @@ namespace i18n { by the given Unicode codepoint due to word breaking. */ bool allowsWordBreaking(char16_t chr); +/** Returns whether the given string can be displayed with letter-spacing. + False for Arabic scripts, where letter-spacing will break ligatures. */ +bool allowsLetterSpacing(const std::u16string& string); + /** Returns whether a line break can be inserted after any character in the given string. If false, line breaking should occur on word boundaries instead. */ diff --git a/src/mbgl/util/throttler.cpp b/src/mbgl/util/throttler.cpp new file mode 100644 index 0000000000..910810ce2f --- /dev/null +++ b/src/mbgl/util/throttler.cpp @@ -0,0 +1,36 @@ +#include <mbgl/util/throttler.hpp> + +namespace mbgl { +namespace util { + +Throttler::Throttler(Duration frequency_, std::function<void()>&& function_) + : frequency(frequency_) + , function(std::move(function_)) + , pendingInvocation(false) + , lastInvocation(TimePoint::min()) +{} + +void Throttler::invoke() { + if (pendingInvocation) { + return; + } + + Duration timeToNextInvocation = lastInvocation == TimePoint::min() + ? Duration::zero() + : (lastInvocation + frequency) - Clock::now(); + + if (timeToNextInvocation <= Duration::zero()) { + lastInvocation = Clock::now(); + function(); + } else { + pendingInvocation = true; + timer.start(timeToNextInvocation, Duration::zero(), [this]{ + pendingInvocation = false; + lastInvocation = Clock::now(); + function(); + }); + } +} + +} // namespace util +} // namespace mbgl diff --git a/src/mbgl/util/throttler.hpp b/src/mbgl/util/throttler.hpp new file mode 100644 index 0000000000..175de7ccaf --- /dev/null +++ b/src/mbgl/util/throttler.hpp @@ -0,0 +1,22 @@ +#include <mbgl/util/chrono.hpp> +#include <mbgl/util/timer.hpp> + +namespace mbgl { +namespace util { + +class Throttler { +public: + Throttler(Duration frequency, std::function<void()>&& function); + + void invoke(); +private: + Duration frequency; + std::function<void()> function; + + Timer timer; + bool pendingInvocation; + TimePoint lastInvocation; +}; + +} // namespace util +} // namespace mbgl |