summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra Soto <fabian.guerra@mapbox.com>2017-05-23 12:02:09 -0400
committerGitHub <noreply@github.com>2017-05-23 12:02:09 -0400
commitfe17f7e8db266a125ac05d805003f5d2bf1548c6 (patch)
tree9d760b8f53dd60a363059ef6f776d8085be3990c
parent71b686517298e100f8021dca62db65a2ca9baad2 (diff)
downloadqtlocation-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)
-rw-r--r--cmake/core-files.cmake2
-rw-r--r--src/mbgl/layout/symbol_layout.cpp2
-rw-r--r--src/mbgl/tile/geometry_tile.cpp12
-rw-r--r--src/mbgl/tile/geometry_tile.hpp5
-rw-r--r--src/mbgl/util/i18n.cpp19
-rw-r--r--src/mbgl/util/i18n.hpp4
-rw-r--r--src/mbgl/util/throttler.cpp36
-rw-r--r--src/mbgl/util/throttler.hpp22
8 files changed, 94 insertions, 8 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index e9d7442e5d..4779abba86 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -583,6 +583,8 @@ set(MBGL_CORE_FILES
src/mbgl/util/thread_context.cpp
src/mbgl/util/thread_context.hpp
src/mbgl/util/thread_local.hpp
+ src/mbgl/util/throttler.cpp
+ src/mbgl/util/throttler.hpp
src/mbgl/util/tile_coordinate.hpp
src/mbgl/util/tile_cover.cpp
src/mbgl/util/tile_cover.hpp
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