summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core-files.json10
-rw-r--r--src/mbgl/actor/mailbox.cpp12
-rw-r--r--src/mbgl/actor/scheduler.cpp11
-rw-r--r--src/mbgl/geometry/line_atlas.cpp128
-rw-r--r--src/mbgl/geometry/line_atlas.hpp50
-rw-r--r--src/mbgl/gfx/context.hpp7
-rw-r--r--src/mbgl/gfx/rendering_stats.cpp12
-rw-r--r--src/mbgl/gl/context.cpp34
-rw-r--r--src/mbgl/gl/context.hpp6
-rw-r--r--src/mbgl/gl/index_buffer_resource.cpp14
-rw-r--r--src/mbgl/gl/index_buffer_resource.hpp5
-rw-r--r--src/mbgl/gl/object.cpp2
-rw-r--r--src/mbgl/gl/texture_resource.cpp45
-rw-r--r--src/mbgl/gl/texture_resource.hpp7
-rw-r--r--src/mbgl/gl/upload_pass.cpp12
-rw-r--r--src/mbgl/gl/vertex_buffer_resource.cpp14
-rw-r--r--src/mbgl/gl/vertex_buffer_resource.hpp5
-rw-r--r--src/mbgl/layout/symbol_layout.cpp19
-rw-r--r--src/mbgl/renderer/image_manager.cpp73
-rw-r--r--src/mbgl/renderer/image_manager.hpp17
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp41
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp9
-rw-r--r--src/mbgl/renderer/render_orchestrator.cpp85
-rw-r--r--src/mbgl/renderer/render_orchestrator.hpp4
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp4
-rw-r--r--src/mbgl/style/expression/assertion.cpp6
-rw-r--r--src/mbgl/style/expression/collator.cpp24
-rw-r--r--src/mbgl/style/expression/formatted.cpp29
-rw-r--r--src/mbgl/style/expression/number_format.cpp4
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp66
-rw-r--r--src/mbgl/style/layers/background_layer.cpp87
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp199
-rw-r--r--src/mbgl/style/layers/custom_layer.cpp4
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer.cpp157
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp143
-rw-r--r--src/mbgl/style/layers/heatmap_layer.cpp115
-rw-r--r--src/mbgl/style/layers/hillshade_layer.cpp129
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs87
-rw-r--r--src/mbgl/style/layers/line_layer.cpp232
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp157
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp496
-rw-r--r--src/mbgl/style/light.cpp83
-rw-r--r--src/mbgl/style/light.cpp.ejs49
-rw-r--r--src/mbgl/style/sources/geojson_source.cpp24
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp38
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.hpp16
-rw-r--r--src/mbgl/text/placement.cpp67
-rw-r--r--src/mbgl/text/quads.cpp28
-rw-r--r--src/mbgl/text/shaping.cpp64
-rw-r--r--src/mbgl/text/shaping.hpp8
-rw-r--r--src/mbgl/util/color.cpp5
-rw-r--r--src/mbgl/util/thread_pool.cpp63
-rw-r--r--src/mbgl/util/thread_pool.hpp58
53 files changed, 2020 insertions, 1044 deletions
diff --git a/src/core-files.json b/src/core-files.json
index d881e6259d..c25e8273d4 100644
--- a/src/core-files.json
+++ b/src/core-files.json
@@ -17,20 +17,24 @@
"src/mbgl/geometry/line_atlas.cpp",
"src/mbgl/gfx/attribute.cpp",
"src/mbgl/gfx/renderer_backend.cpp",
+ "src/mbgl/gfx/rendering_stats.cpp",
"src/mbgl/gl/attribute.cpp",
"src/mbgl/gl/command_encoder.cpp",
"src/mbgl/gl/context.cpp",
"src/mbgl/gl/debugging_extension.cpp",
"src/mbgl/gl/enum.cpp",
+ "src/mbgl/gl/index_buffer_resource.cpp",
"src/mbgl/gl/object.cpp",
"src/mbgl/gl/offscreen_texture.cpp",
"src/mbgl/gl/render_pass.cpp",
"src/mbgl/gl/renderer_backend.cpp",
"src/mbgl/gl/texture.cpp",
+ "src/mbgl/gl/texture_resource.cpp",
"src/mbgl/gl/uniform.cpp",
"src/mbgl/gl/upload_pass.cpp",
"src/mbgl/gl/value.cpp",
"src/mbgl/gl/vertex_array.cpp",
+ "src/mbgl/gl/vertex_buffer_resource.cpp",
"src/mbgl/layermanager/background_layer_factory.cpp",
"src/mbgl/layermanager/circle_layer_factory.cpp",
"src/mbgl/layermanager/custom_layer_factory.cpp",
@@ -178,6 +182,7 @@
"src/mbgl/style/expression/check_subtype.cpp",
"src/mbgl/style/expression/coalesce.cpp",
"src/mbgl/style/expression/coercion.cpp",
+ "src/mbgl/style/expression/collator.cpp",
"src/mbgl/style/expression/collator_expression.cpp",
"src/mbgl/style/expression/comparison.cpp",
"src/mbgl/style/expression/compound_expression.cpp",
@@ -330,8 +335,11 @@
"mbgl/gfx/backend_scope.hpp": "include/mbgl/gfx/backend_scope.hpp",
"mbgl/gfx/renderable.hpp": "include/mbgl/gfx/renderable.hpp",
"mbgl/gfx/renderer_backend.hpp": "include/mbgl/gfx/renderer_backend.hpp",
+ "mbgl/gfx/rendering_stats.hpp": "include/mbgl/gfx/rendering_stats.hpp",
"mbgl/gl/renderable_resource.hpp": "include/mbgl/gl/renderable_resource.hpp",
"mbgl/gl/renderer_backend.hpp": "include/mbgl/gl/renderer_backend.hpp",
+ "mbgl/i18n/collator.hpp": "include/mbgl/i18n/collator.hpp",
+ "mbgl/i18n/number_format.hpp": "include/mbgl/i18n/number_format.hpp",
"mbgl/layermanager/background_layer_factory.hpp": "include/mbgl/layermanager/background_layer_factory.hpp",
"mbgl/layermanager/circle_layer_factory.hpp": "include/mbgl/layermanager/circle_layer_factory.hpp",
"mbgl/layermanager/custom_layer_factory.hpp": "include/mbgl/layermanager/custom_layer_factory.hpp",
@@ -449,6 +457,7 @@
"mbgl/style/sources/raster_source.hpp": "include/mbgl/style/sources/raster_source.hpp",
"mbgl/style/sources/vector_source.hpp": "include/mbgl/style/sources/vector_source.hpp",
"mbgl/style/style.hpp": "include/mbgl/style/style.hpp",
+ "mbgl/style/style_property.hpp": "include/mbgl/style/style_property.hpp",
"mbgl/style/transition_options.hpp": "include/mbgl/style/transition_options.hpp",
"mbgl/style/types.hpp": "include/mbgl/style/types.hpp",
"mbgl/style/undefined.hpp": "include/mbgl/style/undefined.hpp",
@@ -479,6 +488,7 @@
"mbgl/util/indexed_tuple.hpp": "include/mbgl/util/indexed_tuple.hpp",
"mbgl/util/interpolate.hpp": "include/mbgl/util/interpolate.hpp",
"mbgl/util/logging.hpp": "include/mbgl/util/logging.hpp",
+ "mbgl/util/monotonic_timer.hpp": "include/mbgl/util/monotonic_timer.hpp",
"mbgl/util/noncopyable.hpp": "include/mbgl/util/noncopyable.hpp",
"mbgl/util/optional.hpp": "include/mbgl/util/optional.hpp",
"mbgl/util/platform.hpp": "include/mbgl/util/platform.hpp",
diff --git a/src/mbgl/actor/mailbox.cpp b/src/mbgl/actor/mailbox.cpp
index dfe0520790..070e14bdb0 100644
--- a/src/mbgl/actor/mailbox.cpp
+++ b/src/mbgl/actor/mailbox.cpp
@@ -27,7 +27,7 @@ void Mailbox::open(Scheduler& scheduler_) {
}
if (!queue.empty()) {
- (*scheduler)->schedule(shared_from_this());
+ (*scheduler)->schedule(makeClosure(shared_from_this()));
}
}
@@ -57,7 +57,7 @@ void Mailbox::push(std::unique_ptr<Message> message) {
bool wasEmpty = queue.empty();
queue.push(std::move(message));
if (wasEmpty && scheduler) {
- (*scheduler)->schedule(shared_from_this());
+ (*scheduler)->schedule(makeClosure(shared_from_this()));
}
}
@@ -84,14 +84,20 @@ void Mailbox::receive() {
(*message)();
if (!wasEmpty) {
- (*scheduler)->schedule(shared_from_this());
+ (*scheduler)->schedule(makeClosure(shared_from_this()));
}
}
+// static
void Mailbox::maybeReceive(std::weak_ptr<Mailbox> mailbox) {
if (auto locked = mailbox.lock()) {
locked->receive();
}
}
+// static
+std::function<void()> Mailbox::makeClosure(std::weak_ptr<Mailbox> mailbox) {
+ return [mailbox]() { maybeReceive(mailbox); };
+}
+
} // namespace mbgl
diff --git a/src/mbgl/actor/scheduler.cpp b/src/mbgl/actor/scheduler.cpp
index cb0c7728ec..81e259fe1f 100644
--- a/src/mbgl/actor/scheduler.cpp
+++ b/src/mbgl/actor/scheduler.cpp
@@ -4,7 +4,14 @@
namespace mbgl {
-util::ThreadLocal<Scheduler> g_currentScheduler;
+std::function<void()> Scheduler::bindOnce(std::function<void()> fn) {
+ assert(fn);
+ return [scheduler = makeWeakPtr(), scheduled = std::move(fn)]() mutable {
+ if (!scheduled) return; // Repeated call.
+ auto schedulerGuard = scheduler.lock();
+ if (scheduler) scheduler->schedule(std::move(scheduled));
+ };
+}
static auto& current() {
static util::ThreadLocal<Scheduler> scheduler;
@@ -28,7 +35,7 @@ std::shared_ptr<Scheduler> Scheduler::GetBackground() {
std::shared_ptr<Scheduler> scheduler = weak.lock();
if (!scheduler) {
- weak = scheduler = std::make_shared<ThreadPool>(4);
+ weak = scheduler = std::make_shared<ThreadPool>();
}
return scheduler;
diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp
index 106a24d015..2e4de3edbe 100644
--- a/src/mbgl/geometry/line_atlas.cpp
+++ b/src/mbgl/geometry/line_atlas.cpp
@@ -1,50 +1,33 @@
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/gfx/upload_pass.hpp>
+#include <mbgl/math/minmax.hpp>
+#include <mbgl/util/hash.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/platform.hpp>
-#include <mbgl/util/hash.hpp>
#include <cmath>
namespace mbgl {
+namespace {
-LineAtlas::LineAtlas(const Size size)
- : image(size),
- dirty(true) {
-}
-
-LineAtlas::~LineAtlas() = default;
-
-LinePatternPos LineAtlas::getDashPosition(const std::vector<float>& dasharray,
- LinePatternCap patternCap) {
- size_t key = patternCap == LinePatternCap::Round ? std::numeric_limits<size_t>::min()
- : std::numeric_limits<size_t>::max();
+size_t getDashPatternHash(const std::vector<float>& dasharray, const LinePatternCap patternCap) {
+ size_t key =
+ patternCap == LinePatternCap::Round ? std::numeric_limits<size_t>::min() : std::numeric_limits<size_t>::max();
for (const float part : dasharray) {
util::hash_combine<float>(key, part);
}
-
- // Note: We're not handling hash collisions here.
- const auto it = positions.find(key);
- if (it == positions.end()) {
- auto inserted = positions.emplace(key, addDash(dasharray, patternCap));
- assert(inserted.second);
- return inserted.first->second;
- } else {
- return it->second;
- }
+ return key;
}
-LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatternCap patternCap) {
+LinePatternPos addDashPattern(AlphaImage& image,
+ const int32_t yOffset,
+ const std::vector<float>& dasharray,
+ const LinePatternCap patternCap) {
const uint8_t n = patternCap == LinePatternCap::Round ? 7 : 0;
- const uint8_t dashheight = 2 * n + 1;
- const uint8_t offset = 128;
+ constexpr const uint8_t offset = 128;
if (dasharray.size() < 2) {
- return LinePatternPos();
- }
-
- if (nextRow + dashheight > image.size.height) {
- Log::Warning(Event::OpenGL, "line atlas bitmap overflow");
+ Log::Warning(Event::ParseStyle, "line dasharray requires at least two elements");
return LinePatternPos();
}
@@ -60,7 +43,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
bool oddLength = dasharray.size() % 2 == 1;
for (int y = -n; y <= n; y++) {
- int row = nextRow + n + y;
+ int row = yOffset + n + y;
int index = image.size.width * row;
float left = 0;
@@ -72,7 +55,6 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
}
for (uint32_t x = 0; x < image.size.width; x++) {
-
while (right < x / stretch) {
left = right;
if (partIndex >= dasharray.size()) {
@@ -111,37 +93,79 @@ LinePatternPos LineAtlas::addDash(const std::vector<float>& dasharray, LinePatte
}
LinePatternPos position;
- position.y = (0.5 + nextRow + n) / image.size.height;
- position.height = (2.0 * n) / image.size.height;
+ position.y = (0.5 + yOffset + n) / image.size.height;
+ position.height = (2.0 * n + 1) / image.size.height;
position.width = length;
- nextRow += dashheight;
-
- dirty = true;
-
return position;
}
-Size LineAtlas::getSize() const {
- return image.size;
+} // namespace
+
+DashPatternTexture::DashPatternTexture(const std::vector<float>& from_,
+ const std::vector<float>& to_,
+ const LinePatternCap cap) {
+ const bool patternsIdentical = from_ == to_;
+ const int32_t patternHeight = cap == LinePatternCap::Round ? 15 : 1;
+
+ AlphaImage image({256, static_cast<uint32_t>((patternsIdentical ? 1 : 2) * patternHeight)});
+
+ from = addDashPattern(image, 0, from_, cap);
+ to = patternsIdentical ? from : addDashPattern(image, patternHeight, to_, cap);
+
+ texture = std::move(image);
}
-void LineAtlas::upload(gfx::UploadPass& uploadPass) {
- if (!texture) {
- texture = uploadPass.createTexture(image);
- } else if (dirty) {
- uploadPass.updateTexture(*texture, image);
+void DashPatternTexture::upload(gfx::UploadPass& uploadPass) {
+ if (texture.is<AlphaImage>()) {
+ texture = uploadPass.createTexture(texture.get<AlphaImage>());
}
+}
+
+gfx::TextureBinding DashPatternTexture::textureBinding() const {
+ // The texture needs to have been uploaded already.
+ assert(texture.is<gfx::Texture>());
+ return {texture.get<gfx::Texture>().getResource(),
+ gfx::TextureFilterType::Linear,
+ gfx::TextureMipMapType::No,
+ gfx::TextureWrapType::Repeat,
+ gfx::TextureWrapType::Clamp};
+}
- dirty = false;
+Size DashPatternTexture::getSize() const {
+ return texture.match([](const auto& obj) { return obj.size; });
}
-gfx::TextureBinding LineAtlas::textureBinding() {
- assert(texture);
- // All _changes_ to the texture should've been made and uploaded already.
- assert(!dirty);
- return { texture->getResource(), gfx::TextureFilterType::Linear, gfx::TextureMipMapType::No,
- gfx::TextureWrapType::Repeat, gfx::TextureWrapType::Clamp };
+LineAtlas::LineAtlas() = default;
+
+LineAtlas::~LineAtlas() = default;
+
+DashPatternTexture& LineAtlas::getDashPatternTexture(const std::vector<float>& from,
+ const std::vector<float>& to,
+ const LinePatternCap cap) {
+ const size_t hash = util::hash(getDashPatternHash(from, cap), getDashPatternHash(to, cap));
+
+ // Note: We're not handling hash collisions here.
+ const auto it = textures.find(hash);
+ if (it == textures.end()) {
+ auto inserted = textures.emplace(
+ std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(from, to, cap));
+ assert(inserted.second);
+ needsUpload.emplace_back(hash);
+ return inserted.first->second;
+ } else {
+ return it->second;
+ }
+}
+
+void LineAtlas::upload(gfx::UploadPass& uploadPass) {
+ for (const size_t hash : needsUpload) {
+ const auto it = textures.find(hash);
+ if (it != textures.end()) {
+ it->second.upload(uploadPass);
+ }
+ }
+ needsUpload.clear();
}
} // namespace mbgl
diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp
index b43583c9c8..853305d138 100644
--- a/src/mbgl/geometry/line_atlas.hpp
+++ b/src/mbgl/geometry/line_atlas.hpp
@@ -3,10 +3,11 @@
#include <mbgl/gfx/texture.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/variant.hpp>
-#include <vector>
-#include <unordered_map>
+#include <map>
#include <memory>
+#include <vector>
namespace mbgl {
@@ -26,29 +27,46 @@ enum class LinePatternCap : bool {
Round = true,
};
-class LineAtlas {
+class DashPatternTexture {
public:
- LineAtlas(Size);
- ~LineAtlas();
-
- // Binds the atlas texture to the GPU, and uploads data if it is out of date.
- gfx::TextureBinding textureBinding();
+ DashPatternTexture(const std::vector<float>& from, const std::vector<float>& to, LinePatternCap);
// Uploads the texture to the GPU to be available when we need it. This is a lazy operation;
- // the texture is only bound when the data is out of date (=dirty).
+ // the texture is only bound when the data is uploaded for the first time.
void upload(gfx::UploadPass&);
- LinePatternPos getDashPosition(const std::vector<float>&, LinePatternCap);
- LinePatternPos addDash(const std::vector<float>& dasharray, LinePatternCap);
+ // Binds the atlas texture to the GPU, and uploads data if it is out of date.
+ gfx::TextureBinding textureBinding() const;
+ // Returns the size of the texture image.
Size getSize() const;
+ const LinePatternPos& getFrom() const { return from; }
+ const LinePatternPos& getTo() const { return to; }
+
private:
- const AlphaImage image;
- bool dirty;
- optional<gfx::Texture> texture;
- uint32_t nextRow = 0;
- std::unordered_map<size_t, LinePatternPos> positions;
+ LinePatternPos from, to;
+ variant<AlphaImage, gfx::Texture> texture;
+};
+
+class LineAtlas {
+public:
+ LineAtlas();
+ ~LineAtlas();
+
+ // Obtains or creates a texture that has both line patterns in it
+ DashPatternTexture& getDashPatternTexture(const std::vector<float>& from,
+ const std::vector<float>& to,
+ LinePatternCap);
+
+ // Uploads the textures to the GPU to be available when we need it.
+ void upload(gfx::UploadPass&);
+
+private:
+ std::map<size_t, DashPatternTexture> textures;
+
+ // Stores a list of hashes of texture objcts that need uploading.
+ std::vector<size_t> needsUpload;
};
} // namespace mbgl
diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp
index 2c7cb14899..fe0851be11 100644
--- a/src/mbgl/gfx/context.hpp
+++ b/src/mbgl/gfx/context.hpp
@@ -1,12 +1,13 @@
#pragma once
#include <mbgl/gfx/backend.hpp>
-#include <mbgl/gfx/renderbuffer.hpp>
#include <mbgl/gfx/command_encoder.hpp>
#include <mbgl/gfx/draw_scope.hpp>
#include <mbgl/gfx/program.hpp>
-#include <mbgl/gfx/types.hpp>
+#include <mbgl/gfx/renderbuffer.hpp>
+#include <mbgl/gfx/rendering_stats.hpp>
#include <mbgl/gfx/texture.hpp>
+#include <mbgl/gfx/types.hpp>
namespace mbgl {
@@ -85,6 +86,8 @@ public:
public:
virtual std::unique_ptr<CommandEncoder> createCommandEncoder() = 0;
+ virtual const RenderingStats& renderingStats() const = 0;
+
#if not defined(NDEBUG)
public:
virtual void visualizeStencilBuffer() = 0;
diff --git a/src/mbgl/gfx/rendering_stats.cpp b/src/mbgl/gfx/rendering_stats.cpp
new file mode 100644
index 0000000000..0a239ebd11
--- /dev/null
+++ b/src/mbgl/gfx/rendering_stats.cpp
@@ -0,0 +1,12 @@
+#include <mbgl/gfx/rendering_stats.hpp>
+
+namespace mbgl {
+namespace gfx {
+
+bool RenderingStats::isZero() const {
+ return numActiveTextures == 0 && numCreatedTextures == 0 && numBuffers == 0 && numFrameBuffers == 0 &&
+ memTextures == 0 && memIndexBuffers == 0 && memVertexBuffers == 0;
+}
+
+} // namespace gfx
+} // namespace mbgl \ No newline at end of file
diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp
index 18b376e3dc..e2bcc7fadc 100644
--- a/src/mbgl/gl/context.cpp
+++ b/src/mbgl/gl/context.cpp
@@ -54,13 +54,15 @@ Context::Context(RendererBackend& backend_)
GLint value;
MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
return value;
- }()), backend(backend_) {
-}
+ }()),
+ backend(backend_),
+ stats() {}
Context::~Context() {
if (cleanupOnDestruction) {
reset();
}
+ assert(stats.isZero());
}
void Context::initializeExtensions(const std::function<gl::ProcAddress(const char*)>& getProcAddress) {
@@ -206,10 +208,12 @@ UniqueTexture Context::createUniqueTexture() {
if (pooledTextures.empty()) {
pooledTextures.resize(TextureMax);
MBGL_CHECK_ERROR(glGenTextures(TextureMax, pooledTextures.data()));
+ stats.numCreatedTextures += TextureMax;
}
TextureID id = pooledTextures.back();
pooledTextures.pop_back();
+ stats.numActiveTextures++;
// NOLINTNEXTLINE(performance-move-const-arg)
return UniqueTexture{std::move(id), {this}};
}
@@ -238,6 +242,7 @@ VertexArray Context::createVertexArray() {
UniqueFramebuffer Context::createFramebuffer() {
FramebufferID id = 0;
MBGL_CHECK_ERROR(glGenFramebuffers(1, &id));
+ stats.numFrameBuffers++;
// NOLINTNEXTLINE(performance-move-const-arg)
return UniqueFramebuffer{ std::move(id), { this } };
}
@@ -245,8 +250,10 @@ UniqueFramebuffer Context::createFramebuffer() {
std::unique_ptr<gfx::TextureResource> Context::createTextureResource(
const Size size, const gfx::TexturePixelType format, const gfx::TextureChannelDataType type) {
auto obj = createUniqueTexture();
+ int textureByteSize = gl::TextureResource::getStorageSize(size, format, type);
+ stats.memTextures += textureByteSize;
std::unique_ptr<gfx::TextureResource> resource =
- std::make_unique<gl::TextureResource>(std::move(obj));
+ std::make_unique<gl::TextureResource>(std::move(obj), textureByteSize);
// Always use texture unit 0 for manipulating it.
activeTextureUnit = 0;
@@ -517,6 +524,8 @@ void Context::clear(optional<mbgl::Color> color,
}
MBGL_CHECK_ERROR(glClear(mask));
+
+ stats.numDrawCalls = 0;
}
void Context::setCullFaceMode(const gfx::CullFaceMode& mode) {
@@ -583,6 +592,18 @@ std::unique_ptr<gfx::CommandEncoder> Context::createCommandEncoder() {
return std::make_unique<gl::CommandEncoder>(*this);
}
+gfx::RenderingStats& Context::renderingStats() {
+ return stats;
+}
+
+const gfx::RenderingStats& Context::renderingStats() const {
+ return stats;
+}
+
+void Context::finish() {
+ MBGL_CHECK_ERROR(glFinish());
+}
+
void Context::draw(const gfx::DrawMode& drawMode,
std::size_t indexOffset,
std::size_t indexLength) {
@@ -607,6 +628,8 @@ void Context::draw(const gfx::DrawMode& drawMode,
static_cast<GLsizei>(indexLength),
GL_UNSIGNED_SHORT,
reinterpret_cast<GLvoid*>(sizeof(uint16_t) * indexOffset)));
+
+ stats.numDrawCalls++;
}
void Context::performCleanup() {
@@ -643,6 +666,7 @@ void Context::performCleanup() {
}
}
MBGL_CHECK_ERROR(glDeleteBuffers(int(abandonedBuffers.size()), abandonedBuffers.data()));
+ stats.numBuffers -= int(abandonedBuffers.size());
abandonedBuffers.clear();
}
@@ -655,6 +679,8 @@ void Context::performCleanup() {
}
}
MBGL_CHECK_ERROR(glDeleteTextures(int(abandonedTextures.size()), abandonedTextures.data()));
+ stats.numCreatedTextures -= int(abandonedTextures.size());
+ assert(stats.numCreatedTextures >= 0);
abandonedTextures.clear();
}
@@ -678,6 +704,8 @@ void Context::performCleanup() {
}
MBGL_CHECK_ERROR(
glDeleteFramebuffers(int(abandonedFramebuffers.size()), abandonedFramebuffers.data()));
+ stats.numFrameBuffers -= int(abandonedFramebuffers.size());
+ assert(stats.numFrameBuffers >= 0);
abandonedFramebuffers.clear();
}
diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp
index 70f12e5a8d..b0d043ff9f 100644
--- a/src/mbgl/gl/context.hpp
+++ b/src/mbgl/gl/context.hpp
@@ -43,6 +43,9 @@ public:
std::unique_ptr<gfx::CommandEncoder> createCommandEncoder() override;
+ gfx::RenderingStats& renderingStats();
+ const gfx::RenderingStats& renderingStats() const override;
+
void initializeExtensions(const std::function<gl::ProcAddress(const char*)>&);
void enableDebugging();
@@ -92,6 +95,8 @@ public:
std::size_t indexOffset,
std::size_t indexLength);
+ void finish();
+
// Actually remove the objects we marked as abandoned with the above methods.
// Only call this while the OpenGL context is exclusive to this thread.
void performCleanup() override;
@@ -130,6 +135,7 @@ private:
RendererBackend& backend;
bool cleanupOnDestruction = true;
+ gfx::RenderingStats stats;
std::unique_ptr<extension::Debugging> debugging;
std::unique_ptr<extension::VertexArray> vertexArray;
diff --git a/src/mbgl/gl/index_buffer_resource.cpp b/src/mbgl/gl/index_buffer_resource.cpp
new file mode 100644
index 0000000000..2ef178846b
--- /dev/null
+++ b/src/mbgl/gl/index_buffer_resource.cpp
@@ -0,0 +1,14 @@
+#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/index_buffer_resource.hpp>
+
+namespace mbgl {
+namespace gl {
+
+IndexBufferResource::~IndexBufferResource() {
+ auto& stats = buffer.get_deleter().context.renderingStats();
+ stats.memIndexBuffers -= byteSize;
+ assert(stats.memIndexBuffers >= 0);
+}
+
+} // namespace gl
+} // namespace mbgl \ No newline at end of file
diff --git a/src/mbgl/gl/index_buffer_resource.hpp b/src/mbgl/gl/index_buffer_resource.hpp
index 2da25fdb96..00c66be5b5 100644
--- a/src/mbgl/gl/index_buffer_resource.hpp
+++ b/src/mbgl/gl/index_buffer_resource.hpp
@@ -8,10 +8,11 @@ namespace gl {
class IndexBufferResource : public gfx::IndexBufferResource {
public:
- IndexBufferResource(UniqueBuffer&& buffer_) : buffer(std::move(buffer_)) {
- }
+ IndexBufferResource(UniqueBuffer&& buffer_, int byteSize_) : buffer(std::move(buffer_)), byteSize(byteSize_) {}
+ ~IndexBufferResource();
UniqueBuffer buffer;
+ int byteSize;
};
} // namespace gl
diff --git a/src/mbgl/gl/object.cpp b/src/mbgl/gl/object.cpp
index ec2998a27d..c075aa8f13 100644
--- a/src/mbgl/gl/object.cpp
+++ b/src/mbgl/gl/object.cpp
@@ -28,6 +28,8 @@ void TextureDeleter::operator()(TextureID id) const {
} else {
context->pooledTextures.push_back(id);
}
+ context->renderingStats().numActiveTextures--;
+ assert(context->renderingStats().numActiveTextures >= 0);
}
void VertexArrayDeleter::operator()(VertexArrayID id) const {
diff --git a/src/mbgl/gl/texture_resource.cpp b/src/mbgl/gl/texture_resource.cpp
new file mode 100644
index 0000000000..b9bf620eea
--- /dev/null
+++ b/src/mbgl/gl/texture_resource.cpp
@@ -0,0 +1,45 @@
+#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/texture_resource.hpp>
+
+namespace mbgl {
+namespace gl {
+
+static int channelCount(gfx::TexturePixelType format) {
+ switch (format) {
+ case gfx::TexturePixelType::Alpha:
+ case gfx::TexturePixelType::Depth:
+ case gfx::TexturePixelType::Luminance:
+ case gfx::TexturePixelType::Stencil:
+ return 1;
+ case gfx::TexturePixelType::RGBA:
+ return 4;
+ default:
+ assert(!"Unknown texture pixel type");
+ return 0;
+ }
+}
+
+static int channelStorageSize(gfx::TextureChannelDataType type) {
+ switch (type) {
+ case gfx::TextureChannelDataType::HalfFloat:
+ return 2;
+ case gfx::TextureChannelDataType::UnsignedByte:
+ return 1;
+ default:
+ assert(!"Unknown texture channel data type");
+ return 0;
+ }
+}
+
+TextureResource::~TextureResource() {
+ auto& stats = texture.get_deleter().context->renderingStats();
+ stats.memTextures -= byteSize;
+ assert(stats.memTextures >= 0);
+}
+
+int TextureResource::getStorageSize(const Size& size, gfx::TexturePixelType format, gfx::TextureChannelDataType type) {
+ return size.width * size.height * channelCount(format) * channelStorageSize(type);
+}
+
+} // namespace gl
+} // namespace mbgl \ No newline at end of file
diff --git a/src/mbgl/gl/texture_resource.hpp b/src/mbgl/gl/texture_resource.hpp
index ed742e75b7..494e5ae8a3 100644
--- a/src/mbgl/gl/texture_resource.hpp
+++ b/src/mbgl/gl/texture_resource.hpp
@@ -8,14 +8,17 @@ namespace gl {
class TextureResource : public gfx::TextureResource {
public:
- TextureResource(UniqueTexture&& texture_) : texture(std::move(texture_)) {
- }
+ TextureResource(UniqueTexture&& texture_, int byteSize_) : texture(std::move(texture_)), byteSize(byteSize_) {}
+ ~TextureResource();
+
+ static int getStorageSize(const Size& size, gfx::TexturePixelType format, gfx::TextureChannelDataType type);
UniqueTexture texture;
gfx::TextureFilterType filter = gfx::TextureFilterType::Nearest;
gfx::TextureMipMapType mipmap = gfx::TextureMipMapType::No;
gfx::TextureWrapType wrapX = gfx::TextureWrapType::Clamp;
gfx::TextureWrapType wrapY = gfx::TextureWrapType::Clamp;
+ int byteSize;
};
} // namespace gl
diff --git a/src/mbgl/gl/upload_pass.cpp b/src/mbgl/gl/upload_pass.cpp
index 4312488fb4..962bc72239 100644
--- a/src/mbgl/gl/upload_pass.cpp
+++ b/src/mbgl/gl/upload_pass.cpp
@@ -20,12 +20,14 @@ std::unique_ptr<gfx::VertexBufferResource> UploadPass::createVertexBufferResourc
const void* data, std::size_t size, const gfx::BufferUsageType usage) {
BufferID id = 0;
MBGL_CHECK_ERROR(glGenBuffers(1, &id));
+ commandEncoder.context.renderingStats().numBuffers++;
+ commandEncoder.context.renderingStats().memVertexBuffers += size;
// NOLINTNEXTLINE(performance-move-const-arg)
UniqueBuffer result{ std::move(id), { commandEncoder.context } };
commandEncoder.context.vertexBuffer = result;
MBGL_CHECK_ERROR(
glBufferData(GL_ARRAY_BUFFER, size, data, Enum<gfx::BufferUsageType>::to(usage)));
- return std::make_unique<gl::VertexBufferResource>(std::move(result));
+ return std::make_unique<gl::VertexBufferResource>(std::move(result), size);
}
void UploadPass::updateVertexBufferResource(gfx::VertexBufferResource& resource,
@@ -39,13 +41,15 @@ std::unique_ptr<gfx::IndexBufferResource> UploadPass::createIndexBufferResource(
const void* data, std::size_t size, const gfx::BufferUsageType usage) {
BufferID id = 0;
MBGL_CHECK_ERROR(glGenBuffers(1, &id));
+ commandEncoder.context.renderingStats().numBuffers++;
+ commandEncoder.context.renderingStats().memIndexBuffers += size;
// NOLINTNEXTLINE(performance-move-const-arg)
UniqueBuffer result{ std::move(id), { commandEncoder.context } };
commandEncoder.context.bindVertexArray = 0;
commandEncoder.context.globalVertexArrayState.indexBuffer = result;
MBGL_CHECK_ERROR(
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, Enum<gfx::BufferUsageType>::to(usage)));
- return std::make_unique<gl::IndexBufferResource>(std::move(result));
+ return std::make_unique<gl::IndexBufferResource>(std::move(result), size);
}
void UploadPass::updateIndexBufferResource(gfx::IndexBufferResource& resource,
@@ -65,8 +69,10 @@ UploadPass::createTextureResource(const Size size,
gfx::TexturePixelType format,
gfx::TextureChannelDataType type) {
auto obj = commandEncoder.context.createUniqueTexture();
+ int textureByteSize = gl::TextureResource::getStorageSize(size, format, type);
+ commandEncoder.context.renderingStats().memTextures += textureByteSize;
std::unique_ptr<gfx::TextureResource> resource =
- std::make_unique<gl::TextureResource>(std::move(obj));
+ std::make_unique<gl::TextureResource>(std::move(obj), textureByteSize);
commandEncoder.context.pixelStoreUnpack = { 1 };
updateTextureResource(*resource, size, data, format, type);
// We are using clamp to edge here since OpenGL ES doesn't allow GL_REPEAT on NPOT textures.
diff --git a/src/mbgl/gl/vertex_buffer_resource.cpp b/src/mbgl/gl/vertex_buffer_resource.cpp
new file mode 100644
index 0000000000..cddbdd43d0
--- /dev/null
+++ b/src/mbgl/gl/vertex_buffer_resource.cpp
@@ -0,0 +1,14 @@
+#include <mbgl/gl/context.hpp>
+#include <mbgl/gl/vertex_buffer_resource.hpp>
+
+namespace mbgl {
+namespace gl {
+
+VertexBufferResource::~VertexBufferResource() {
+ auto& stats = buffer.get_deleter().context.renderingStats();
+ stats.memVertexBuffers -= byteSize;
+ assert(stats.memVertexBuffers >= 0);
+}
+
+} // namespace gl
+} // namespace mbgl \ No newline at end of file
diff --git a/src/mbgl/gl/vertex_buffer_resource.hpp b/src/mbgl/gl/vertex_buffer_resource.hpp
index 95e5e75d45..f9c599c757 100644
--- a/src/mbgl/gl/vertex_buffer_resource.hpp
+++ b/src/mbgl/gl/vertex_buffer_resource.hpp
@@ -8,10 +8,11 @@ namespace gl {
class VertexBufferResource : public gfx::VertexBufferResource {
public:
- VertexBufferResource(UniqueBuffer&& buffer_) : buffer(std::move(buffer_)) {
- }
+ VertexBufferResource(UniqueBuffer&& buffer_, int byteSize_) : buffer(std::move(buffer_)), byteSize(byteSize_) {}
+ ~VertexBufferResource();
UniqueBuffer buffer;
+ int byteSize;
};
} // namespace gl
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 81d1d9a5b6..d0227c36c5 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -121,7 +121,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
allowVerticalPlacement = allowVerticalPlacement || placementMode == style::TextWritingModeType::Vertical;
return !seen.insert(placementMode).second;
});
- modes.erase(end, modes.end());
+ modes.erase(end, modes.end());
placementModes = std::move(modes);
}
@@ -525,21 +525,22 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
const float textRepeatDistance = symbolSpacing / 2;
const auto evaluatedLayoutProperties = layout->evaluate(zoom, feature);
IndexedSubfeature indexedFeature(feature.index, sourceLayer->getName(), bucketLeaderID, symbolInstances.size());
- const bool hasIconTextFit = evaluatedLayoutProperties.get<style::IconTextFit>() != IconTextFitType::None;
+ const auto iconTextFit = evaluatedLayoutProperties.get<style::IconTextFit>();
// Adjust shaped icon size when icon-text-fit is used.
optional<PositionedIcon> verticallyShapedIcon;
- if (shapedIcon && hasIconTextFit) {
+ if (shapedIcon && iconTextFit != IconTextFitType::None) {
// Create vertically shaped icon for vertical writing mode if needed.
if (allowVerticalPlacement && shapedTextOrientations.vertical) {
verticallyShapedIcon = shapedIcon;
- verticallyShapedIcon->fitIconToText(evaluatedLayoutProperties,
- shapedTextOrientations.vertical,
- layoutTextSize);
+ verticallyShapedIcon->fitIconToText(
+ shapedTextOrientations.vertical, iconTextFit, layout->get<IconTextFitPadding>(), iconOffset, fontScale);
+ }
+ const auto shapedText = getDefaultHorizontalShaping(shapedTextOrientations);
+ if (shapedText) {
+ shapedIcon->fitIconToText(
+ shapedText, iconTextFit, layout->get<IconTextFitPadding>(), iconOffset, fontScale);
}
- shapedIcon->fitIconToText(evaluatedLayoutProperties,
- getDefaultHorizontalShaping(shapedTextOrientations),
- layoutTextSize);
}
auto addSymbolInstance = [&] (Anchor& anchor, std::shared_ptr<SymbolInstanceSharedData> sharedData) {
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp
index d001084f92..2ea753d8aa 100644
--- a/src/mbgl/renderer/image_manager.cpp
+++ b/src/mbgl/renderer/image_manager.cpp
@@ -138,8 +138,9 @@ void ImageManager::removeRequestor(ImageRequestor& requestor) {
void ImageManager::notifyIfMissingImageAdded() {
for (auto it = missingImageRequestors.begin(); it != missingImageRequestors.end();) {
- if (it->second.callbacks.empty()) {
- notify(*it->first, it->second.pair);
+ ImageRequestor& requestor = *it->first;
+ if (!requestor.hasPendingRequests()) {
+ notify(requestor, it->second);
it = missingImageRequestors.erase(it);
} else {
++it;
@@ -169,38 +170,56 @@ void ImageManager::reduceMemoryUseIfCacheSizeExceedsLimit() {
}
void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) {
- std::vector<std::string> missingImages;
- missingImages.reserve(pair.first.size());
+ ImageDependencies missingDependencies;
+
for (const auto& dependency : pair.first) {
if (images.find(dependency.first) == images.end()) {
- missingImages.push_back(dependency.first);
+ missingDependencies.emplace(dependency);
}
}
- if (!missingImages.empty()) {
+ if (!missingDependencies.empty()) {
ImageRequestor* requestorPtr = &requestor;
+ assert(!missingImageRequestors.count(requestorPtr));
+ missingImageRequestors.emplace(requestorPtr, pair);
- auto emplaced = missingImageRequestors.emplace(requestorPtr, MissingImageRequestPair { pair, {} });
- assert(emplaced.second);
-
- for (const auto& missingImage : missingImages) {
+ for (const auto& dependency : missingDependencies) {
+ const std::string& missingImage = dependency.first;
assert(observer != nullptr);
- requestedImages[missingImage].emplace(&requestor);
- auto callback = std::make_unique<ActorCallback>(
- *Scheduler::GetCurrent(),
- [this, requestorPtr, missingImage] {
- auto requestorIt = missingImageRequestors.find(requestorPtr);
- if (requestorIt != missingImageRequestors.end()) {
- assert(requestorIt->second.callbacks.find(missingImage) != requestorIt->second.callbacks.end());
- requestorIt->second.callbacks.erase(missingImage);
- }
- });
-
- auto actorRef = callback->self();
- emplaced.first->second.callbacks.emplace(missingImage, std::move(callback));
- observer->onStyleImageMissing(missingImage, [actorRef] {
- actorRef.invoke(&Callback::operator());
- });
+
+ auto existingRequestorsIt = requestedImages.find(missingImage);
+ if (existingRequestorsIt != requestedImages.end()) { // Already asked client about this image.
+ std::set<ImageRequestor*>& existingRequestors = existingRequestorsIt->second;
+ // existingRequestors is empty if all the previous requestors are deleted.
+ if (!existingRequestors.empty() &&
+ (*existingRequestors.begin())
+ ->hasPendingRequest(missingImage)) { // Still waiting for the client response for this image.
+ requestorPtr->addPendingRequest(missingImage);
+ existingRequestors.emplace(requestorPtr);
+ continue;
+ }
+ // The request for this image has been already delivered
+ // to the client, so we do not treat it as pending.
+ existingRequestors.emplace(requestorPtr);
+ // TODO: we could `continue;` here, but we need to call `observer->onStyleImageMissing`,
+ // so that rendering is re-launched from the handler at Map::Impl.
+ } else {
+ requestedImages[missingImage].emplace(requestorPtr);
+ requestor.addPendingRequest(missingImage);
+ }
+
+ auto removePendingRequests = [this, missingImage] {
+ auto existingRequest = requestedImages.find(missingImage);
+ if (existingRequest == requestedImages.end()) {
+ return;
+ }
+
+ for (auto* req : existingRequest->second) {
+ req->removePendingRequest(missingImage);
+ }
+ };
+ observer->onStyleImageMissing(missingImage,
+ Scheduler::GetCurrent()->bindOnce(std::move(removePendingRequests)));
}
} else {
// Associate requestor with an image that was provided by the client.
@@ -230,7 +249,7 @@ void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pai
}
}
- requestor.onImagesAvailable(iconMap, patternMap, std::move(versionMap), pair.second);
+ requestor.onImagesAvailable(std::move(iconMap), std::move(patternMap), std::move(versionMap), pair.second);
}
void ImageManager::dumpDebugLogs() const {
diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp
index 9097418681..5ed6e237f0 100644
--- a/src/mbgl/renderer/image_manager.hpp
+++ b/src/mbgl/renderer/image_manager.hpp
@@ -58,13 +58,7 @@ private:
bool loaded = false;
std::map<ImageRequestor*, ImageRequestPair> requestors;
- using Callback = std::function<void()>;
- using ActorCallback = Actor<Callback>;
- struct MissingImageRequestPair {
- ImageRequestPair pair;
- std::map<std::string, std::unique_ptr<ActorCallback>> callbacks;
- };
- std::map<ImageRequestor*, MissingImageRequestPair> missingImageRequestors;
+ std::map<ImageRequestor*, ImageRequestPair> missingImageRequestors;
std::map<std::string, std::set<ImageRequestor*>> requestedImages;
std::size_t requestedImagesCacheSize = 0ul;
ImageMap images;
@@ -77,8 +71,17 @@ public:
explicit ImageRequestor(ImageManager&);
virtual ~ImageRequestor();
virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, ImageVersionMap versionMap, uint64_t imageCorrelationID) = 0;
+
+ void addPendingRequest(const std::string& imageId) { pendingRequests.insert(imageId); }
+ bool hasPendingRequest(const std::string& imageId) const { return pendingRequests.count(imageId); }
+ bool hasPendingRequests() const { return !pendingRequests.empty(); }
+ void removePendingRequest(const std::string& imageId) { pendingRequests.erase(imageId); }
+
private:
ImageManager& imageManager;
+
+ // Pending requests are image requests that are waiting to be dispatched to the client.
+ std::set<std::string> pendingRequests;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index 36665c1db4..e5bbe74bf9 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -78,8 +78,8 @@ void RenderLineLayer::prepare(const LayerPrepareParameters& params) {
const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round
? LinePatternCap::Round : LinePatternCap::Square;
// Ensures that the dash data gets added to the atlas.
- params.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().from, cap);
- params.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().to, cap);
+ params.lineAtlas.getDashPatternTexture(
+ evaluated.get<LineDasharray>().from, evaluated.get<LineDasharray>().to, cap);
}
}
@@ -146,27 +146,26 @@ void RenderLineLayer::render(PaintParameters& parameters) {
};
if (!evaluated.get<LineDasharray>().from.empty()) {
- const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round
- ? LinePatternCap::Round : LinePatternCap::Square;
- LinePatternPos posA = parameters.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().from, cap);
- LinePatternPos posB = parameters.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().to, cap);
+ const LinePatternCap cap =
+ bucket.layout.get<LineCap>() == LineCapType::Round ? LinePatternCap::Round : LinePatternCap::Square;
+ const auto& dashPatternTexture = parameters.lineAtlas.getDashPatternTexture(
+ evaluated.get<LineDasharray>().from, evaluated.get<LineDasharray>().to, cap);
draw(parameters.programs.getLineLayerPrograms().lineSDF,
- LineSDFProgram::layoutUniformValues(
- evaluated,
- parameters.pixelRatio,
- tile,
- parameters.state,
- parameters.pixelsToGLUnits,
- posA,
- posB,
- crossfade,
- parameters.lineAtlas.getSize().width),
- {},
- {},
- LineSDFProgram::TextureBindings{
- parameters.lineAtlas.textureBinding(),
- });
+ LineSDFProgram::layoutUniformValues(evaluated,
+ parameters.pixelRatio,
+ tile,
+ parameters.state,
+ parameters.pixelsToGLUnits,
+ dashPatternTexture.getFrom(),
+ dashPatternTexture.getTo(),
+ crossfade,
+ dashPatternTexture.getSize().width),
+ {},
+ {},
+ LineSDFProgram::TextureBindings{
+ dashPatternTexture.textureBinding(),
+ });
} else if (!unevaluated.get<LinePattern>().isUndefined()) {
const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""});
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index 1a36f8a2e5..db9f61411a 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -370,11 +370,10 @@ public:
}
std::tuple<float> interpolationFactor(float currentZoom) const override {
- if (expression.useIntegerZoom) {
- return std::tuple<float> { expression.interpolationFactor(zoomRange, std::floor(currentZoom)) };
- } else {
- return std::tuple<float> { expression.interpolationFactor(zoomRange, currentZoom) };
- }
+ const float possiblyRoundedZoom = expression.useIntegerZoom ? std::floor(currentZoom) : currentZoom;
+
+ return std::tuple<float>{
+ ::fmax(0.0, ::fmin(1.0, expression.interpolationFactor(zoomRange, possiblyRoundedZoom)))};
}
std::tuple<T> uniformValue(const PossiblyEvaluatedPropertyValue<T>& currentValue) const override {
diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp
index 28f6ab3199..e13a439ae4 100644
--- a/src/mbgl/renderer/render_orchestrator.cpp
+++ b/src/mbgl/renderer/render_orchestrator.cpp
@@ -103,19 +103,17 @@ public:
} // namespace
-RenderOrchestrator::RenderOrchestrator(
- bool backgroundLayerAsColor_,
- optional<std::string> localFontFamily_)
- : observer(&nullObserver())
- , glyphManager(std::make_unique<GlyphManager>(std::make_unique<LocalGlyphRasterizer>(std::move(localFontFamily_))))
- , imageManager(std::make_unique<ImageManager>())
- , lineAtlas(std::make_unique<LineAtlas>(Size{ 256, 512 }))
- , patternAtlas(std::make_unique<PatternAtlas>())
- , imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>())
- , sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>())
- , layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>())
- , renderLight(makeMutable<Light::Impl>())
- , backgroundLayerAsColor(backgroundLayerAsColor_) {
+RenderOrchestrator::RenderOrchestrator(bool backgroundLayerAsColor_, optional<std::string> localFontFamily_)
+ : observer(&nullObserver()),
+ glyphManager(std::make_unique<GlyphManager>(std::make_unique<LocalGlyphRasterizer>(std::move(localFontFamily_)))),
+ imageManager(std::make_unique<ImageManager>()),
+ lineAtlas(std::make_unique<LineAtlas>()),
+ patternAtlas(std::make_unique<PatternAtlas>()),
+ imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>()),
+ sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>()),
+ layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>()),
+ renderLight(makeMutable<Light::Impl>()),
+ backgroundLayerAsColor(backgroundLayerAsColor_) {
glyphManager->setObserver(this);
imageManager->setObserver(this);
}
@@ -220,6 +218,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
const LayerDifference layerDiff = diffLayers(layerImpls, updateParameters.layers);
layerImpls = updateParameters.layers;
+ const bool layersAddedOrRemoved = !layerDiff.added.empty() || !layerDiff.removed.empty();
// Remove render layers for removed layers.
for (const auto& entry : layerDiff.removed) {
@@ -238,20 +237,31 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
renderLayers.at(entry.first)->transition(transitionParameters, entry.second.after);
}
- if (!layerDiff.removed.empty() || !layerDiff.added.empty() || !layerDiff.changed.empty()) {
- glyphManager->evict(fontStacks(*updateParameters.layers));
+ if (layersAddedOrRemoved) {
+ orderedLayers.clear();
+ orderedLayers.reserve(layerImpls->size());
+ for (const auto& layerImpl : *layerImpls) {
+ RenderLayer* layer = renderLayers.at(layerImpl->id).get();
+ assert(layer);
+ orderedLayers.emplace_back(*layer);
+ }
+ }
+ assert(orderedLayers.size() == renderLayers.size());
+
+ if (layersAddedOrRemoved || !layerDiff.changed.empty()) {
+ glyphManager->evict(fontStacks(*layerImpls));
}
// Update layers for class and zoom changes.
std::unordered_set<std::string> constantsMaskChanged;
- for (const auto& entry : renderLayers) {
- RenderLayer& layer = *entry.second;
- const bool layerAddedOrChanged = layerDiff.added.count(entry.first) || layerDiff.changed.count(entry.first);
+ for (RenderLayer& layer : orderedLayers) {
+ const std::string& id = layer.getID();
+ const bool layerAddedOrChanged = layerDiff.added.count(id) || layerDiff.changed.count(id);
if (layerAddedOrChanged || zoomChanged || layer.hasTransition() || layer.hasCrossfade()) {
auto previousMask = layer.evaluatedProperties->constantsMask();
layer.evaluate(evaluationParameters);
if (previousMask != layer.evaluatedProperties->constantsMask()) {
- constantsMaskChanged.insert(layer.getID());
+ constantsMaskChanged.insert(id);
}
}
}
@@ -281,7 +291,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
renderLight.getEvaluated());
std::set<LayerRenderItem> layerRenderItems;
- std::vector<std::reference_wrapper<RenderLayer>> layersNeedPlacement;
+ layersNeedPlacement.clear();
auto renderItemsEmplaceHint = layerRenderItems.begin();
// Reserve size for filteredLayersForSource if there are sources.
@@ -293,27 +303,26 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
for (const auto& sourceImpl : *sourceImpls) {
RenderSource* source = renderSources.at(sourceImpl->id).get();
bool sourceNeedsRendering = false;
- bool sourceNeedsRelayout = false;
-
- uint32_t index = 0u;
- const auto begin = layerImpls->begin();
- const auto end = layerImpls->end();
- for (auto it = begin; it != end; ++it, ++index) {
- const Immutable<Layer::Impl>& layerImpl = *it;
- RenderLayer* layer = getRenderLayer(layerImpl->id);
- const auto* layerInfo = layerImpl->getTypeInfo();
- const bool layerIsVisible = layer->baseImpl->visibility != style::VisibilityType::None;
- const bool zoomFitsLayer = layer->supportsZoom(zoomHistory.lastZoom);
+ bool sourceNeedsRelayout = false;
+
+ for (uint32_t index = 0u; index < orderedLayers.size(); ++index) {
+ RenderLayer& layer = orderedLayers[index];
+ const auto* layerInfo = layer.baseImpl->getTypeInfo();
+ const bool layerIsVisible = layer.baseImpl->visibility != style::VisibilityType::None;
+ const bool zoomFitsLayer = layer.supportsZoom(zoomHistory.lastZoom);
renderTreeParameters->has3D |= (layerInfo->pass3d == LayerTypeInfo::Pass3D::Required);
if (layerInfo->source != LayerTypeInfo::Source::NotRequired) {
- if (layerImpl->source == sourceImpl->id) {
- sourceNeedsRelayout = (sourceNeedsRelayout || hasImageDiff || constantsMaskChanged.count(layerImpl->id) || hasLayoutDifference(layerDiff, layerImpl->id));
+ if (layer.baseImpl->source == sourceImpl->id) {
+ const std::string& layerId = layer.getID();
+ sourceNeedsRelayout = (sourceNeedsRelayout || hasImageDiff || constantsMaskChanged.count(layerId) ||
+ hasLayoutDifference(layerDiff, layerId));
if (layerIsVisible) {
- filteredLayersForSource.push_back(layer->evaluatedProperties);
+ filteredLayersForSource.push_back(layer.evaluatedProperties);
if (zoomFitsLayer) {
sourceNeedsRendering = true;
- renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, *layer, source, index);
+ renderItemsEmplaceHint =
+ layerRenderItems.emplace_hint(renderItemsEmplaceHint, layer, source, index);
}
}
}
@@ -322,14 +331,14 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(const UpdatePar
// Handle layers without source.
if (layerIsVisible && zoomFitsLayer && sourceImpl.get() == sourceImpls->at(0).get()) {
- if (backgroundLayerAsColor && layerImpl.get() == layerImpls->at(0).get()) {
- const auto& solidBackground = layer->getSolidBackground();
+ if (backgroundLayerAsColor && layer.baseImpl == layerImpls->front()) {
+ const auto& solidBackground = layer.getSolidBackground();
if (solidBackground) {
renderTreeParameters->backgroundColor = *solidBackground;
continue; // This layer is shown with background color, and it shall not be added to render items.
}
}
- renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, *layer, nullptr, index);
+ renderItemsEmplaceHint = layerRenderItems.emplace_hint(renderItemsEmplaceHint, layer, nullptr, index);
}
}
source->update(sourceImpl,
diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp
index 9b63498a2a..c2b44c2792 100644
--- a/src/mbgl/renderer/render_orchestrator.hpp
+++ b/src/mbgl/renderer/render_orchestrator.hpp
@@ -127,9 +127,11 @@ private:
const bool backgroundLayerAsColor;
bool contextLost = false;
- // Vector with reserved capacity of layerImpls->size() to avoid reallocation
+ // Vectors with reserved capacity of layerImpls->size() to avoid reallocation
// on each frame.
std::vector<Immutable<style::LayerProperties>> filteredLayersForSource;
+ std::vector<std::reference_wrapper<RenderLayer>> orderedLayers;
+ std::vector<std::reference_wrapper<RenderLayer>> layersNeedPlacement;
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp
index 2bf6e2e1a9..586d3b5a8a 100644
--- a/src/mbgl/renderer/tile_pyramid.cpp
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -68,6 +68,10 @@ void TilePyramid::update(const std::vector<Immutable<style::LayerProperties>>& l
if (!needsRendering) {
if (!needsRelayout) {
for (auto& entry : tiles) {
+ // These tiles are invisible, we set optional necessity
+ // for them and thus suppress network requests on
+ // tiles expiration (see `OnlineFileRequest`).
+ entry.second->setNecessity(TileNecessity::Optional);
cache.add(entry.first, std::move(entry.second));
}
}
diff --git a/src/mbgl/style/expression/assertion.cpp b/src/mbgl/style/expression/assertion.cpp
index 8e5a8b555d..17f8925511 100644
--- a/src/mbgl/style/expression/assertion.cpp
+++ b/src/mbgl/style/expression/assertion.cpp
@@ -16,12 +16,12 @@ Assertion::Assertion(type::Type type_, std::vector<std::unique_ptr<Expression>>
}
ParseResult Assertion::parse(const Convertible& value, ParsingContext& ctx) {
- static std::unordered_map<std::string, type::Type> types {
+ static std::unordered_map<std::string, type::Type> types{
{"string", type::String},
+ {"image", type::String}, // TODO: replace once we implement image expressions
{"number", type::Number},
{"boolean", type::Boolean},
- {"object", type::Object}
- };
+ {"object", type::Object}};
std::size_t length = arrayLength(value);
diff --git a/src/mbgl/style/expression/collator.cpp b/src/mbgl/style/expression/collator.cpp
new file mode 100644
index 0000000000..185d713150
--- /dev/null
+++ b/src/mbgl/style/expression/collator.cpp
@@ -0,0 +1,24 @@
+#include <mbgl/style/expression/collator.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+Collator::Collator(bool caseSensitive, bool diacriticSensitive, optional<std::string> locale)
+ : collator(platform::Collator(caseSensitive, diacriticSensitive, std::move(locale))) {}
+
+bool Collator::operator==(const Collator& other) const {
+ return collator == other.collator;
+}
+
+int Collator::compare(const std::string& lhs, const std::string& rhs) const {
+ return collator.compare(lhs, rhs);
+}
+
+std::string Collator::resolvedLocale() const {
+ return collator.resolvedLocale();
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/formatted.cpp b/src/mbgl/style/expression/formatted.cpp
index 5d45806ecb..4591a50ed1 100644
--- a/src/mbgl/style/expression/formatted.cpp
+++ b/src/mbgl/style/expression/formatted.cpp
@@ -35,6 +35,35 @@ std::string Formatted::toString() const {
return result;
}
+mbgl::Value Formatted::toObject() const {
+ mapbox::base::ValueObject result;
+ mapbox::base::ValueArray sectionValues;
+ sectionValues.reserve(sections.size());
+ for (const auto& section : sections) {
+ mapbox::base::ValueObject serializedSection;
+ serializedSection.emplace("text", section.text);
+ if (section.fontScale) {
+ serializedSection.emplace("scale", *section.fontScale);
+ } else {
+ serializedSection.emplace("scale", NullValue());
+ }
+ if (section.fontStack) {
+ std::string fontStackString;
+ serializedSection.emplace("fontStack", fontStackToString(*section.fontStack));
+ } else {
+ serializedSection.emplace("fontStack", NullValue());
+ }
+ if (section.textColor) {
+ serializedSection.emplace("textColor", section.textColor->toObject());
+ } else {
+ serializedSection.emplace("textColor", NullValue());
+ }
+ sectionValues.emplace_back(serializedSection);
+ }
+ result.emplace("sections", std::move(sectionValues));
+ return result;
+}
+
} // namespace expression
namespace conversion {
diff --git a/src/mbgl/style/expression/number_format.cpp b/src/mbgl/style/expression/number_format.cpp
index e31a9ce398..c2de032ff4 100644
--- a/src/mbgl/style/expression/number_format.cpp
+++ b/src/mbgl/style/expression/number_format.cpp
@@ -1,6 +1,6 @@
-#include <mbgl/style/expression/number_format.hpp>
+#include <mbgl/i18n/number_format.hpp>
#include <mbgl/style/conversion_impl.hpp>
-#include <mbgl/util/platform.hpp>
+#include <mbgl/style/expression/number_format.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 6ce3a9bfaa..699190608b 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -100,38 +100,40 @@ ParseResult ParsingContext::parse(const Convertible& value, std::size_t index_,
}
using ParseFunction = ParseResult (*)(const conversion::Convertible&, ParsingContext&);
-MAPBOX_ETERNAL_CONSTEXPR const auto expressionRegistry = mapbox::eternal::hash_map<mapbox::eternal::string, ParseFunction>({
- {"==", parseComparison},
- {"!=", parseComparison},
- {">", parseComparison},
- {"<", parseComparison},
- {">=", parseComparison},
- {"<=", parseComparison},
- {"all", All::parse},
- {"any", Any::parse},
- {"array", Assertion::parse},
- {"at", At::parse},
- {"boolean", Assertion::parse},
- {"case", Case::parse},
- {"coalesce", Coalesce::parse},
- {"collator", CollatorExpression::parse},
- {"format", FormatExpression::parse},
- {"interpolate", parseInterpolate},
- {"length", Length::parse},
- {"let", Let::parse},
- {"literal", Literal::parse},
- {"match", parseMatch},
- {"number", Assertion::parse},
- {"number-format", NumberFormat::parse},
- {"object", Assertion::parse},
- {"step", Step::parse},
- {"string", Assertion::parse},
- {"to-boolean", Coercion::parse},
- {"to-color", Coercion::parse},
- {"to-number", Coercion::parse},
- {"to-string", Coercion::parse},
- {"var", Var::parse},
-});
+MAPBOX_ETERNAL_CONSTEXPR const auto expressionRegistry =
+ mapbox::eternal::hash_map<mapbox::eternal::string, ParseFunction>({
+ {"==", parseComparison},
+ {"!=", parseComparison},
+ {">", parseComparison},
+ {"<", parseComparison},
+ {">=", parseComparison},
+ {"<=", parseComparison},
+ {"all", All::parse},
+ {"any", Any::parse},
+ {"array", Assertion::parse},
+ {"at", At::parse},
+ {"boolean", Assertion::parse},
+ {"case", Case::parse},
+ {"coalesce", Coalesce::parse},
+ {"collator", CollatorExpression::parse},
+ {"format", FormatExpression::parse},
+ {"image", Assertion::parse}, // TODO: replace once we implement image expressions
+ {"interpolate", parseInterpolate},
+ {"length", Length::parse},
+ {"let", Let::parse},
+ {"literal", Literal::parse},
+ {"match", parseMatch},
+ {"number", Assertion::parse},
+ {"number-format", NumberFormat::parse},
+ {"object", Assertion::parse},
+ {"step", Step::parse},
+ {"string", Assertion::parse},
+ {"to-boolean", Coercion::parse},
+ {"to-color", Coercion::parse},
+ {"to-number", Coercion::parse},
+ {"to-string", Coercion::parse},
+ {"var", Var::parse},
+ });
bool isExpression(const std::string& name) {
return expressionRegistry.contains(name.c_str());
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
index 7a186a3354..9187784452 100644
--- a/src/mbgl/style/layers/background_layer.cpp
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/background_layer.hpp>
@@ -148,28 +146,37 @@ TransitionOptions BackgroundLayer::getBackgroundPatternTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ BackgroundColor,
+ BackgroundOpacity,
+ BackgroundPattern,
+ BackgroundColorTransition,
+ BackgroundOpacityTransition,
+ BackgroundPatternTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"background-color", toUint8(Property::BackgroundColor)},
+ {"background-opacity", toUint8(Property::BackgroundOpacity)},
+ {"background-pattern", toUint8(Property::BackgroundPattern)},
+ {"background-color-transition", toUint8(Property::BackgroundColorTransition)},
+ {"background-opacity-transition", toUint8(Property::BackgroundOpacityTransition)},
+ {"background-pattern-transition", toUint8(Property::BackgroundPatternTransition)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::BackgroundPatternTransition);
+} // namespace
+
optional<Error> BackgroundLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- BackgroundColor,
- BackgroundOpacity,
- BackgroundPattern,
- BackgroundColorTransition,
- BackgroundOpacityTransition,
- BackgroundPatternTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "background-color", mbgl::underlying_type(Property::BackgroundColor) },
- { "background-opacity", mbgl::underlying_type(Property::BackgroundOpacity) },
- { "background-pattern", mbgl::underlying_type(Property::BackgroundPattern) },
- { "background-color-transition", mbgl::underlying_type(Property::BackgroundColorTransition) },
- { "background-opacity-transition", mbgl::underlying_type(Property::BackgroundOpacityTransition) },
- { "background-pattern-transition", mbgl::underlying_type(Property::BackgroundPatternTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -217,24 +224,46 @@ optional<Error> BackgroundLayer::setPaintProperty(const std::string& name, const
if (!transition) {
return error;
}
-
+
if (property == Property::BackgroundColorTransition) {
setBackgroundColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::BackgroundOpacityTransition) {
setBackgroundOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::BackgroundPatternTransition) {
setBackgroundPatternTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty BackgroundLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::BackgroundColor:
+ return makeStyleProperty(getBackgroundColor());
+ case Property::BackgroundOpacity:
+ return makeStyleProperty(getBackgroundOpacity());
+ case Property::BackgroundPattern:
+ return makeStyleProperty(getBackgroundPattern());
+ case Property::BackgroundColorTransition:
+ return makeStyleProperty(getBackgroundColorTransition());
+ case Property::BackgroundOpacityTransition:
+ return makeStyleProperty(getBackgroundOpacityTransition());
+ case Property::BackgroundPatternTransition:
+ return makeStyleProperty(getBackgroundPatternTransition());
+ }
+ return {};
}
optional<Error> BackgroundLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -251,5 +280,3 @@ Mutable<Layer::Impl> BackgroundLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index 2f68bcccf3..145d76a9a8 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/circle_layer.hpp>
@@ -364,60 +362,69 @@ TransitionOptions CircleLayer::getCircleTranslateAnchorTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ CircleBlur,
+ CircleColor,
+ CircleOpacity,
+ CirclePitchAlignment,
+ CirclePitchScale,
+ CircleRadius,
+ CircleStrokeColor,
+ CircleStrokeOpacity,
+ CircleStrokeWidth,
+ CircleTranslate,
+ CircleTranslateAnchor,
+ CircleBlurTransition,
+ CircleColorTransition,
+ CircleOpacityTransition,
+ CirclePitchAlignmentTransition,
+ CirclePitchScaleTransition,
+ CircleRadiusTransition,
+ CircleStrokeColorTransition,
+ CircleStrokeOpacityTransition,
+ CircleStrokeWidthTransition,
+ CircleTranslateTransition,
+ CircleTranslateAnchorTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"circle-blur", toUint8(Property::CircleBlur)},
+ {"circle-color", toUint8(Property::CircleColor)},
+ {"circle-opacity", toUint8(Property::CircleOpacity)},
+ {"circle-pitch-alignment", toUint8(Property::CirclePitchAlignment)},
+ {"circle-pitch-scale", toUint8(Property::CirclePitchScale)},
+ {"circle-radius", toUint8(Property::CircleRadius)},
+ {"circle-stroke-color", toUint8(Property::CircleStrokeColor)},
+ {"circle-stroke-opacity", toUint8(Property::CircleStrokeOpacity)},
+ {"circle-stroke-width", toUint8(Property::CircleStrokeWidth)},
+ {"circle-translate", toUint8(Property::CircleTranslate)},
+ {"circle-translate-anchor", toUint8(Property::CircleTranslateAnchor)},
+ {"circle-blur-transition", toUint8(Property::CircleBlurTransition)},
+ {"circle-color-transition", toUint8(Property::CircleColorTransition)},
+ {"circle-opacity-transition", toUint8(Property::CircleOpacityTransition)},
+ {"circle-pitch-alignment-transition", toUint8(Property::CirclePitchAlignmentTransition)},
+ {"circle-pitch-scale-transition", toUint8(Property::CirclePitchScaleTransition)},
+ {"circle-radius-transition", toUint8(Property::CircleRadiusTransition)},
+ {"circle-stroke-color-transition", toUint8(Property::CircleStrokeColorTransition)},
+ {"circle-stroke-opacity-transition", toUint8(Property::CircleStrokeOpacityTransition)},
+ {"circle-stroke-width-transition", toUint8(Property::CircleStrokeWidthTransition)},
+ {"circle-translate-transition", toUint8(Property::CircleTranslateTransition)},
+ {"circle-translate-anchor-transition", toUint8(Property::CircleTranslateAnchorTransition)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::CircleTranslateAnchorTransition);
+} // namespace
+
optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- CircleBlur,
- CircleColor,
- CircleOpacity,
- CirclePitchAlignment,
- CirclePitchScale,
- CircleRadius,
- CircleStrokeColor,
- CircleStrokeOpacity,
- CircleStrokeWidth,
- CircleTranslate,
- CircleTranslateAnchor,
- CircleBlurTransition,
- CircleColorTransition,
- CircleOpacityTransition,
- CirclePitchAlignmentTransition,
- CirclePitchScaleTransition,
- CircleRadiusTransition,
- CircleStrokeColorTransition,
- CircleStrokeOpacityTransition,
- CircleStrokeWidthTransition,
- CircleTranslateTransition,
- CircleTranslateAnchorTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "circle-blur", mbgl::underlying_type(Property::CircleBlur) },
- { "circle-color", mbgl::underlying_type(Property::CircleColor) },
- { "circle-opacity", mbgl::underlying_type(Property::CircleOpacity) },
- { "circle-pitch-alignment", mbgl::underlying_type(Property::CirclePitchAlignment) },
- { "circle-pitch-scale", mbgl::underlying_type(Property::CirclePitchScale) },
- { "circle-radius", mbgl::underlying_type(Property::CircleRadius) },
- { "circle-stroke-color", mbgl::underlying_type(Property::CircleStrokeColor) },
- { "circle-stroke-opacity", mbgl::underlying_type(Property::CircleStrokeOpacity) },
- { "circle-stroke-width", mbgl::underlying_type(Property::CircleStrokeWidth) },
- { "circle-translate", mbgl::underlying_type(Property::CircleTranslate) },
- { "circle-translate-anchor", mbgl::underlying_type(Property::CircleTranslateAnchor) },
- { "circle-blur-transition", mbgl::underlying_type(Property::CircleBlurTransition) },
- { "circle-color-transition", mbgl::underlying_type(Property::CircleColorTransition) },
- { "circle-opacity-transition", mbgl::underlying_type(Property::CircleOpacityTransition) },
- { "circle-pitch-alignment-transition", mbgl::underlying_type(Property::CirclePitchAlignmentTransition) },
- { "circle-pitch-scale-transition", mbgl::underlying_type(Property::CirclePitchScaleTransition) },
- { "circle-radius-transition", mbgl::underlying_type(Property::CircleRadiusTransition) },
- { "circle-stroke-color-transition", mbgl::underlying_type(Property::CircleStrokeColorTransition) },
- { "circle-stroke-opacity-transition", mbgl::underlying_type(Property::CircleStrokeOpacityTransition) },
- { "circle-stroke-width-transition", mbgl::underlying_type(Property::CircleStrokeWidthTransition) },
- { "circle-translate-transition", mbgl::underlying_type(Property::CircleTranslateTransition) },
- { "circle-translate-anchor-transition", mbgl::underlying_type(Property::CircleTranslateAnchorTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -530,64 +537,118 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con
if (!transition) {
return error;
}
-
+
if (property == Property::CircleBlurTransition) {
setCircleBlurTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleColorTransition) {
setCircleColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleOpacityTransition) {
setCircleOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CirclePitchAlignmentTransition) {
setCirclePitchAlignmentTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CirclePitchScaleTransition) {
setCirclePitchScaleTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleRadiusTransition) {
setCircleRadiusTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleStrokeColorTransition) {
setCircleStrokeColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleStrokeOpacityTransition) {
setCircleStrokeOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleStrokeWidthTransition) {
setCircleStrokeWidthTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleTranslateTransition) {
setCircleTranslateTransition(*transition);
return nullopt;
}
-
+
if (property == Property::CircleTranslateAnchorTransition) {
setCircleTranslateAnchorTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty CircleLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::CircleBlur:
+ return makeStyleProperty(getCircleBlur());
+ case Property::CircleColor:
+ return makeStyleProperty(getCircleColor());
+ case Property::CircleOpacity:
+ return makeStyleProperty(getCircleOpacity());
+ case Property::CirclePitchAlignment:
+ return makeStyleProperty(getCirclePitchAlignment());
+ case Property::CirclePitchScale:
+ return makeStyleProperty(getCirclePitchScale());
+ case Property::CircleRadius:
+ return makeStyleProperty(getCircleRadius());
+ case Property::CircleStrokeColor:
+ return makeStyleProperty(getCircleStrokeColor());
+ case Property::CircleStrokeOpacity:
+ return makeStyleProperty(getCircleStrokeOpacity());
+ case Property::CircleStrokeWidth:
+ return makeStyleProperty(getCircleStrokeWidth());
+ case Property::CircleTranslate:
+ return makeStyleProperty(getCircleTranslate());
+ case Property::CircleTranslateAnchor:
+ return makeStyleProperty(getCircleTranslateAnchor());
+ case Property::CircleBlurTransition:
+ return makeStyleProperty(getCircleBlurTransition());
+ case Property::CircleColorTransition:
+ return makeStyleProperty(getCircleColorTransition());
+ case Property::CircleOpacityTransition:
+ return makeStyleProperty(getCircleOpacityTransition());
+ case Property::CirclePitchAlignmentTransition:
+ return makeStyleProperty(getCirclePitchAlignmentTransition());
+ case Property::CirclePitchScaleTransition:
+ return makeStyleProperty(getCirclePitchScaleTransition());
+ case Property::CircleRadiusTransition:
+ return makeStyleProperty(getCircleRadiusTransition());
+ case Property::CircleStrokeColorTransition:
+ return makeStyleProperty(getCircleStrokeColorTransition());
+ case Property::CircleStrokeOpacityTransition:
+ return makeStyleProperty(getCircleStrokeOpacityTransition());
+ case Property::CircleStrokeWidthTransition:
+ return makeStyleProperty(getCircleStrokeWidthTransition());
+ case Property::CircleTranslateTransition:
+ return makeStyleProperty(getCircleTranslateTransition());
+ case Property::CircleTranslateAnchorTransition:
+ return makeStyleProperty(getCircleTranslateAnchorTransition());
+ }
+ return {};
}
optional<Error> CircleLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -604,5 +665,3 @@ Mutable<Layer::Impl> CircleLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/custom_layer.cpp b/src/mbgl/style/layers/custom_layer.cpp
index 8b9e17ea25..e13cf0069a 100644
--- a/src/mbgl/style/layers/custom_layer.cpp
+++ b/src/mbgl/style/layers/custom_layer.cpp
@@ -47,6 +47,10 @@ optional<Error> CustomLayer::setLayoutProperty(const std::string&, const Convert
return Error { "layer doesn't support this property" };
}
+StyleProperty CustomLayer::getProperty(const std::string&) const {
+ return {};
+}
+
Mutable<Layer::Impl> CustomLayer::mutableBaseImpl() const {
return staticMutableCast<Layer::Impl>(mutableImpl());
}
diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp
index 2686f7d044..87e196926f 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer.cpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
@@ -283,48 +281,57 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionVerticalGradientTransition
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ FillExtrusionBase,
+ FillExtrusionColor,
+ FillExtrusionHeight,
+ FillExtrusionOpacity,
+ FillExtrusionPattern,
+ FillExtrusionTranslate,
+ FillExtrusionTranslateAnchor,
+ FillExtrusionVerticalGradient,
+ FillExtrusionBaseTransition,
+ FillExtrusionColorTransition,
+ FillExtrusionHeightTransition,
+ FillExtrusionOpacityTransition,
+ FillExtrusionPatternTransition,
+ FillExtrusionTranslateTransition,
+ FillExtrusionTranslateAnchorTransition,
+ FillExtrusionVerticalGradientTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"fill-extrusion-base", toUint8(Property::FillExtrusionBase)},
+ {"fill-extrusion-color", toUint8(Property::FillExtrusionColor)},
+ {"fill-extrusion-height", toUint8(Property::FillExtrusionHeight)},
+ {"fill-extrusion-opacity", toUint8(Property::FillExtrusionOpacity)},
+ {"fill-extrusion-pattern", toUint8(Property::FillExtrusionPattern)},
+ {"fill-extrusion-translate", toUint8(Property::FillExtrusionTranslate)},
+ {"fill-extrusion-translate-anchor", toUint8(Property::FillExtrusionTranslateAnchor)},
+ {"fill-extrusion-vertical-gradient", toUint8(Property::FillExtrusionVerticalGradient)},
+ {"fill-extrusion-base-transition", toUint8(Property::FillExtrusionBaseTransition)},
+ {"fill-extrusion-color-transition", toUint8(Property::FillExtrusionColorTransition)},
+ {"fill-extrusion-height-transition", toUint8(Property::FillExtrusionHeightTransition)},
+ {"fill-extrusion-opacity-transition", toUint8(Property::FillExtrusionOpacityTransition)},
+ {"fill-extrusion-pattern-transition", toUint8(Property::FillExtrusionPatternTransition)},
+ {"fill-extrusion-translate-transition", toUint8(Property::FillExtrusionTranslateTransition)},
+ {"fill-extrusion-translate-anchor-transition", toUint8(Property::FillExtrusionTranslateAnchorTransition)},
+ {"fill-extrusion-vertical-gradient-transition", toUint8(Property::FillExtrusionVerticalGradientTransition)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::FillExtrusionVerticalGradientTransition);
+} // namespace
+
optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- FillExtrusionBase,
- FillExtrusionColor,
- FillExtrusionHeight,
- FillExtrusionOpacity,
- FillExtrusionPattern,
- FillExtrusionTranslate,
- FillExtrusionTranslateAnchor,
- FillExtrusionVerticalGradient,
- FillExtrusionBaseTransition,
- FillExtrusionColorTransition,
- FillExtrusionHeightTransition,
- FillExtrusionOpacityTransition,
- FillExtrusionPatternTransition,
- FillExtrusionTranslateTransition,
- FillExtrusionTranslateAnchorTransition,
- FillExtrusionVerticalGradientTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "fill-extrusion-base", mbgl::underlying_type(Property::FillExtrusionBase) },
- { "fill-extrusion-color", mbgl::underlying_type(Property::FillExtrusionColor) },
- { "fill-extrusion-height", mbgl::underlying_type(Property::FillExtrusionHeight) },
- { "fill-extrusion-opacity", mbgl::underlying_type(Property::FillExtrusionOpacity) },
- { "fill-extrusion-pattern", mbgl::underlying_type(Property::FillExtrusionPattern) },
- { "fill-extrusion-translate", mbgl::underlying_type(Property::FillExtrusionTranslate) },
- { "fill-extrusion-translate-anchor", mbgl::underlying_type(Property::FillExtrusionTranslateAnchor) },
- { "fill-extrusion-vertical-gradient", mbgl::underlying_type(Property::FillExtrusionVerticalGradient) },
- { "fill-extrusion-base-transition", mbgl::underlying_type(Property::FillExtrusionBaseTransition) },
- { "fill-extrusion-color-transition", mbgl::underlying_type(Property::FillExtrusionColorTransition) },
- { "fill-extrusion-height-transition", mbgl::underlying_type(Property::FillExtrusionHeightTransition) },
- { "fill-extrusion-opacity-transition", mbgl::underlying_type(Property::FillExtrusionOpacityTransition) },
- { "fill-extrusion-pattern-transition", mbgl::underlying_type(Property::FillExtrusionPatternTransition) },
- { "fill-extrusion-translate-transition", mbgl::underlying_type(Property::FillExtrusionTranslateTransition) },
- { "fill-extrusion-translate-anchor-transition", mbgl::underlying_type(Property::FillExtrusionTranslateAnchorTransition) },
- { "fill-extrusion-vertical-gradient-transition", mbgl::underlying_type(Property::FillExtrusionVerticalGradientTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -427,49 +434,91 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co
if (!transition) {
return error;
}
-
+
if (property == Property::FillExtrusionBaseTransition) {
setFillExtrusionBaseTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillExtrusionColorTransition) {
setFillExtrusionColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillExtrusionHeightTransition) {
setFillExtrusionHeightTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillExtrusionOpacityTransition) {
setFillExtrusionOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillExtrusionPatternTransition) {
setFillExtrusionPatternTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillExtrusionTranslateTransition) {
setFillExtrusionTranslateTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillExtrusionTranslateAnchorTransition) {
setFillExtrusionTranslateAnchorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillExtrusionVerticalGradientTransition) {
setFillExtrusionVerticalGradientTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty FillExtrusionLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::FillExtrusionBase:
+ return makeStyleProperty(getFillExtrusionBase());
+ case Property::FillExtrusionColor:
+ return makeStyleProperty(getFillExtrusionColor());
+ case Property::FillExtrusionHeight:
+ return makeStyleProperty(getFillExtrusionHeight());
+ case Property::FillExtrusionOpacity:
+ return makeStyleProperty(getFillExtrusionOpacity());
+ case Property::FillExtrusionPattern:
+ return makeStyleProperty(getFillExtrusionPattern());
+ case Property::FillExtrusionTranslate:
+ return makeStyleProperty(getFillExtrusionTranslate());
+ case Property::FillExtrusionTranslateAnchor:
+ return makeStyleProperty(getFillExtrusionTranslateAnchor());
+ case Property::FillExtrusionVerticalGradient:
+ return makeStyleProperty(getFillExtrusionVerticalGradient());
+ case Property::FillExtrusionBaseTransition:
+ return makeStyleProperty(getFillExtrusionBaseTransition());
+ case Property::FillExtrusionColorTransition:
+ return makeStyleProperty(getFillExtrusionColorTransition());
+ case Property::FillExtrusionHeightTransition:
+ return makeStyleProperty(getFillExtrusionHeightTransition());
+ case Property::FillExtrusionOpacityTransition:
+ return makeStyleProperty(getFillExtrusionOpacityTransition());
+ case Property::FillExtrusionPatternTransition:
+ return makeStyleProperty(getFillExtrusionPatternTransition());
+ case Property::FillExtrusionTranslateTransition:
+ return makeStyleProperty(getFillExtrusionTranslateTransition());
+ case Property::FillExtrusionTranslateAnchorTransition:
+ return makeStyleProperty(getFillExtrusionTranslateAnchorTransition());
+ case Property::FillExtrusionVerticalGradientTransition:
+ return makeStyleProperty(getFillExtrusionVerticalGradientTransition());
+ }
+ return {};
}
optional<Error> FillExtrusionLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -486,5 +535,3 @@ Mutable<Layer::Impl> FillExtrusionLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
index 52f2b166b3..e3d6c6c708 100644
--- a/src/mbgl/style/layers/fill_layer.cpp
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/fill_layer.hpp>
@@ -256,44 +254,53 @@ TransitionOptions FillLayer::getFillTranslateAnchorTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ FillAntialias,
+ FillColor,
+ FillOpacity,
+ FillOutlineColor,
+ FillPattern,
+ FillTranslate,
+ FillTranslateAnchor,
+ FillAntialiasTransition,
+ FillColorTransition,
+ FillOpacityTransition,
+ FillOutlineColorTransition,
+ FillPatternTransition,
+ FillTranslateTransition,
+ FillTranslateAnchorTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"fill-antialias", toUint8(Property::FillAntialias)},
+ {"fill-color", toUint8(Property::FillColor)},
+ {"fill-opacity", toUint8(Property::FillOpacity)},
+ {"fill-outline-color", toUint8(Property::FillOutlineColor)},
+ {"fill-pattern", toUint8(Property::FillPattern)},
+ {"fill-translate", toUint8(Property::FillTranslate)},
+ {"fill-translate-anchor", toUint8(Property::FillTranslateAnchor)},
+ {"fill-antialias-transition", toUint8(Property::FillAntialiasTransition)},
+ {"fill-color-transition", toUint8(Property::FillColorTransition)},
+ {"fill-opacity-transition", toUint8(Property::FillOpacityTransition)},
+ {"fill-outline-color-transition", toUint8(Property::FillOutlineColorTransition)},
+ {"fill-pattern-transition", toUint8(Property::FillPatternTransition)},
+ {"fill-translate-transition", toUint8(Property::FillTranslateTransition)},
+ {"fill-translate-anchor-transition", toUint8(Property::FillTranslateAnchorTransition)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::FillTranslateAnchorTransition);
+} // namespace
+
optional<Error> FillLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- FillAntialias,
- FillColor,
- FillOpacity,
- FillOutlineColor,
- FillPattern,
- FillTranslate,
- FillTranslateAnchor,
- FillAntialiasTransition,
- FillColorTransition,
- FillOpacityTransition,
- FillOutlineColorTransition,
- FillPatternTransition,
- FillTranslateTransition,
- FillTranslateAnchorTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "fill-antialias", mbgl::underlying_type(Property::FillAntialias) },
- { "fill-color", mbgl::underlying_type(Property::FillColor) },
- { "fill-opacity", mbgl::underlying_type(Property::FillOpacity) },
- { "fill-outline-color", mbgl::underlying_type(Property::FillOutlineColor) },
- { "fill-pattern", mbgl::underlying_type(Property::FillPattern) },
- { "fill-translate", mbgl::underlying_type(Property::FillTranslate) },
- { "fill-translate-anchor", mbgl::underlying_type(Property::FillTranslateAnchor) },
- { "fill-antialias-transition", mbgl::underlying_type(Property::FillAntialiasTransition) },
- { "fill-color-transition", mbgl::underlying_type(Property::FillColorTransition) },
- { "fill-opacity-transition", mbgl::underlying_type(Property::FillOpacityTransition) },
- { "fill-outline-color-transition", mbgl::underlying_type(Property::FillOutlineColorTransition) },
- { "fill-pattern-transition", mbgl::underlying_type(Property::FillPatternTransition) },
- { "fill-translate-transition", mbgl::underlying_type(Property::FillTranslateTransition) },
- { "fill-translate-anchor-transition", mbgl::underlying_type(Property::FillTranslateAnchorTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -384,44 +391,82 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve
if (!transition) {
return error;
}
-
+
if (property == Property::FillAntialiasTransition) {
setFillAntialiasTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillColorTransition) {
setFillColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillOpacityTransition) {
setFillOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillOutlineColorTransition) {
setFillOutlineColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillPatternTransition) {
setFillPatternTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillTranslateTransition) {
setFillTranslateTransition(*transition);
return nullopt;
}
-
+
if (property == Property::FillTranslateAnchorTransition) {
setFillTranslateAnchorTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty FillLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::FillAntialias:
+ return makeStyleProperty(getFillAntialias());
+ case Property::FillColor:
+ return makeStyleProperty(getFillColor());
+ case Property::FillOpacity:
+ return makeStyleProperty(getFillOpacity());
+ case Property::FillOutlineColor:
+ return makeStyleProperty(getFillOutlineColor());
+ case Property::FillPattern:
+ return makeStyleProperty(getFillPattern());
+ case Property::FillTranslate:
+ return makeStyleProperty(getFillTranslate());
+ case Property::FillTranslateAnchor:
+ return makeStyleProperty(getFillTranslateAnchor());
+ case Property::FillAntialiasTransition:
+ return makeStyleProperty(getFillAntialiasTransition());
+ case Property::FillColorTransition:
+ return makeStyleProperty(getFillColorTransition());
+ case Property::FillOpacityTransition:
+ return makeStyleProperty(getFillOpacityTransition());
+ case Property::FillOutlineColorTransition:
+ return makeStyleProperty(getFillOutlineColorTransition());
+ case Property::FillPatternTransition:
+ return makeStyleProperty(getFillPatternTransition());
+ case Property::FillTranslateTransition:
+ return makeStyleProperty(getFillTranslateTransition());
+ case Property::FillTranslateAnchorTransition:
+ return makeStyleProperty(getFillTranslateAnchorTransition());
+ }
+ return {};
}
optional<Error> FillLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -438,5 +483,3 @@ Mutable<Layer::Impl> FillLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp
index 86bb2d6de1..332c65c6b4 100644
--- a/src/mbgl/style/layers/heatmap_layer.cpp
+++ b/src/mbgl/style/layers/heatmap_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/heatmap_layer.hpp>
@@ -204,36 +202,45 @@ TransitionOptions HeatmapLayer::getHeatmapWeightTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ HeatmapColor,
+ HeatmapIntensity,
+ HeatmapOpacity,
+ HeatmapRadius,
+ HeatmapWeight,
+ HeatmapColorTransition,
+ HeatmapIntensityTransition,
+ HeatmapOpacityTransition,
+ HeatmapRadiusTransition,
+ HeatmapWeightTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"heatmap-color", toUint8(Property::HeatmapColor)},
+ {"heatmap-intensity", toUint8(Property::HeatmapIntensity)},
+ {"heatmap-opacity", toUint8(Property::HeatmapOpacity)},
+ {"heatmap-radius", toUint8(Property::HeatmapRadius)},
+ {"heatmap-weight", toUint8(Property::HeatmapWeight)},
+ {"heatmap-color-transition", toUint8(Property::HeatmapColorTransition)},
+ {"heatmap-intensity-transition", toUint8(Property::HeatmapIntensityTransition)},
+ {"heatmap-opacity-transition", toUint8(Property::HeatmapOpacityTransition)},
+ {"heatmap-radius-transition", toUint8(Property::HeatmapRadiusTransition)},
+ {"heatmap-weight-transition", toUint8(Property::HeatmapWeightTransition)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::HeatmapWeightTransition);
+} // namespace
+
optional<Error> HeatmapLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- HeatmapColor,
- HeatmapIntensity,
- HeatmapOpacity,
- HeatmapRadius,
- HeatmapWeight,
- HeatmapColorTransition,
- HeatmapIntensityTransition,
- HeatmapOpacityTransition,
- HeatmapRadiusTransition,
- HeatmapWeightTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "heatmap-color", mbgl::underlying_type(Property::HeatmapColor) },
- { "heatmap-intensity", mbgl::underlying_type(Property::HeatmapIntensity) },
- { "heatmap-opacity", mbgl::underlying_type(Property::HeatmapOpacity) },
- { "heatmap-radius", mbgl::underlying_type(Property::HeatmapRadius) },
- { "heatmap-weight", mbgl::underlying_type(Property::HeatmapWeight) },
- { "heatmap-color-transition", mbgl::underlying_type(Property::HeatmapColorTransition) },
- { "heatmap-intensity-transition", mbgl::underlying_type(Property::HeatmapIntensityTransition) },
- { "heatmap-opacity-transition", mbgl::underlying_type(Property::HeatmapOpacityTransition) },
- { "heatmap-radius-transition", mbgl::underlying_type(Property::HeatmapRadiusTransition) },
- { "heatmap-weight-transition", mbgl::underlying_type(Property::HeatmapWeightTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -295,34 +302,64 @@ optional<Error> HeatmapLayer::setPaintProperty(const std::string& name, const Co
if (!transition) {
return error;
}
-
+
if (property == Property::HeatmapColorTransition) {
setHeatmapColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HeatmapIntensityTransition) {
setHeatmapIntensityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HeatmapOpacityTransition) {
setHeatmapOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HeatmapRadiusTransition) {
setHeatmapRadiusTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HeatmapWeightTransition) {
setHeatmapWeightTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty HeatmapLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::HeatmapColor:
+ return makeStyleProperty(getHeatmapColor());
+ case Property::HeatmapIntensity:
+ return makeStyleProperty(getHeatmapIntensity());
+ case Property::HeatmapOpacity:
+ return makeStyleProperty(getHeatmapOpacity());
+ case Property::HeatmapRadius:
+ return makeStyleProperty(getHeatmapRadius());
+ case Property::HeatmapWeight:
+ return makeStyleProperty(getHeatmapWeight());
+ case Property::HeatmapColorTransition:
+ return makeStyleProperty(getHeatmapColorTransition());
+ case Property::HeatmapIntensityTransition:
+ return makeStyleProperty(getHeatmapIntensityTransition());
+ case Property::HeatmapOpacityTransition:
+ return makeStyleProperty(getHeatmapOpacityTransition());
+ case Property::HeatmapRadiusTransition:
+ return makeStyleProperty(getHeatmapRadiusTransition());
+ case Property::HeatmapWeightTransition:
+ return makeStyleProperty(getHeatmapWeightTransition());
+ }
+ return {};
}
optional<Error> HeatmapLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -339,5 +376,3 @@ Mutable<Layer::Impl> HeatmapLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/hillshade_layer.cpp b/src/mbgl/style/layers/hillshade_layer.cpp
index 710efe5844..a55c079c49 100644
--- a/src/mbgl/style/layers/hillshade_layer.cpp
+++ b/src/mbgl/style/layers/hillshade_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/hillshade_layer.hpp>
@@ -229,40 +227,49 @@ TransitionOptions HillshadeLayer::getHillshadeShadowColorTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ HillshadeAccentColor,
+ HillshadeExaggeration,
+ HillshadeHighlightColor,
+ HillshadeIlluminationAnchor,
+ HillshadeIlluminationDirection,
+ HillshadeShadowColor,
+ HillshadeAccentColorTransition,
+ HillshadeExaggerationTransition,
+ HillshadeHighlightColorTransition,
+ HillshadeIlluminationAnchorTransition,
+ HillshadeIlluminationDirectionTransition,
+ HillshadeShadowColorTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"hillshade-accent-color", toUint8(Property::HillshadeAccentColor)},
+ {"hillshade-exaggeration", toUint8(Property::HillshadeExaggeration)},
+ {"hillshade-highlight-color", toUint8(Property::HillshadeHighlightColor)},
+ {"hillshade-illumination-anchor", toUint8(Property::HillshadeIlluminationAnchor)},
+ {"hillshade-illumination-direction", toUint8(Property::HillshadeIlluminationDirection)},
+ {"hillshade-shadow-color", toUint8(Property::HillshadeShadowColor)},
+ {"hillshade-accent-color-transition", toUint8(Property::HillshadeAccentColorTransition)},
+ {"hillshade-exaggeration-transition", toUint8(Property::HillshadeExaggerationTransition)},
+ {"hillshade-highlight-color-transition", toUint8(Property::HillshadeHighlightColorTransition)},
+ {"hillshade-illumination-anchor-transition", toUint8(Property::HillshadeIlluminationAnchorTransition)},
+ {"hillshade-illumination-direction-transition", toUint8(Property::HillshadeIlluminationDirectionTransition)},
+ {"hillshade-shadow-color-transition", toUint8(Property::HillshadeShadowColorTransition)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::HillshadeShadowColorTransition);
+} // namespace
+
optional<Error> HillshadeLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- HillshadeAccentColor,
- HillshadeExaggeration,
- HillshadeHighlightColor,
- HillshadeIlluminationAnchor,
- HillshadeIlluminationDirection,
- HillshadeShadowColor,
- HillshadeAccentColorTransition,
- HillshadeExaggerationTransition,
- HillshadeHighlightColorTransition,
- HillshadeIlluminationAnchorTransition,
- HillshadeIlluminationDirectionTransition,
- HillshadeShadowColorTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "hillshade-accent-color", mbgl::underlying_type(Property::HillshadeAccentColor) },
- { "hillshade-exaggeration", mbgl::underlying_type(Property::HillshadeExaggeration) },
- { "hillshade-highlight-color", mbgl::underlying_type(Property::HillshadeHighlightColor) },
- { "hillshade-illumination-anchor", mbgl::underlying_type(Property::HillshadeIlluminationAnchor) },
- { "hillshade-illumination-direction", mbgl::underlying_type(Property::HillshadeIlluminationDirection) },
- { "hillshade-shadow-color", mbgl::underlying_type(Property::HillshadeShadowColor) },
- { "hillshade-accent-color-transition", mbgl::underlying_type(Property::HillshadeAccentColorTransition) },
- { "hillshade-exaggeration-transition", mbgl::underlying_type(Property::HillshadeExaggerationTransition) },
- { "hillshade-highlight-color-transition", mbgl::underlying_type(Property::HillshadeHighlightColorTransition) },
- { "hillshade-illumination-anchor-transition", mbgl::underlying_type(Property::HillshadeIlluminationAnchorTransition) },
- { "hillshade-illumination-direction-transition", mbgl::underlying_type(Property::HillshadeIlluminationDirectionTransition) },
- { "hillshade-shadow-color-transition", mbgl::underlying_type(Property::HillshadeShadowColorTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -329,39 +336,73 @@ optional<Error> HillshadeLayer::setPaintProperty(const std::string& name, const
if (!transition) {
return error;
}
-
+
if (property == Property::HillshadeAccentColorTransition) {
setHillshadeAccentColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HillshadeExaggerationTransition) {
setHillshadeExaggerationTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HillshadeHighlightColorTransition) {
setHillshadeHighlightColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HillshadeIlluminationAnchorTransition) {
setHillshadeIlluminationAnchorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HillshadeIlluminationDirectionTransition) {
setHillshadeIlluminationDirectionTransition(*transition);
return nullopt;
}
-
+
if (property == Property::HillshadeShadowColorTransition) {
setHillshadeShadowColorTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty HillshadeLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::HillshadeAccentColor:
+ return makeStyleProperty(getHillshadeAccentColor());
+ case Property::HillshadeExaggeration:
+ return makeStyleProperty(getHillshadeExaggeration());
+ case Property::HillshadeHighlightColor:
+ return makeStyleProperty(getHillshadeHighlightColor());
+ case Property::HillshadeIlluminationAnchor:
+ return makeStyleProperty(getHillshadeIlluminationAnchor());
+ case Property::HillshadeIlluminationDirection:
+ return makeStyleProperty(getHillshadeIlluminationDirection());
+ case Property::HillshadeShadowColor:
+ return makeStyleProperty(getHillshadeShadowColor());
+ case Property::HillshadeAccentColorTransition:
+ return makeStyleProperty(getHillshadeAccentColorTransition());
+ case Property::HillshadeExaggerationTransition:
+ return makeStyleProperty(getHillshadeExaggerationTransition());
+ case Property::HillshadeHighlightColorTransition:
+ return makeStyleProperty(getHillshadeHighlightColorTransition());
+ case Property::HillshadeIlluminationAnchorTransition:
+ return makeStyleProperty(getHillshadeIlluminationAnchorTransition());
+ case Property::HillshadeIlluminationDirectionTransition:
+ return makeStyleProperty(getHillshadeIlluminationDirectionTransition());
+ case Property::HillshadeShadowColorTransition:
+ return makeStyleProperty(getHillshadeShadowColorTransition());
+ }
+ return {};
}
optional<Error> HillshadeLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -378,5 +419,3 @@ Mutable<Layer::Impl> HillshadeLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index 0cd9a82d75..775288264f 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -3,8 +3,6 @@
const layoutProperties = locals.layoutProperties;
const paintProperties = locals.paintProperties;
-%>
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
@@ -190,24 +188,42 @@ TransitionOptions <%- camelize(type) %>Layer::get<%- camelize(property.name) %>T
using namespace conversion;
-optional<Error> <%- camelize(type) %>Layer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
+namespace {
+
+enum class Property : uint8_t {
<% for (const property of paintProperties) { -%>
- <%- camelize(property.name) %>,
+ <%- camelize(property.name) %>,
<% } -%>
<% for (const property of paintProperties) { -%>
- <%- camelize(property.name) %>Transition,
+ <%- camelize(property.name) %>Transition,
+<% } -%>
+<% for (const property of layoutProperties) { -%>
+ <%- camelize(property.name) %>,
<% } -%>
- };
+};
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- <%- paintProperties.map(p => `{ "${p.name}", mbgl::underlying_type(Property::${camelize(p.name)}) }`).join(',\n ') %>,
- <%- paintProperties.map(p => `{ "${p.name}-transition", mbgl::underlying_type(Property::${camelize(p.name)}Transition) }`).join(',\n ') %>
- });
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {<%- paintProperties.map(p => `{"${p.name}", toUint8(Property::${camelize(p.name)})}`).join(',\n ') %>,
+<% if (!layoutProperties.length) { -%>
+ <%- paintProperties.map(p => `{"${p.name}-transition", toUint8(Property::${camelize(p.name)}Transition)}`).join(',\n ') %>});
+<% } else { -%>
+ <%- paintProperties.map(p => `{"${p.name}-transition", toUint8(Property::${camelize(p.name)}Transition)}`).join(',\n ') %>,
+ <%- layoutProperties.map(p => `{"${p.name}", toUint8(Property::${camelize(p.name)})}`).join(',\n ') %>});
+<% } -%>
+
+<% const lastPaintProperty = paintProperties[paintProperties.length - 1]; -%>
+<%-`constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::${camelize(lastPaintProperty.name)}Transition);` %>
+} // namespace
+
+optional<Error> <%- camelize(type) %>Layer::setPaintProperty(const std::string& name, const Convertible& value) {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -248,14 +264,36 @@ optional<Error> <%- camelize(type) %>Layer::setPaintProperty(const std::string&
if (!transition) {
return error;
}
- <% for (const property of paintProperties) { %>
+<% for (const property of paintProperties) { %>
if (property == Property::<%- camelize(property.name) %>Transition) {
set<%- camelize(property.name) %>Transition(*transition);
return nullopt;
}
- <% } %>
+<% } %>
+ return Error{"layer doesn't support this property"};
+}
- return Error { "layer doesn't support this property" };
+StyleProperty <%- camelize(type) %>Layer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+<% for (const property of paintProperties) { -%>
+ case Property::<%- camelize(property.name) %>:
+ return makeStyleProperty(get<%- camelize(property.name) %>());
+<% } -%>
+<% for (const property of paintProperties) { -%>
+ case Property::<%- camelize(property.name) %>Transition:
+ return makeStyleProperty(get<%- camelize(property.name) %>Transition());
+<% } -%>
+<% for (const property of layoutProperties) { -%>
+ case Property::<%- camelize(property.name) %>:
+ return makeStyleProperty(get<%- camelize(property.name) %>());
+<% } -%>
+ }
+ return {};
}
optional<Error> <%- camelize(type) %>Layer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -263,17 +301,8 @@ optional<Error> <%- camelize(type) %>Layer::setLayoutProperty(const std::string&
return Layer::setVisibility(value);
}
<% if (layoutProperties.length) { -%>
- enum class Property {
-<% for (const property of layoutProperties) { -%>
- <%- camelize(property.name) %>,
-<% } -%>
- };
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- <%- layoutProperties.map(p => `{ "${p.name}", mbgl::underlying_type(Property::${camelize(p.name)}) }`).join(',\n ') %>
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second <= lastPaintPropertyIndex) {
return Error { "layer doesn't support this property" };
}
@@ -319,5 +348,3 @@ Mutable<Layer::Impl> <%- camelize(type) %>Layer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index bd29f7f6fd..309a81ae2b 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/line_layer.hpp>
@@ -430,60 +428,77 @@ TransitionOptions LineLayer::getLineWidthTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ LineBlur,
+ LineColor,
+ LineDasharray,
+ LineGapWidth,
+ LineGradient,
+ LineOffset,
+ LineOpacity,
+ LinePattern,
+ LineTranslate,
+ LineTranslateAnchor,
+ LineWidth,
+ LineBlurTransition,
+ LineColorTransition,
+ LineDasharrayTransition,
+ LineGapWidthTransition,
+ LineGradientTransition,
+ LineOffsetTransition,
+ LineOpacityTransition,
+ LinePatternTransition,
+ LineTranslateTransition,
+ LineTranslateAnchorTransition,
+ LineWidthTransition,
+ LineCap,
+ LineJoin,
+ LineMiterLimit,
+ LineRoundLimit,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"line-blur", toUint8(Property::LineBlur)},
+ {"line-color", toUint8(Property::LineColor)},
+ {"line-dasharray", toUint8(Property::LineDasharray)},
+ {"line-gap-width", toUint8(Property::LineGapWidth)},
+ {"line-gradient", toUint8(Property::LineGradient)},
+ {"line-offset", toUint8(Property::LineOffset)},
+ {"line-opacity", toUint8(Property::LineOpacity)},
+ {"line-pattern", toUint8(Property::LinePattern)},
+ {"line-translate", toUint8(Property::LineTranslate)},
+ {"line-translate-anchor", toUint8(Property::LineTranslateAnchor)},
+ {"line-width", toUint8(Property::LineWidth)},
+ {"line-blur-transition", toUint8(Property::LineBlurTransition)},
+ {"line-color-transition", toUint8(Property::LineColorTransition)},
+ {"line-dasharray-transition", toUint8(Property::LineDasharrayTransition)},
+ {"line-gap-width-transition", toUint8(Property::LineGapWidthTransition)},
+ {"line-gradient-transition", toUint8(Property::LineGradientTransition)},
+ {"line-offset-transition", toUint8(Property::LineOffsetTransition)},
+ {"line-opacity-transition", toUint8(Property::LineOpacityTransition)},
+ {"line-pattern-transition", toUint8(Property::LinePatternTransition)},
+ {"line-translate-transition", toUint8(Property::LineTranslateTransition)},
+ {"line-translate-anchor-transition", toUint8(Property::LineTranslateAnchorTransition)},
+ {"line-width-transition", toUint8(Property::LineWidthTransition)},
+ {"line-cap", toUint8(Property::LineCap)},
+ {"line-join", toUint8(Property::LineJoin)},
+ {"line-miter-limit", toUint8(Property::LineMiterLimit)},
+ {"line-round-limit", toUint8(Property::LineRoundLimit)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::LineWidthTransition);
+} // namespace
+
optional<Error> LineLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- LineBlur,
- LineColor,
- LineDasharray,
- LineGapWidth,
- LineGradient,
- LineOffset,
- LineOpacity,
- LinePattern,
- LineTranslate,
- LineTranslateAnchor,
- LineWidth,
- LineBlurTransition,
- LineColorTransition,
- LineDasharrayTransition,
- LineGapWidthTransition,
- LineGradientTransition,
- LineOffsetTransition,
- LineOpacityTransition,
- LinePatternTransition,
- LineTranslateTransition,
- LineTranslateAnchorTransition,
- LineWidthTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "line-blur", mbgl::underlying_type(Property::LineBlur) },
- { "line-color", mbgl::underlying_type(Property::LineColor) },
- { "line-dasharray", mbgl::underlying_type(Property::LineDasharray) },
- { "line-gap-width", mbgl::underlying_type(Property::LineGapWidth) },
- { "line-gradient", mbgl::underlying_type(Property::LineGradient) },
- { "line-offset", mbgl::underlying_type(Property::LineOffset) },
- { "line-opacity", mbgl::underlying_type(Property::LineOpacity) },
- { "line-pattern", mbgl::underlying_type(Property::LinePattern) },
- { "line-translate", mbgl::underlying_type(Property::LineTranslate) },
- { "line-translate-anchor", mbgl::underlying_type(Property::LineTranslateAnchor) },
- { "line-width", mbgl::underlying_type(Property::LineWidth) },
- { "line-blur-transition", mbgl::underlying_type(Property::LineBlurTransition) },
- { "line-color-transition", mbgl::underlying_type(Property::LineColorTransition) },
- { "line-dasharray-transition", mbgl::underlying_type(Property::LineDasharrayTransition) },
- { "line-gap-width-transition", mbgl::underlying_type(Property::LineGapWidthTransition) },
- { "line-gradient-transition", mbgl::underlying_type(Property::LineGradientTransition) },
- { "line-offset-transition", mbgl::underlying_type(Property::LineOffsetTransition) },
- { "line-opacity-transition", mbgl::underlying_type(Property::LineOpacityTransition) },
- { "line-pattern-transition", mbgl::underlying_type(Property::LinePatternTransition) },
- { "line-translate-transition", mbgl::underlying_type(Property::LineTranslateTransition) },
- { "line-translate-anchor-transition", mbgl::underlying_type(Property::LineTranslateAnchorTransition) },
- { "line-width-transition", mbgl::underlying_type(Property::LineWidthTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -601,85 +616,134 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (!transition) {
return error;
}
-
+
if (property == Property::LineBlurTransition) {
setLineBlurTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineColorTransition) {
setLineColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineDasharrayTransition) {
setLineDasharrayTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineGapWidthTransition) {
setLineGapWidthTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineGradientTransition) {
setLineGradientTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineOffsetTransition) {
setLineOffsetTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineOpacityTransition) {
setLineOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LinePatternTransition) {
setLinePatternTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineTranslateTransition) {
setLineTranslateTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineTranslateAnchorTransition) {
setLineTranslateAnchorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::LineWidthTransition) {
setLineWidthTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty LineLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::LineBlur:
+ return makeStyleProperty(getLineBlur());
+ case Property::LineColor:
+ return makeStyleProperty(getLineColor());
+ case Property::LineDasharray:
+ return makeStyleProperty(getLineDasharray());
+ case Property::LineGapWidth:
+ return makeStyleProperty(getLineGapWidth());
+ case Property::LineGradient:
+ return makeStyleProperty(getLineGradient());
+ case Property::LineOffset:
+ return makeStyleProperty(getLineOffset());
+ case Property::LineOpacity:
+ return makeStyleProperty(getLineOpacity());
+ case Property::LinePattern:
+ return makeStyleProperty(getLinePattern());
+ case Property::LineTranslate:
+ return makeStyleProperty(getLineTranslate());
+ case Property::LineTranslateAnchor:
+ return makeStyleProperty(getLineTranslateAnchor());
+ case Property::LineWidth:
+ return makeStyleProperty(getLineWidth());
+ case Property::LineBlurTransition:
+ return makeStyleProperty(getLineBlurTransition());
+ case Property::LineColorTransition:
+ return makeStyleProperty(getLineColorTransition());
+ case Property::LineDasharrayTransition:
+ return makeStyleProperty(getLineDasharrayTransition());
+ case Property::LineGapWidthTransition:
+ return makeStyleProperty(getLineGapWidthTransition());
+ case Property::LineGradientTransition:
+ return makeStyleProperty(getLineGradientTransition());
+ case Property::LineOffsetTransition:
+ return makeStyleProperty(getLineOffsetTransition());
+ case Property::LineOpacityTransition:
+ return makeStyleProperty(getLineOpacityTransition());
+ case Property::LinePatternTransition:
+ return makeStyleProperty(getLinePatternTransition());
+ case Property::LineTranslateTransition:
+ return makeStyleProperty(getLineTranslateTransition());
+ case Property::LineTranslateAnchorTransition:
+ return makeStyleProperty(getLineTranslateAnchorTransition());
+ case Property::LineWidthTransition:
+ return makeStyleProperty(getLineWidthTransition());
+ case Property::LineCap:
+ return makeStyleProperty(getLineCap());
+ case Property::LineJoin:
+ return makeStyleProperty(getLineJoin());
+ case Property::LineMiterLimit:
+ return makeStyleProperty(getLineMiterLimit());
+ case Property::LineRoundLimit:
+ return makeStyleProperty(getLineRoundLimit());
+ }
+ return {};
}
optional<Error> LineLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
if (name == "visibility") {
return Layer::setVisibility(value);
}
- enum class Property {
- LineCap,
- LineJoin,
- LineMiterLimit,
- LineRoundLimit,
- };
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "line-cap", mbgl::underlying_type(Property::LineCap) },
- { "line-join", mbgl::underlying_type(Property::LineJoin) },
- { "line-miter-limit", mbgl::underlying_type(Property::LineMiterLimit) },
- { "line-round-limit", mbgl::underlying_type(Property::LineRoundLimit) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second <= lastPaintPropertyIndex) {
return Error { "layer doesn't support this property" };
}
@@ -739,5 +803,3 @@ Mutable<Layer::Impl> LineLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
index fde1df838d..359e502f3e 100644
--- a/src/mbgl/style/layers/raster_layer.cpp
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/raster_layer.hpp>
@@ -283,48 +281,57 @@ TransitionOptions RasterLayer::getRasterSaturationTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ RasterBrightnessMax,
+ RasterBrightnessMin,
+ RasterContrast,
+ RasterFadeDuration,
+ RasterHueRotate,
+ RasterOpacity,
+ RasterResampling,
+ RasterSaturation,
+ RasterBrightnessMaxTransition,
+ RasterBrightnessMinTransition,
+ RasterContrastTransition,
+ RasterFadeDurationTransition,
+ RasterHueRotateTransition,
+ RasterOpacityTransition,
+ RasterResamplingTransition,
+ RasterSaturationTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"raster-brightness-max", toUint8(Property::RasterBrightnessMax)},
+ {"raster-brightness-min", toUint8(Property::RasterBrightnessMin)},
+ {"raster-contrast", toUint8(Property::RasterContrast)},
+ {"raster-fade-duration", toUint8(Property::RasterFadeDuration)},
+ {"raster-hue-rotate", toUint8(Property::RasterHueRotate)},
+ {"raster-opacity", toUint8(Property::RasterOpacity)},
+ {"raster-resampling", toUint8(Property::RasterResampling)},
+ {"raster-saturation", toUint8(Property::RasterSaturation)},
+ {"raster-brightness-max-transition", toUint8(Property::RasterBrightnessMaxTransition)},
+ {"raster-brightness-min-transition", toUint8(Property::RasterBrightnessMinTransition)},
+ {"raster-contrast-transition", toUint8(Property::RasterContrastTransition)},
+ {"raster-fade-duration-transition", toUint8(Property::RasterFadeDurationTransition)},
+ {"raster-hue-rotate-transition", toUint8(Property::RasterHueRotateTransition)},
+ {"raster-opacity-transition", toUint8(Property::RasterOpacityTransition)},
+ {"raster-resampling-transition", toUint8(Property::RasterResamplingTransition)},
+ {"raster-saturation-transition", toUint8(Property::RasterSaturationTransition)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::RasterSaturationTransition);
+} // namespace
+
optional<Error> RasterLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- RasterBrightnessMax,
- RasterBrightnessMin,
- RasterContrast,
- RasterFadeDuration,
- RasterHueRotate,
- RasterOpacity,
- RasterResampling,
- RasterSaturation,
- RasterBrightnessMaxTransition,
- RasterBrightnessMinTransition,
- RasterContrastTransition,
- RasterFadeDurationTransition,
- RasterHueRotateTransition,
- RasterOpacityTransition,
- RasterResamplingTransition,
- RasterSaturationTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "raster-brightness-max", mbgl::underlying_type(Property::RasterBrightnessMax) },
- { "raster-brightness-min", mbgl::underlying_type(Property::RasterBrightnessMin) },
- { "raster-contrast", mbgl::underlying_type(Property::RasterContrast) },
- { "raster-fade-duration", mbgl::underlying_type(Property::RasterFadeDuration) },
- { "raster-hue-rotate", mbgl::underlying_type(Property::RasterHueRotate) },
- { "raster-opacity", mbgl::underlying_type(Property::RasterOpacity) },
- { "raster-resampling", mbgl::underlying_type(Property::RasterResampling) },
- { "raster-saturation", mbgl::underlying_type(Property::RasterSaturation) },
- { "raster-brightness-max-transition", mbgl::underlying_type(Property::RasterBrightnessMaxTransition) },
- { "raster-brightness-min-transition", mbgl::underlying_type(Property::RasterBrightnessMinTransition) },
- { "raster-contrast-transition", mbgl::underlying_type(Property::RasterContrastTransition) },
- { "raster-fade-duration-transition", mbgl::underlying_type(Property::RasterFadeDurationTransition) },
- { "raster-hue-rotate-transition", mbgl::underlying_type(Property::RasterHueRotateTransition) },
- { "raster-opacity-transition", mbgl::underlying_type(Property::RasterOpacityTransition) },
- { "raster-resampling-transition", mbgl::underlying_type(Property::RasterResamplingTransition) },
- { "raster-saturation-transition", mbgl::underlying_type(Property::RasterSaturationTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -392,49 +399,91 @@ optional<Error> RasterLayer::setPaintProperty(const std::string& name, const Con
if (!transition) {
return error;
}
-
+
if (property == Property::RasterBrightnessMaxTransition) {
setRasterBrightnessMaxTransition(*transition);
return nullopt;
}
-
+
if (property == Property::RasterBrightnessMinTransition) {
setRasterBrightnessMinTransition(*transition);
return nullopt;
}
-
+
if (property == Property::RasterContrastTransition) {
setRasterContrastTransition(*transition);
return nullopt;
}
-
+
if (property == Property::RasterFadeDurationTransition) {
setRasterFadeDurationTransition(*transition);
return nullopt;
}
-
+
if (property == Property::RasterHueRotateTransition) {
setRasterHueRotateTransition(*transition);
return nullopt;
}
-
+
if (property == Property::RasterOpacityTransition) {
setRasterOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::RasterResamplingTransition) {
setRasterResamplingTransition(*transition);
return nullopt;
}
-
+
if (property == Property::RasterSaturationTransition) {
setRasterSaturationTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty RasterLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::RasterBrightnessMax:
+ return makeStyleProperty(getRasterBrightnessMax());
+ case Property::RasterBrightnessMin:
+ return makeStyleProperty(getRasterBrightnessMin());
+ case Property::RasterContrast:
+ return makeStyleProperty(getRasterContrast());
+ case Property::RasterFadeDuration:
+ return makeStyleProperty(getRasterFadeDuration());
+ case Property::RasterHueRotate:
+ return makeStyleProperty(getRasterHueRotate());
+ case Property::RasterOpacity:
+ return makeStyleProperty(getRasterOpacity());
+ case Property::RasterResampling:
+ return makeStyleProperty(getRasterResampling());
+ case Property::RasterSaturation:
+ return makeStyleProperty(getRasterSaturation());
+ case Property::RasterBrightnessMaxTransition:
+ return makeStyleProperty(getRasterBrightnessMaxTransition());
+ case Property::RasterBrightnessMinTransition:
+ return makeStyleProperty(getRasterBrightnessMinTransition());
+ case Property::RasterContrastTransition:
+ return makeStyleProperty(getRasterContrastTransition());
+ case Property::RasterFadeDurationTransition:
+ return makeStyleProperty(getRasterFadeDurationTransition());
+ case Property::RasterHueRotateTransition:
+ return makeStyleProperty(getRasterHueRotateTransition());
+ case Property::RasterOpacityTransition:
+ return makeStyleProperty(getRasterOpacityTransition());
+ case Property::RasterResamplingTransition:
+ return makeStyleProperty(getRasterResamplingTransition());
+ case Property::RasterSaturationTransition:
+ return makeStyleProperty(getRasterSaturationTransition());
+ }
+ return {};
}
optional<Error> RasterLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
@@ -451,5 +500,3 @@ Mutable<Layer::Impl> RasterLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index af5daa4dc0..b3ee0f698c 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
#include <mbgl/style/layers/symbol_layer.hpp>
@@ -1102,72 +1100,163 @@ TransitionOptions SymbolLayer::getTextTranslateAnchorTransition() const {
using namespace conversion;
+namespace {
+
+enum class Property : uint8_t {
+ IconColor,
+ IconHaloBlur,
+ IconHaloColor,
+ IconHaloWidth,
+ IconOpacity,
+ IconTranslate,
+ IconTranslateAnchor,
+ TextColor,
+ TextHaloBlur,
+ TextHaloColor,
+ TextHaloWidth,
+ TextOpacity,
+ TextTranslate,
+ TextTranslateAnchor,
+ IconColorTransition,
+ IconHaloBlurTransition,
+ IconHaloColorTransition,
+ IconHaloWidthTransition,
+ IconOpacityTransition,
+ IconTranslateTransition,
+ IconTranslateAnchorTransition,
+ TextColorTransition,
+ TextHaloBlurTransition,
+ TextHaloColorTransition,
+ TextHaloWidthTransition,
+ TextOpacityTransition,
+ TextTranslateTransition,
+ TextTranslateAnchorTransition,
+ IconAllowOverlap,
+ IconAnchor,
+ IconIgnorePlacement,
+ IconImage,
+ IconKeepUpright,
+ IconOffset,
+ IconOptional,
+ IconPadding,
+ IconPitchAlignment,
+ IconRotate,
+ IconRotationAlignment,
+ IconSize,
+ IconTextFit,
+ IconTextFitPadding,
+ SymbolAvoidEdges,
+ SymbolPlacement,
+ SymbolSortKey,
+ SymbolSpacing,
+ SymbolZOrder,
+ TextAllowOverlap,
+ TextAnchor,
+ TextField,
+ TextFont,
+ TextIgnorePlacement,
+ TextJustify,
+ TextKeepUpright,
+ TextLetterSpacing,
+ TextLineHeight,
+ TextMaxAngle,
+ TextMaxWidth,
+ TextOffset,
+ TextOptional,
+ TextPadding,
+ TextPitchAlignment,
+ TextRadialOffset,
+ TextRotate,
+ TextRotationAlignment,
+ TextSize,
+ TextTransform,
+ TextVariableAnchor,
+ TextWritingMode,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto layerProperties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"icon-color", toUint8(Property::IconColor)},
+ {"icon-halo-blur", toUint8(Property::IconHaloBlur)},
+ {"icon-halo-color", toUint8(Property::IconHaloColor)},
+ {"icon-halo-width", toUint8(Property::IconHaloWidth)},
+ {"icon-opacity", toUint8(Property::IconOpacity)},
+ {"icon-translate", toUint8(Property::IconTranslate)},
+ {"icon-translate-anchor", toUint8(Property::IconTranslateAnchor)},
+ {"text-color", toUint8(Property::TextColor)},
+ {"text-halo-blur", toUint8(Property::TextHaloBlur)},
+ {"text-halo-color", toUint8(Property::TextHaloColor)},
+ {"text-halo-width", toUint8(Property::TextHaloWidth)},
+ {"text-opacity", toUint8(Property::TextOpacity)},
+ {"text-translate", toUint8(Property::TextTranslate)},
+ {"text-translate-anchor", toUint8(Property::TextTranslateAnchor)},
+ {"icon-color-transition", toUint8(Property::IconColorTransition)},
+ {"icon-halo-blur-transition", toUint8(Property::IconHaloBlurTransition)},
+ {"icon-halo-color-transition", toUint8(Property::IconHaloColorTransition)},
+ {"icon-halo-width-transition", toUint8(Property::IconHaloWidthTransition)},
+ {"icon-opacity-transition", toUint8(Property::IconOpacityTransition)},
+ {"icon-translate-transition", toUint8(Property::IconTranslateTransition)},
+ {"icon-translate-anchor-transition", toUint8(Property::IconTranslateAnchorTransition)},
+ {"text-color-transition", toUint8(Property::TextColorTransition)},
+ {"text-halo-blur-transition", toUint8(Property::TextHaloBlurTransition)},
+ {"text-halo-color-transition", toUint8(Property::TextHaloColorTransition)},
+ {"text-halo-width-transition", toUint8(Property::TextHaloWidthTransition)},
+ {"text-opacity-transition", toUint8(Property::TextOpacityTransition)},
+ {"text-translate-transition", toUint8(Property::TextTranslateTransition)},
+ {"text-translate-anchor-transition", toUint8(Property::TextTranslateAnchorTransition)},
+ {"icon-allow-overlap", toUint8(Property::IconAllowOverlap)},
+ {"icon-anchor", toUint8(Property::IconAnchor)},
+ {"icon-ignore-placement", toUint8(Property::IconIgnorePlacement)},
+ {"icon-image", toUint8(Property::IconImage)},
+ {"icon-keep-upright", toUint8(Property::IconKeepUpright)},
+ {"icon-offset", toUint8(Property::IconOffset)},
+ {"icon-optional", toUint8(Property::IconOptional)},
+ {"icon-padding", toUint8(Property::IconPadding)},
+ {"icon-pitch-alignment", toUint8(Property::IconPitchAlignment)},
+ {"icon-rotate", toUint8(Property::IconRotate)},
+ {"icon-rotation-alignment", toUint8(Property::IconRotationAlignment)},
+ {"icon-size", toUint8(Property::IconSize)},
+ {"icon-text-fit", toUint8(Property::IconTextFit)},
+ {"icon-text-fit-padding", toUint8(Property::IconTextFitPadding)},
+ {"symbol-avoid-edges", toUint8(Property::SymbolAvoidEdges)},
+ {"symbol-placement", toUint8(Property::SymbolPlacement)},
+ {"symbol-sort-key", toUint8(Property::SymbolSortKey)},
+ {"symbol-spacing", toUint8(Property::SymbolSpacing)},
+ {"symbol-z-order", toUint8(Property::SymbolZOrder)},
+ {"text-allow-overlap", toUint8(Property::TextAllowOverlap)},
+ {"text-anchor", toUint8(Property::TextAnchor)},
+ {"text-field", toUint8(Property::TextField)},
+ {"text-font", toUint8(Property::TextFont)},
+ {"text-ignore-placement", toUint8(Property::TextIgnorePlacement)},
+ {"text-justify", toUint8(Property::TextJustify)},
+ {"text-keep-upright", toUint8(Property::TextKeepUpright)},
+ {"text-letter-spacing", toUint8(Property::TextLetterSpacing)},
+ {"text-line-height", toUint8(Property::TextLineHeight)},
+ {"text-max-angle", toUint8(Property::TextMaxAngle)},
+ {"text-max-width", toUint8(Property::TextMaxWidth)},
+ {"text-offset", toUint8(Property::TextOffset)},
+ {"text-optional", toUint8(Property::TextOptional)},
+ {"text-padding", toUint8(Property::TextPadding)},
+ {"text-pitch-alignment", toUint8(Property::TextPitchAlignment)},
+ {"text-radial-offset", toUint8(Property::TextRadialOffset)},
+ {"text-rotate", toUint8(Property::TextRotate)},
+ {"text-rotation-alignment", toUint8(Property::TextRotationAlignment)},
+ {"text-size", toUint8(Property::TextSize)},
+ {"text-transform", toUint8(Property::TextTransform)},
+ {"text-variable-anchor", toUint8(Property::TextVariableAnchor)},
+ {"text-writing-mode", toUint8(Property::TextWritingMode)}});
+
+constexpr uint8_t lastPaintPropertyIndex = toUint8(Property::TextTranslateAnchorTransition);
+} // namespace
+
optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- IconColor,
- IconHaloBlur,
- IconHaloColor,
- IconHaloWidth,
- IconOpacity,
- IconTranslate,
- IconTranslateAnchor,
- TextColor,
- TextHaloBlur,
- TextHaloColor,
- TextHaloWidth,
- TextOpacity,
- TextTranslate,
- TextTranslateAnchor,
- IconColorTransition,
- IconHaloBlurTransition,
- IconHaloColorTransition,
- IconHaloWidthTransition,
- IconOpacityTransition,
- IconTranslateTransition,
- IconTranslateAnchorTransition,
- TextColorTransition,
- TextHaloBlurTransition,
- TextHaloColorTransition,
- TextHaloWidthTransition,
- TextOpacityTransition,
- TextTranslateTransition,
- TextTranslateAnchorTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "icon-color", mbgl::underlying_type(Property::IconColor) },
- { "icon-halo-blur", mbgl::underlying_type(Property::IconHaloBlur) },
- { "icon-halo-color", mbgl::underlying_type(Property::IconHaloColor) },
- { "icon-halo-width", mbgl::underlying_type(Property::IconHaloWidth) },
- { "icon-opacity", mbgl::underlying_type(Property::IconOpacity) },
- { "icon-translate", mbgl::underlying_type(Property::IconTranslate) },
- { "icon-translate-anchor", mbgl::underlying_type(Property::IconTranslateAnchor) },
- { "text-color", mbgl::underlying_type(Property::TextColor) },
- { "text-halo-blur", mbgl::underlying_type(Property::TextHaloBlur) },
- { "text-halo-color", mbgl::underlying_type(Property::TextHaloColor) },
- { "text-halo-width", mbgl::underlying_type(Property::TextHaloWidth) },
- { "text-opacity", mbgl::underlying_type(Property::TextOpacity) },
- { "text-translate", mbgl::underlying_type(Property::TextTranslate) },
- { "text-translate-anchor", mbgl::underlying_type(Property::TextTranslateAnchor) },
- { "icon-color-transition", mbgl::underlying_type(Property::IconColorTransition) },
- { "icon-halo-blur-transition", mbgl::underlying_type(Property::IconHaloBlurTransition) },
- { "icon-halo-color-transition", mbgl::underlying_type(Property::IconHaloColorTransition) },
- { "icon-halo-width-transition", mbgl::underlying_type(Property::IconHaloWidthTransition) },
- { "icon-opacity-transition", mbgl::underlying_type(Property::IconOpacityTransition) },
- { "icon-translate-transition", mbgl::underlying_type(Property::IconTranslateTransition) },
- { "icon-translate-anchor-transition", mbgl::underlying_type(Property::IconTranslateAnchorTransition) },
- { "text-color-transition", mbgl::underlying_type(Property::TextColorTransition) },
- { "text-halo-blur-transition", mbgl::underlying_type(Property::TextHaloBlurTransition) },
- { "text-halo-color-transition", mbgl::underlying_type(Property::TextHaloColorTransition) },
- { "text-halo-width-transition", mbgl::underlying_type(Property::TextHaloWidthTransition) },
- { "text-opacity-transition", mbgl::underlying_type(Property::TextOpacityTransition) },
- { "text-translate-transition", mbgl::underlying_type(Property::TextTranslateTransition) },
- { "text-translate-anchor-transition", mbgl::underlying_type(Property::TextTranslateAnchorTransition) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
- return Error { "layer doesn't support this property" };
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second > lastPaintPropertyIndex) {
+ return Error{"layer doesn't support this property"};
}
auto property = static_cast<Property>(it->second);
@@ -1285,174 +1374,235 @@ optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Con
if (!transition) {
return error;
}
-
+
if (property == Property::IconColorTransition) {
setIconColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::IconHaloBlurTransition) {
setIconHaloBlurTransition(*transition);
return nullopt;
}
-
+
if (property == Property::IconHaloColorTransition) {
setIconHaloColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::IconHaloWidthTransition) {
setIconHaloWidthTransition(*transition);
return nullopt;
}
-
+
if (property == Property::IconOpacityTransition) {
setIconOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::IconTranslateTransition) {
setIconTranslateTransition(*transition);
return nullopt;
}
-
+
if (property == Property::IconTranslateAnchorTransition) {
setIconTranslateAnchorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::TextColorTransition) {
setTextColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::TextHaloBlurTransition) {
setTextHaloBlurTransition(*transition);
return nullopt;
}
-
+
if (property == Property::TextHaloColorTransition) {
setTextHaloColorTransition(*transition);
return nullopt;
}
-
+
if (property == Property::TextHaloWidthTransition) {
setTextHaloWidthTransition(*transition);
return nullopt;
}
-
+
if (property == Property::TextOpacityTransition) {
setTextOpacityTransition(*transition);
return nullopt;
}
-
+
if (property == Property::TextTranslateTransition) {
setTextTranslateTransition(*transition);
return nullopt;
}
-
+
if (property == Property::TextTranslateAnchorTransition) {
setTextTranslateAnchorTransition(*transition);
return nullopt;
}
-
- return Error { "layer doesn't support this property" };
+ return Error{"layer doesn't support this property"};
+}
+
+StyleProperty SymbolLayer::getProperty(const std::string& name) const {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::IconColor:
+ return makeStyleProperty(getIconColor());
+ case Property::IconHaloBlur:
+ return makeStyleProperty(getIconHaloBlur());
+ case Property::IconHaloColor:
+ return makeStyleProperty(getIconHaloColor());
+ case Property::IconHaloWidth:
+ return makeStyleProperty(getIconHaloWidth());
+ case Property::IconOpacity:
+ return makeStyleProperty(getIconOpacity());
+ case Property::IconTranslate:
+ return makeStyleProperty(getIconTranslate());
+ case Property::IconTranslateAnchor:
+ return makeStyleProperty(getIconTranslateAnchor());
+ case Property::TextColor:
+ return makeStyleProperty(getTextColor());
+ case Property::TextHaloBlur:
+ return makeStyleProperty(getTextHaloBlur());
+ case Property::TextHaloColor:
+ return makeStyleProperty(getTextHaloColor());
+ case Property::TextHaloWidth:
+ return makeStyleProperty(getTextHaloWidth());
+ case Property::TextOpacity:
+ return makeStyleProperty(getTextOpacity());
+ case Property::TextTranslate:
+ return makeStyleProperty(getTextTranslate());
+ case Property::TextTranslateAnchor:
+ return makeStyleProperty(getTextTranslateAnchor());
+ case Property::IconColorTransition:
+ return makeStyleProperty(getIconColorTransition());
+ case Property::IconHaloBlurTransition:
+ return makeStyleProperty(getIconHaloBlurTransition());
+ case Property::IconHaloColorTransition:
+ return makeStyleProperty(getIconHaloColorTransition());
+ case Property::IconHaloWidthTransition:
+ return makeStyleProperty(getIconHaloWidthTransition());
+ case Property::IconOpacityTransition:
+ return makeStyleProperty(getIconOpacityTransition());
+ case Property::IconTranslateTransition:
+ return makeStyleProperty(getIconTranslateTransition());
+ case Property::IconTranslateAnchorTransition:
+ return makeStyleProperty(getIconTranslateAnchorTransition());
+ case Property::TextColorTransition:
+ return makeStyleProperty(getTextColorTransition());
+ case Property::TextHaloBlurTransition:
+ return makeStyleProperty(getTextHaloBlurTransition());
+ case Property::TextHaloColorTransition:
+ return makeStyleProperty(getTextHaloColorTransition());
+ case Property::TextHaloWidthTransition:
+ return makeStyleProperty(getTextHaloWidthTransition());
+ case Property::TextOpacityTransition:
+ return makeStyleProperty(getTextOpacityTransition());
+ case Property::TextTranslateTransition:
+ return makeStyleProperty(getTextTranslateTransition());
+ case Property::TextTranslateAnchorTransition:
+ return makeStyleProperty(getTextTranslateAnchorTransition());
+ case Property::IconAllowOverlap:
+ return makeStyleProperty(getIconAllowOverlap());
+ case Property::IconAnchor:
+ return makeStyleProperty(getIconAnchor());
+ case Property::IconIgnorePlacement:
+ return makeStyleProperty(getIconIgnorePlacement());
+ case Property::IconImage:
+ return makeStyleProperty(getIconImage());
+ case Property::IconKeepUpright:
+ return makeStyleProperty(getIconKeepUpright());
+ case Property::IconOffset:
+ return makeStyleProperty(getIconOffset());
+ case Property::IconOptional:
+ return makeStyleProperty(getIconOptional());
+ case Property::IconPadding:
+ return makeStyleProperty(getIconPadding());
+ case Property::IconPitchAlignment:
+ return makeStyleProperty(getIconPitchAlignment());
+ case Property::IconRotate:
+ return makeStyleProperty(getIconRotate());
+ case Property::IconRotationAlignment:
+ return makeStyleProperty(getIconRotationAlignment());
+ case Property::IconSize:
+ return makeStyleProperty(getIconSize());
+ case Property::IconTextFit:
+ return makeStyleProperty(getIconTextFit());
+ case Property::IconTextFitPadding:
+ return makeStyleProperty(getIconTextFitPadding());
+ case Property::SymbolAvoidEdges:
+ return makeStyleProperty(getSymbolAvoidEdges());
+ case Property::SymbolPlacement:
+ return makeStyleProperty(getSymbolPlacement());
+ case Property::SymbolSortKey:
+ return makeStyleProperty(getSymbolSortKey());
+ case Property::SymbolSpacing:
+ return makeStyleProperty(getSymbolSpacing());
+ case Property::SymbolZOrder:
+ return makeStyleProperty(getSymbolZOrder());
+ case Property::TextAllowOverlap:
+ return makeStyleProperty(getTextAllowOverlap());
+ case Property::TextAnchor:
+ return makeStyleProperty(getTextAnchor());
+ case Property::TextField:
+ return makeStyleProperty(getTextField());
+ case Property::TextFont:
+ return makeStyleProperty(getTextFont());
+ case Property::TextIgnorePlacement:
+ return makeStyleProperty(getTextIgnorePlacement());
+ case Property::TextJustify:
+ return makeStyleProperty(getTextJustify());
+ case Property::TextKeepUpright:
+ return makeStyleProperty(getTextKeepUpright());
+ case Property::TextLetterSpacing:
+ return makeStyleProperty(getTextLetterSpacing());
+ case Property::TextLineHeight:
+ return makeStyleProperty(getTextLineHeight());
+ case Property::TextMaxAngle:
+ return makeStyleProperty(getTextMaxAngle());
+ case Property::TextMaxWidth:
+ return makeStyleProperty(getTextMaxWidth());
+ case Property::TextOffset:
+ return makeStyleProperty(getTextOffset());
+ case Property::TextOptional:
+ return makeStyleProperty(getTextOptional());
+ case Property::TextPadding:
+ return makeStyleProperty(getTextPadding());
+ case Property::TextPitchAlignment:
+ return makeStyleProperty(getTextPitchAlignment());
+ case Property::TextRadialOffset:
+ return makeStyleProperty(getTextRadialOffset());
+ case Property::TextRotate:
+ return makeStyleProperty(getTextRotate());
+ case Property::TextRotationAlignment:
+ return makeStyleProperty(getTextRotationAlignment());
+ case Property::TextSize:
+ return makeStyleProperty(getTextSize());
+ case Property::TextTransform:
+ return makeStyleProperty(getTextTransform());
+ case Property::TextVariableAnchor:
+ return makeStyleProperty(getTextVariableAnchor());
+ case Property::TextWritingMode:
+ return makeStyleProperty(getTextWritingMode());
+ }
+ return {};
}
optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
if (name == "visibility") {
return Layer::setVisibility(value);
}
- enum class Property {
- IconAllowOverlap,
- IconAnchor,
- IconIgnorePlacement,
- IconImage,
- IconKeepUpright,
- IconOffset,
- IconOptional,
- IconPadding,
- IconPitchAlignment,
- IconRotate,
- IconRotationAlignment,
- IconSize,
- IconTextFit,
- IconTextFitPadding,
- SymbolAvoidEdges,
- SymbolPlacement,
- SymbolSortKey,
- SymbolSpacing,
- SymbolZOrder,
- TextAllowOverlap,
- TextAnchor,
- TextField,
- TextFont,
- TextIgnorePlacement,
- TextJustify,
- TextKeepUpright,
- TextLetterSpacing,
- TextLineHeight,
- TextMaxAngle,
- TextMaxWidth,
- TextOffset,
- TextOptional,
- TextPadding,
- TextPitchAlignment,
- TextRadialOffset,
- TextRotate,
- TextRotationAlignment,
- TextSize,
- TextTransform,
- TextVariableAnchor,
- TextWritingMode,
- };
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "icon-allow-overlap", mbgl::underlying_type(Property::IconAllowOverlap) },
- { "icon-anchor", mbgl::underlying_type(Property::IconAnchor) },
- { "icon-ignore-placement", mbgl::underlying_type(Property::IconIgnorePlacement) },
- { "icon-image", mbgl::underlying_type(Property::IconImage) },
- { "icon-keep-upright", mbgl::underlying_type(Property::IconKeepUpright) },
- { "icon-offset", mbgl::underlying_type(Property::IconOffset) },
- { "icon-optional", mbgl::underlying_type(Property::IconOptional) },
- { "icon-padding", mbgl::underlying_type(Property::IconPadding) },
- { "icon-pitch-alignment", mbgl::underlying_type(Property::IconPitchAlignment) },
- { "icon-rotate", mbgl::underlying_type(Property::IconRotate) },
- { "icon-rotation-alignment", mbgl::underlying_type(Property::IconRotationAlignment) },
- { "icon-size", mbgl::underlying_type(Property::IconSize) },
- { "icon-text-fit", mbgl::underlying_type(Property::IconTextFit) },
- { "icon-text-fit-padding", mbgl::underlying_type(Property::IconTextFitPadding) },
- { "symbol-avoid-edges", mbgl::underlying_type(Property::SymbolAvoidEdges) },
- { "symbol-placement", mbgl::underlying_type(Property::SymbolPlacement) },
- { "symbol-sort-key", mbgl::underlying_type(Property::SymbolSortKey) },
- { "symbol-spacing", mbgl::underlying_type(Property::SymbolSpacing) },
- { "symbol-z-order", mbgl::underlying_type(Property::SymbolZOrder) },
- { "text-allow-overlap", mbgl::underlying_type(Property::TextAllowOverlap) },
- { "text-anchor", mbgl::underlying_type(Property::TextAnchor) },
- { "text-field", mbgl::underlying_type(Property::TextField) },
- { "text-font", mbgl::underlying_type(Property::TextFont) },
- { "text-ignore-placement", mbgl::underlying_type(Property::TextIgnorePlacement) },
- { "text-justify", mbgl::underlying_type(Property::TextJustify) },
- { "text-keep-upright", mbgl::underlying_type(Property::TextKeepUpright) },
- { "text-letter-spacing", mbgl::underlying_type(Property::TextLetterSpacing) },
- { "text-line-height", mbgl::underlying_type(Property::TextLineHeight) },
- { "text-max-angle", mbgl::underlying_type(Property::TextMaxAngle) },
- { "text-max-width", mbgl::underlying_type(Property::TextMaxWidth) },
- { "text-offset", mbgl::underlying_type(Property::TextOffset) },
- { "text-optional", mbgl::underlying_type(Property::TextOptional) },
- { "text-padding", mbgl::underlying_type(Property::TextPadding) },
- { "text-pitch-alignment", mbgl::underlying_type(Property::TextPitchAlignment) },
- { "text-radial-offset", mbgl::underlying_type(Property::TextRadialOffset) },
- { "text-rotate", mbgl::underlying_type(Property::TextRotate) },
- { "text-rotation-alignment", mbgl::underlying_type(Property::TextRotationAlignment) },
- { "text-size", mbgl::underlying_type(Property::TextSize) },
- { "text-transform", mbgl::underlying_type(Property::TextTransform) },
- { "text-variable-anchor", mbgl::underlying_type(Property::TextVariableAnchor) },
- { "text-writing-mode", mbgl::underlying_type(Property::TextWritingMode) }
- });
-
- const auto it = properties.find(name.c_str());
- if (it == properties.end()) {
+ const auto it = layerProperties.find(name.c_str());
+ if (it == layerProperties.end() || it->second <= lastPaintPropertyIndex) {
return Error { "layer doesn't support this property" };
}
@@ -1805,5 +1955,3 @@ Mutable<Layer::Impl> SymbolLayer::mutableBaseImpl() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/light.cpp b/src/mbgl/style/light.cpp
index be56a0d93b..a10e693073 100644
--- a/src/mbgl/style/light.cpp
+++ b/src/mbgl/style/light.cpp
@@ -1,5 +1,3 @@
-// clang-format off
-
// This file is generated. Do not edit.
#include <mbgl/style/light.hpp>
@@ -36,29 +34,37 @@ Mutable<Light::Impl> Light::mutableImpl() const {
using namespace conversion;
-optional<Error> Light::setProperty(const std::string& name, const Convertible& value) {
- enum class Property {
- Anchor,
- Color,
- Intensity,
- Position,
- AnchorTransition,
- ColorTransition,
- IntensityTransition,
- PositionTransition,
- };
-
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- { "anchor", mbgl::underlying_type(Property::Anchor) },
- { "color", mbgl::underlying_type(Property::Color) },
- { "intensity", mbgl::underlying_type(Property::Intensity) },
- { "position", mbgl::underlying_type(Property::Position) },
- { "anchor-transition", mbgl::underlying_type(Property::AnchorTransition) },
- { "color-transition", mbgl::underlying_type(Property::ColorTransition) },
- { "intensity-transition", mbgl::underlying_type(Property::IntensityTransition) },
- { "position-transition", mbgl::underlying_type(Property::PositionTransition) }
- });
+namespace {
+
+enum class Property : uint8_t {
+ Anchor,
+ Color,
+ Intensity,
+ Position,
+ AnchorTransition,
+ ColorTransition,
+ IntensityTransition,
+ PositionTransition,
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
+
+MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {{"anchor", toUint8(Property::Anchor)},
+ {"color", toUint8(Property::Color)},
+ {"intensity", toUint8(Property::Intensity)},
+ {"position", toUint8(Property::Position)},
+ {"anchor-transition", toUint8(Property::AnchorTransition)},
+ {"color-transition", toUint8(Property::ColorTransition)},
+ {"intensity-transition", toUint8(Property::IntensityTransition)},
+ {"position-transition", toUint8(Property::PositionTransition)}});
+} // namespace
+
+optional<Error> Light::setProperty(const std::string& name, const Convertible& value) {
const auto it = properties.find(name.c_str());
if (it == properties.end()) {
return Error { "light doesn't support this property" };
@@ -146,6 +152,33 @@ optional<Error> Light::setProperty(const std::string& name, const Convertible& v
return Error { "light doesn't support this property" };
}
+StyleProperty Light::getProperty(const std::string& name) const {
+ const auto it = properties.find(name.c_str());
+ if (it == properties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+ case Property::Anchor:
+ return makeStyleProperty(getAnchor());
+ case Property::Color:
+ return makeStyleProperty(getColor());
+ case Property::Intensity:
+ return makeStyleProperty(getIntensity());
+ case Property::Position:
+ return makeStyleProperty(getPosition());
+ case Property::AnchorTransition:
+ return makeStyleProperty(getAnchorTransition());
+ case Property::ColorTransition:
+ return makeStyleProperty(getColorTransition());
+ case Property::IntensityTransition:
+ return makeStyleProperty(getIntensityTransition());
+ case Property::PositionTransition:
+ return makeStyleProperty(getPositionTransition());
+ }
+ return {};
+}
+
LightAnchorType Light::getDefaultAnchor() {
return LightAnchor::defaultValue();
}
@@ -253,5 +286,3 @@ TransitionOptions Light::getPositionTransition() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/light.cpp.ejs b/src/mbgl/style/light.cpp.ejs
index 55cc013827..68c1bf59e2 100644
--- a/src/mbgl/style/light.cpp.ejs
+++ b/src/mbgl/style/light.cpp.ejs
@@ -1,8 +1,6 @@
<%
const properties = locals.properties;
-%>
-// clang-format off
-
// This file is generated. Do not edit.
#include <mbgl/style/light.hpp>
@@ -39,21 +37,29 @@ Mutable<Light::Impl> Light::mutableImpl() const {
using namespace conversion;
-optional<Error> Light::setProperty(const std::string& name, const Convertible& value) {
- enum class Property {
+namespace {
+
+enum class Property : uint8_t {
<% for (const property of properties) { -%>
- <%- camelize(property.name) %>,
+ <%- camelize(property.name) %>,
<% } -%>
<% for (const property of properties) { -%>
- <%- camelize(property.name) %>Transition,
+ <%- camelize(property.name) %>Transition,
<% } -%>
- };
+};
+
+template <typename T>
+constexpr uint8_t toUint8(T t) noexcept {
+ return uint8_t(mbgl::underlying_type(t));
+}
- MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>({
- <%- properties.map(p => `{ "${p.name}", mbgl::underlying_type(Property::${camelize(p.name)}) }`).join(',\n ') %>,
- <%- properties.map(p => `{ "${p.name}-transition", mbgl::underlying_type(Property::${camelize(p.name)}Transition) }`).join(',\n ') %>
- });
+MAPBOX_ETERNAL_CONSTEXPR const auto properties = mapbox::eternal::hash_map<mapbox::eternal::string, uint8_t>(
+ {<%- properties.map(p => `{"${p.name}", toUint8(Property::${camelize(p.name)})}`).join(',\n ') %>,
+ <%- properties.map(p => `{"${p.name}-transition", toUint8(Property::${camelize(p.name)}Transition)}`).join(',\n ') %>});
+} // namespace
+
+optional<Error> Light::setProperty(const std::string& name, const Convertible& value) {
const auto it = properties.find(name.c_str());
if (it == properties.end()) {
return Error { "light doesn't support this property" };
@@ -107,6 +113,25 @@ optional<Error> Light::setProperty(const std::string& name, const Convertible& v
return Error { "light doesn't support this property" };
}
+StyleProperty Light::getProperty(const std::string& name) const {
+ const auto it = properties.find(name.c_str());
+ if (it == properties.end()) {
+ return {};
+ }
+
+ switch (static_cast<Property>(it->second)) {
+<% for (const property of properties) { -%>
+ case Property::<%- camelize(property.name) %>:
+ return makeStyleProperty(get<%- camelize(property.name) %>());
+<% } -%>
+<% for (const property of properties) { -%>
+ case Property::<%- camelize(property.name) %>Transition:
+ return makeStyleProperty(get<%- camelize(property.name) %>Transition());
+<% } -%>
+ }
+ return {};
+}
+
<% for (const property of properties) { -%>
<%- evaluatedType(property) %> Light::getDefault<%- camelize(property.name) %>() {
return Light<%- camelize(property.name) %>::defaultValue();
@@ -138,5 +163,3 @@ TransitionOptions Light::get<%- camelize(property.name) %>Transition() const {
} // namespace style
} // namespace mbgl
-
-// clang-format on
diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp
index 5171c7c8d9..3832977cd4 100644
--- a/src/mbgl/style/sources/geojson_source.cpp
+++ b/src/mbgl/style/sources/geojson_source.cpp
@@ -32,8 +32,12 @@ void GeoJSONSource::setURL(const std::string& url_) {
}
void GeoJSONSource::setGeoJSON(const mapbox::geojson::geojson& geoJSON) {
+ setGeoJSONData(GeoJSONData::create(geoJSON, impl().getOptions()));
+}
+
+void GeoJSONSource::setGeoJSONData(std::shared_ptr<GeoJSONData> geoJSONData) {
req.reset();
- baseImpl = makeMutable<Impl>(impl(), geoJSON);
+ baseImpl = makeMutable<Impl>(impl(), std::move(geoJSONData));
observer->onSourceChanged(*this);
}
@@ -41,6 +45,10 @@ optional<std::string> GeoJSONSource::getURL() const {
return url;
}
+const GeoJSONOptions& GeoJSONSource::getOptions() const {
+ return impl().getOptions();
+}
+
void GeoJSONSource::loadDescription(FileSource& fileSource) {
if (!url) {
loaded = true;
@@ -62,17 +70,15 @@ void GeoJSONSource::loadDescription(FileSource& fileSource) {
*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON")));
} else {
conversion::Error error;
- optional<GeoJSON> geoJSON = conversion::convertJSON<GeoJSON>(*res.data, error);
- if (!geoJSON) {
+ std::shared_ptr<GeoJSONData> geoJSONData;
+ if (optional<GeoJSON> geoJSON = conversion::convertJSON<GeoJSON>(*res.data, error)) {
+ geoJSONData = GeoJSONData::create(*geoJSON, impl().getOptions());
+ } else {
+ // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for tiles to load.
Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s",
error.message.c_str());
- // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for
- // tiles to load.
- baseImpl = makeMutable<Impl>(impl(), GeoJSON{ FeatureCollection{} });
- } else {
- baseImpl = makeMutable<Impl>(impl(), *geoJSON);
}
-
+ baseImpl = makeMutable<Impl>(impl(), std::move(geoJSONData));
loaded = true;
observer->onSourceLoaded(*this);
}
diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp
index c3cb942709..468deb6134 100644
--- a/src/mbgl/style/sources/geojson_source_impl.cpp
+++ b/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -82,13 +82,8 @@ T evaluateFeature(const mapbox::feature::feature<double>& f,
return T();
}
-GeoJSONSource::Impl::Impl(std::string id_, optional<GeoJSONOptions> options_)
- : Source::Impl(SourceType::GeoJSON, std::move(id_)) {
- options = options_ ? std::move(*options_) : GeoJSONOptions{};
-}
-
-GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON)
- : Source::Impl(other), options(other.options) {
+// static
+std::shared_ptr<GeoJSONData> GeoJSONData::create(const GeoJSON& geoJSON, const GeoJSONOptions& options) {
constexpr double scale = util::EXTENT / util::tileSize;
if (options.cluster && geoJSON.is<mapbox::feature::feature_collection<double>>() &&
!geoJSON.get<mapbox::feature::feature_collection<double>>().empty()) {
@@ -99,6 +94,7 @@ GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON)
Feature feature;
clusterOptions.map = [&](const PropertyMap& properties) -> PropertyMap {
PropertyMap ret{};
+ if (properties.empty()) return ret;
for (const auto& p : options.clusterProperties) {
feature.properties = properties;
ret[p.first] = evaluateFeature<Value>(feature, p.second.first);
@@ -115,19 +111,27 @@ GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON)
toReturn[p.first] = evaluateFeature<Value>(feature, p.second.second, accumulated);
}
};
- data = std::make_shared<SuperclusterData>(
- geoJSON.get<mapbox::feature::feature_collection<double>>(), clusterOptions);
- } else {
- mapbox::geojsonvt::Options vtOptions;
- vtOptions.maxZoom = options.maxzoom;
- vtOptions.extent = util::EXTENT;
- vtOptions.buffer = ::round(scale * options.buffer);
- vtOptions.tolerance = scale * options.tolerance;
- vtOptions.lineMetrics = options.lineMetrics;
- data = std::make_shared<GeoJSONVTData>(geoJSON, vtOptions);
+ return std::make_shared<SuperclusterData>(geoJSON.get<mapbox::feature::feature_collection<double>>(),
+ clusterOptions);
}
+
+ mapbox::geojsonvt::Options vtOptions;
+ vtOptions.maxZoom = options.maxzoom;
+ vtOptions.extent = util::EXTENT;
+ vtOptions.buffer = ::round(scale * options.buffer);
+ vtOptions.tolerance = scale * options.tolerance;
+ vtOptions.lineMetrics = options.lineMetrics;
+ return std::make_shared<GeoJSONVTData>(geoJSON, vtOptions);
}
+GeoJSONSource::Impl::Impl(std::string id_, optional<GeoJSONOptions> options_)
+ : Source::Impl(SourceType::GeoJSON, std::move(id_)) {
+ options = options_ ? std::move(*options_) : GeoJSONOptions{};
+}
+
+GeoJSONSource::Impl::Impl(const GeoJSONSource::Impl& other, std::shared_ptr<GeoJSONData> data_)
+ : Source::Impl(other), options(other.options), data(std::move(data_)) {}
+
GeoJSONSource::Impl::~Impl() = default;
Range<uint8_t> GeoJSONSource::Impl::getZoomRange() const {
diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp
index 26b9d95a39..da2673a38c 100644
--- a/src/mbgl/style/sources/geojson_source_impl.hpp
+++ b/src/mbgl/style/sources/geojson_source_impl.hpp
@@ -11,27 +11,15 @@ class CanonicalTileID;
namespace style {
-class GeoJSONData {
-public:
- virtual ~GeoJSONData() = default;
- virtual mapbox::feature::feature_collection<int16_t> getTile(const CanonicalTileID&) = 0;
-
- // SuperclusterData
- virtual mapbox::feature::feature_collection<double> getChildren(const std::uint32_t) = 0;
- virtual mapbox::feature::feature_collection<double> getLeaves(const std::uint32_t,
- const std::uint32_t limit = 10u,
- const std::uint32_t offset = 0u) = 0;
- virtual std::uint8_t getClusterExpansionZoom(std::uint32_t) = 0;
-};
-
class GeoJSONSource::Impl : public Source::Impl {
public:
Impl(std::string id, optional<GeoJSONOptions>);
- Impl(const GeoJSONSource::Impl&, const GeoJSON&);
+ Impl(const GeoJSONSource::Impl&, std::shared_ptr<GeoJSONData>);
~Impl() final;
Range<uint8_t> getZoomRange() const;
std::weak_ptr<GeoJSONData> getData() const;
+ const GeoJSONOptions& getOptions() const { return options; }
optional<std::string> getAttribution() const final;
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 8b0a3975fc..ecc8f93032 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -164,12 +164,12 @@ void Placement::placeBucket(
auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom());
optional<CollisionTileBoundaries> avoidEdges;
- if (mapMode == MapMode::Tile &&
- (layout.get<style::SymbolAvoidEdges>() ||
- layout.get<style::SymbolPlacement>() == style::SymbolPlacementType::Line)) {
+ if (mapMode == MapMode::Tile && (layout.get<style::SymbolAvoidEdges>() ||
+ layout.get<style::SymbolPlacement>() == style::SymbolPlacementType::Line ||
+ !layout.get<style::TextVariableAnchor>().empty())) {
avoidEdges = collisionIndex.projectTileBoundaries(posMatrix);
}
-
+
const bool textAllowOverlap = layout.get<style::TextAllowOverlap>();
const bool iconAllowOverlap = layout.get<style::IconAllowOverlap>();
// This logic is similar to the "defaultOpacityState" logic below in updateBucketOpacities
@@ -220,7 +220,6 @@ void Placement::placeBucket(
if (horizontalTextIndex) {
const PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*horizontalTextIndex);
const float fontSize = evaluateSizeForFeature(partiallyEvaluatedTextSize, placedSymbol);
- const CollisionFeature& textCollisionFeature = symbolInstance.textCollisionFeature;
const auto updatePreviousOrientationIfNotPlaced = [&](bool isPlaced) {
if (bucket.allowVerticalPlacement && !isPlaced && getPrevPlacement()) {
@@ -282,7 +281,8 @@ void Placement::placeBucket(
placeText = placed.first;
offscreen &= placed.second;
- } else if (!textCollisionFeature.alongLine && !textCollisionFeature.boxes.empty()) {
+ } else if (!symbolInstance.textCollisionFeature.alongLine &&
+ !symbolInstance.textCollisionFeature.boxes.empty()) {
// If this symbol was in the last placement, shift the previously used
// anchor to the front of the anchor list, only if the previous anchor
// is still in the anchor list.
@@ -305,8 +305,13 @@ void Placement::placeBucket(
}
}
- const auto placeFeatureForVariableAnchors = [&] (const CollisionFeature& collisionFeature, style::TextWritingModeType orientation) {
- const CollisionBox& textBox = collisionFeature.boxes[0];
+ const bool doVariableIconPlacement =
+ hasIconTextFit && !iconAllowOverlap && symbolInstance.placedIconIndex;
+
+ const auto placeFeatureForVariableAnchors = [&](const CollisionFeature& textCollisionFeature,
+ style::TextWritingModeType orientation,
+ const CollisionFeature& iconCollisionFeature) {
+ const CollisionBox& textBox = textCollisionFeature.boxes[0];
const float width = textBox.x2 - textBox.x1;
const float height = textBox.y2 - textBox.y1;
const float textBoxScale = symbolInstance.textBoxScale;
@@ -323,12 +328,40 @@ void Placement::placeBucket(
}
textBoxes.clear();
- placedFeature = collisionIndex.placeFeature(collisionFeature, shift,
- posMatrix, mat4(), pixelRatio,
- placedSymbol, scale, fontSize,
+ placedFeature = collisionIndex.placeFeature(textCollisionFeature,
+ shift,
+ posMatrix,
+ mat4(),
+ pixelRatio,
+ placedSymbol,
+ scale,
+ fontSize,
allowOverlap,
pitchWithMap,
- params.showCollisionBoxes, avoidEdges, collisionGroup.second, textBoxes);
+ params.showCollisionBoxes,
+ avoidEdges,
+ collisionGroup.second,
+ textBoxes);
+
+ if (doVariableIconPlacement) {
+ auto placedIconFeature = collisionIndex.placeFeature(iconCollisionFeature,
+ shift,
+ posMatrix,
+ iconLabelPlaneMatrix,
+ pixelRatio,
+ placedSymbol,
+ scale,
+ fontSize,
+ iconAllowOverlap,
+ pitchWithMap,
+ params.showCollisionBoxes,
+ avoidEdges,
+ collisionGroup.second,
+ iconBoxes);
+ iconBoxes.clear();
+ if (!placedIconFeature.first) continue;
+ }
+
if (placedFeature.first) {
assert(symbolInstance.crossTileID != 0u);
optional<style::TextVariableAnchorType> prevAnchor;
@@ -366,12 +399,18 @@ void Placement::placeBucket(
};
const auto placeHorizontal = [&] {
- return placeFeatureForVariableAnchors(symbolInstance.textCollisionFeature, style::TextWritingModeType::Horizontal);
+ return placeFeatureForVariableAnchors(symbolInstance.textCollisionFeature,
+ style::TextWritingModeType::Horizontal,
+ symbolInstance.iconCollisionFeature);
};
const auto placeVertical = [&] {
if (bucket.allowVerticalPlacement && !placed.first && symbolInstance.verticalTextCollisionFeature) {
- return placeFeatureForVariableAnchors(*symbolInstance.verticalTextCollisionFeature, style::TextWritingModeType::Vertical);
+ return placeFeatureForVariableAnchors(*symbolInstance.verticalTextCollisionFeature,
+ style::TextWritingModeType::Vertical,
+ symbolInstance.verticalIconCollisionFeature
+ ? *symbolInstance.verticalIconCollisionFeature
+ : symbolInstance.iconCollisionFeature);
}
return std::pair<bool, bool>{false, false};
};
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index 281c5d99de..a94bfee336 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -20,12 +20,28 @@ SymbolQuad getIconQuad(const PositionedIcon& shapedIcon,
// If you have a 10px icon that isn't perfectly aligned to the pixel grid it will cover 11 actual
// pixels. The quad needs to be padded to account for this, otherwise they'll look slightly clipped
// on one edge in some cases.
- const float border = 1.0;
-
- float top = shapedIcon.top() - border / image.pixelRatio;
- float left = shapedIcon.left() - border / image.pixelRatio;
- float bottom = shapedIcon.bottom() + border / image.pixelRatio;
- float right = shapedIcon.right() + border / image.pixelRatio;
+ constexpr const float border = 1.0f;
+
+ // Expand the box to respect the 1 pixel border in the atlas image. We're using `image.paddedRect - border`
+ // instead of image.displaySize because we only pad with one pixel for retina images as well, and the
+ // displaySize uses the logical dimensions, not the physical pixel dimensions.
+ // Unlike the JavaScript version, we're _not_ including the padding in the texture rect, so the
+ // logic "dimension * padded / non-padded - dimension" is swapped.
+ const float iconWidth = shapedIcon.right() - shapedIcon.left();
+ const float expandX = (iconWidth * (static_cast<float>(image.textureRect.w) + 2.0f * border) /
+ static_cast<float>(image.textureRect.w) -
+ iconWidth) /
+ 2.0f;
+ const float left = shapedIcon.left() - expandX;
+ const float right = shapedIcon.right() + expandX;
+
+ const float iconHeight = shapedIcon.bottom() - shapedIcon.top();
+ const float expandY = (iconHeight * (static_cast<float>(image.textureRect.h) + 2.0f * border) /
+ static_cast<float>(image.textureRect.h) -
+ iconHeight) /
+ 2.0f;
+ const float top = shapedIcon.top() - expandY;
+ const float bottom = shapedIcon.bottom() + expandY;
Point<float> tl{left, top};
Point<float> tr{right, top};
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index d6d9a3d34e..8eb885af5d 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -32,7 +32,7 @@ AnchorAlignment AnchorAlignment::getAnchorAlignment(style::SymbolAnchorType anch
result.horizontalAlign = 0.0f;
break;
default:
- break;
+ break;
}
switch (anchor) {
@@ -83,33 +83,41 @@ PositionedIcon PositionedIcon::shapeIcon(const ImagePosition& image,
return PositionedIcon { image, top, bottom, left, right, iconRotation };
}
-void PositionedIcon::fitIconToText(const style::SymbolLayoutProperties::Evaluated& layout,
- const Shaping& shapedText,
- float layoutTextSize) {
- using namespace style;
- assert(layout.get<IconTextFit>() != IconTextFitType::None);
- if (shapedText) {
- auto iconWidth = _right - _left;
- auto iconHeight = _bottom - _top;
- auto size = layoutTextSize / 24.0f;
- auto textLeft = shapedText.left * size;
- auto textRight = shapedText.right * size;
- auto textTop = shapedText.top * size;
- auto textBottom = shapedText.bottom * size;
- auto textWidth = textRight - textLeft;
- auto textHeight = textBottom - textTop;
- auto padT = layout.get<IconTextFitPadding>()[0];
- auto padR = layout.get<IconTextFitPadding>()[1];
- auto padB = layout.get<IconTextFitPadding>()[2];
- auto padL = layout.get<IconTextFitPadding>()[3];
- auto offsetY = layout.get<IconTextFit>() == IconTextFitType::Width ? (textHeight - iconHeight) * 0.5 : 0;
- auto offsetX = layout.get<IconTextFit>() == IconTextFitType::Height ? (textWidth - iconWidth) * 0.5 : 0;
- auto width = layout.get<IconTextFit>() == IconTextFitType::Width || layout.get<IconTextFit>() == IconTextFitType::Both ? textWidth : iconWidth;
- auto height = layout.get<IconTextFit>() == IconTextFitType::Height || layout.get<IconTextFit>() == IconTextFitType::Both ? textHeight : iconHeight;
- _left = textLeft + offsetX - padL;
- _top = textTop + offsetY - padT;
- _right = textLeft + offsetX + padR + width;
- _bottom = textTop + offsetY + padB + height;
+void PositionedIcon::fitIconToText(const Shaping& shapedText,
+ const style::IconTextFitType textFit,
+ const std::array<float, 4>& padding,
+ const std::array<float, 2>& iconOffset,
+ const float fontScale) {
+ assert(textFit != style::IconTextFitType::None);
+ assert(shapedText);
+
+ // We don't respect the icon-anchor, because icon-text-fit is set. Instead,
+ // the icon will be centered on the text, then stretched in the given
+ // dimensions.
+
+ const float textLeft = shapedText.left * fontScale;
+ const float textRight = shapedText.right * fontScale;
+
+ if (textFit == style::IconTextFitType::Width || textFit == style::IconTextFitType::Both) {
+ // Stretched horizontally to the text width
+ _left = iconOffset[0] + textLeft - padding[3];
+ _right = iconOffset[0] + textRight + padding[1];
+ } else {
+ // Centered on the text
+ _left = iconOffset[0] + (textLeft + textRight - image().displaySize()[0]) / 2.0f;
+ _right = _left + image().displaySize()[0];
+ }
+
+ const float textTop = shapedText.top * fontScale;
+ const float textBottom = shapedText.bottom * fontScale;
+ if (textFit == style::IconTextFitType::Height || textFit == style::IconTextFitType::Both) {
+ // Stretched vertically to the text height
+ _top = iconOffset[1] + textTop - padding[0];
+ _bottom = iconOffset[1] + textBottom + padding[2];
+ } else {
+ // Centered on the text
+ _top = iconOffset[1] + (textTop + textBottom - image().displaySize()[1]) / 2.0f;
+ _bottom = _top + image().displaySize()[1];
}
}
diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp
index 28730e9db9..6ed1b5cb0e 100644
--- a/src/mbgl/text/shaping.hpp
+++ b/src/mbgl/text/shaping.hpp
@@ -45,9 +45,11 @@ public:
// Updates shaped icon's bounds based on shaped text's bounds and provided
// layout properties.
- void fitIconToText(const style::SymbolLayoutProperties::Evaluated& layout,
- const Shaping& shapedText,
- float layoutTextSize);
+ void fitIconToText(const Shaping& shapedText,
+ const style::IconTextFitType textFit,
+ const std::array<float, 4>& padding,
+ const std::array<float, 2>& iconOffset,
+ const float fontScale);
const ImagePosition& image() const { return _image; }
float top() const { return _top; }
diff --git a/src/mbgl/util/color.cpp b/src/mbgl/util/color.cpp
index 4c2814cf14..44f815e8b8 100644
--- a/src/mbgl/util/color.cpp
+++ b/src/mbgl/util/color.cpp
@@ -45,10 +45,7 @@ std::array<double, 4> Color::toArray() const {
}
mbgl::Value Color::toObject() const {
- return std::unordered_map<std::string, mbgl::Value>{{"r", double(r)},
- {"g", double(g)},
- {"b", double(b)},
- {"a", double(a)}};
+ return mapbox::base::ValueObject{{"r", double(r)}, {"g", double(g)}, {"b", double(b)}, {"a", double(a)}};
}
} // namespace mbgl
diff --git a/src/mbgl/util/thread_pool.cpp b/src/mbgl/util/thread_pool.cpp
index e839d1b4be..040e996dd4 100644
--- a/src/mbgl/util/thread_pool.cpp
+++ b/src/mbgl/util/thread_pool.cpp
@@ -6,53 +6,44 @@
namespace mbgl {
-ThreadPool::ThreadPool(std::size_t count) {
- threads.reserve(count);
+ThreadedSchedulerBase::~ThreadedSchedulerBase() = default;
- for (std::size_t i = 0; i < count; ++i) {
- threads.emplace_back([this, i]() {
- platform::setCurrentThreadName(std::string{ "Worker " } + util::toString(i + 1));
- platform::attachThread();
-
- while (true) {
- std::unique_lock<std::mutex> lock(mutex);
+void ThreadedSchedulerBase::terminate() {
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+ terminated = true;
+ }
+ cv.notify_all();
+}
- cv.wait(lock, [this] {
- return !queue.empty() || terminate;
- });
+std::thread ThreadedSchedulerBase::makeSchedulerThread(size_t index) {
+ return std::thread([this, index]() {
+ platform::setCurrentThreadName(std::string{"Worker "} + util::toString(index + 1));
+ platform::attachThread();
- if (terminate) {
- platform::detachThread();
- return;
- }
+ while (true) {
+ std::unique_lock<std::mutex> lock(mutex);
- auto mailbox = queue.front();
- queue.pop();
- lock.unlock();
+ cv.wait(lock, [this] { return !queue.empty() || terminated; });
- Mailbox::maybeReceive(mailbox);
+ if (terminated) {
+ platform::detachThread();
+ return;
}
- });
- }
-}
-ThreadPool::~ThreadPool() {
- {
- std::lock_guard<std::mutex> lock(mutex);
- terminate = true;
- }
-
- cv.notify_all();
-
- for (auto& thread : threads) {
- thread.join();
- }
+ auto function = std::move(queue.front());
+ queue.pop();
+ lock.unlock();
+ if (function) function();
+ }
+ });
}
-void ThreadPool::schedule(std::weak_ptr<Mailbox> mailbox) {
+void ThreadedSchedulerBase::schedule(std::function<void()> fn) {
+ assert(fn);
{
std::lock_guard<std::mutex> lock(mutex);
- queue.push(mailbox);
+ queue.push(std::move(fn));
}
cv.notify_one();
diff --git a/src/mbgl/util/thread_pool.hpp b/src/mbgl/util/thread_pool.hpp
index 509fd06061..7642f9b4ca 100644
--- a/src/mbgl/util/thread_pool.hpp
+++ b/src/mbgl/util/thread_pool.hpp
@@ -3,6 +3,7 @@
#include <mbgl/actor/mailbox.hpp>
#include <mbgl/actor/scheduler.hpp>
+#include <array>
#include <condition_variable>
#include <mutex>
#include <queue>
@@ -10,19 +11,60 @@
namespace mbgl {
-class ThreadPool final : public Scheduler {
+class ThreadedSchedulerBase : public Scheduler {
public:
- explicit ThreadPool(std::size_t count);
- ~ThreadPool() override;
+ void schedule(std::function<void()>) override;
- void schedule(std::weak_ptr<Mailbox>) override;
+protected:
+ ThreadedSchedulerBase() = default;
+ ~ThreadedSchedulerBase() override;
-private:
- std::vector<std::thread> threads;
- std::queue<std::weak_ptr<Mailbox>> queue;
+ void terminate();
+ std::thread makeSchedulerThread(size_t index);
+
+ std::queue<std::function<void()>> queue;
std::mutex mutex;
std::condition_variable cv;
- bool terminate{ false };
+ bool terminated{false};
+};
+
+/**
+ * @brief ThreadScheduler implements Scheduler interface using a lightweight event loop
+ *
+ * @tparam N number of threads
+ *
+ * Note: If N == 1 all scheduled tasks are guaranteed to execute consequently;
+ * otherwise, some of the scheduled tasks might be executed in parallel.
+ */
+template <std::size_t N>
+class ThreadedScheduler : public ThreadedSchedulerBase {
+public:
+ ThreadedScheduler() {
+ for (std::size_t i = 0u; i < N; ++i) {
+ threads[i] = makeSchedulerThread(i);
+ }
+ }
+
+ ~ThreadedScheduler() override {
+ terminate();
+ for (auto& thread : threads) {
+ thread.join();
+ }
+ }
+
+ mapbox::base::WeakPtr<Scheduler> makeWeakPtr() override { return weakFactory.makeWeakPtr(); }
+
+private:
+ std::array<std::thread, N> threads;
+ mapbox::base::WeakPtrFactory<Scheduler> weakFactory{this};
+ static_assert(N > 0, "Thread count must be more than zero.");
};
+using SequencedScheduler = ThreadedScheduler<1>;
+
+template <std::size_t extra>
+using ParallelScheduler = ThreadedScheduler<1 + extra>;
+
+using ThreadPool = ParallelScheduler<3>;
+
} // namespace mbgl