summaryrefslogtreecommitdiff
path: root/src/mbgl
diff options
context:
space:
mode:
authorAlexander Shalamov <alexander.shalamov@mapbox.com>2019-10-30 10:21:17 +0200
committerAlexander Shalamov <alexander.shalamov@mapbox.com>2019-11-11 18:20:01 +0200
commitc6f3cc8b60e0cff032020a780d4fd3de1cb2a112 (patch)
tree155fe444f21ae88dda664e81cfc8378e28297b0e /src/mbgl
parente1556fc539607db626b978040895716c1564c9b9 (diff)
downloadqtlocation-mapboxgl-c6f3cc8b60e0cff032020a780d4fd3de1cb2a112.tar.gz
[core] Implement image expression (#15877)
* [core] Bump gl-js version * [core] Implement image expression * [core] Use new image expression * [core] Coerce image expression to / from string * [core] Serialize evaluated image * [core] Pass available images to layout * [core] Pass images to evaluation context * [core] Set available flag value based on image availability * [core] Allow image coercion to boolean to indicate image availability * [core] Coalesce image expression * [core] Add image expression to next build system * [core] Align serialization format and evaluated type with gl-js * [core] Add images to expression evaluation method * [core] Add support for Image expression to expression test runner * [core] Unskip image expression tests * [core] Update unit tests * [core] Use image expression in annotation manager * [core] Add string to ImageExpression conversion * [core] Add image expression to expression dsl * [core] Convert tokens for implicitly created Image literal * [core] Fix clang format * [core] Split generated style code lines that are over 120 characters * [core] Add unit test for image expression equality * [core] Add image property expression evaluation unit test * [core] Unskip image expression render test * [core] Skip 'in' expression tests * [core] Ignore fill-pattern/update-feature-state render test * [core] Rename Image::serialize to Image::toValue
Diffstat (limited to 'src/mbgl')
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp14
-rw-r--r--src/mbgl/layermanager/fill_extrusion_layer_factory.cpp2
-rw-r--r--src/mbgl/layermanager/fill_layer_factory.cpp2
-rw-r--r--src/mbgl/layermanager/line_layer_factory.cpp2
-rw-r--r--src/mbgl/layermanager/symbol_layer_factory.cpp6
-rw-r--r--src/mbgl/layout/layout.hpp1
-rw-r--r--src/mbgl/layout/pattern_layout.hpp46
-rw-r--r--src/mbgl/layout/symbol_feature.hpp5
-rw-r--r--src/mbgl/layout/symbol_layout.cpp23
-rw-r--r--src/mbgl/layout/symbol_layout.hpp5
-rw-r--r--src/mbgl/renderer/cross_faded_property_evaluator.cpp3
-rw-r--r--src/mbgl/renderer/data_driven_property_evaluator.hpp8
-rw-r--r--src/mbgl/renderer/image_manager.cpp6
-rw-r--r--src/mbgl/renderer/image_manager.hpp3
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp10
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp32
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.cpp35
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp31
-rw-r--r--src/mbgl/renderer/possibly_evaluated_property_value.hpp11
-rw-r--r--src/mbgl/style/conversion/function.cpp66
-rw-r--r--src/mbgl/style/conversion/property_value.cpp8
-rw-r--r--src/mbgl/style/conversion/stringify.hpp5
-rw-r--r--src/mbgl/style/expression/check_subtype.cpp15
-rw-r--r--src/mbgl/style/expression/coalesce.cpp14
-rw-r--r--src/mbgl/style/expression/coercion.cpp27
-rw-r--r--src/mbgl/style/expression/dsl.cpp27
-rw-r--r--src/mbgl/style/expression/expression.cpp14
-rw-r--r--src/mbgl/style/expression/image.cpp67
-rw-r--r--src/mbgl/style/expression/image_expression.cpp68
-rw-r--r--src/mbgl/style/expression/is_constant.cpp13
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp19
-rw-r--r--src/mbgl/style/expression/value.cpp153
-rw-r--r--src/mbgl/style/layers/background_layer.cpp15
-rw-r--r--src/mbgl/style/layers/background_layer_properties.hpp4
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp31
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.hpp2
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer.cpp31
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_properties.hpp6
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp29
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.hpp6
-rw-r--r--src/mbgl/style/layers/heatmap_layer.cpp8
-rw-r--r--src/mbgl/style/layers/hillshade_layer.cpp15
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs15
-rw-r--r--src/mbgl/style/layers/line_layer.cpp40
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp8
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp19
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp76
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp22
-rw-r--r--src/mbgl/style/properties.hpp22
-rw-r--r--src/mbgl/style/property_expression.cpp16
-rw-r--r--src/mbgl/tile/geometry_tile.cpp6
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp14
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp12
53 files changed, 720 insertions, 418 deletions
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp
index 345171b96e..b5dfea8e1a 100644
--- a/src/mbgl/annotation/annotation_manager.cpp
+++ b/src/mbgl/annotation/annotation_manager.cpp
@@ -1,15 +1,16 @@
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/annotation/annotation_source.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
-#include <mbgl/annotation/symbol_annotation_impl.hpp>
-#include <mbgl/annotation/line_annotation_impl.hpp>
#include <mbgl/annotation/fill_annotation_impl.hpp>
+#include <mbgl/annotation/line_annotation_impl.hpp>
+#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/layermanager/layer_manager.hpp>
-#include <mbgl/style/style.hpp>
-#include <mbgl/style/style_impl.hpp>
+#include <mbgl/style/expression/dsl.hpp>
+#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
-#include <mbgl/style/expression/dsl.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/style_impl.hpp>
#include <boost/function_output_iterator.hpp>
@@ -184,7 +185,8 @@ void AnnotationManager::updateStyle() {
using namespace expression::dsl;
layer->setSourceLayer(PointLayerID);
- layer->setIconImage(PropertyExpression<std::string>(concat(vec(literal(SourceID + "."), toString(get("sprite"))))));
+ layer->setIconImage(PropertyExpression<expression::Image>(
+ image(concat(vec(literal(SourceID + "."), toString(get("sprite")))))));
layer->setIconAllowOverlap(true);
layer->setIconIgnorePlacement(true);
diff --git a/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp b/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp
index 0163321914..e1bedb5246 100644
--- a/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp
+++ b/src/mbgl/layermanager/fill_extrusion_layer_factory.cpp
@@ -29,7 +29,7 @@ std::unique_ptr<Layout> FillExtrusionLayerFactory::createLayout(const LayoutPara
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
using namespace style;
using LayoutType = PatternLayout<FillExtrusionBucket, FillExtrusionLayerProperties, FillExtrusionPattern>;
- return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies);
+ return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters);
}
std::unique_ptr<RenderLayer> FillExtrusionLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {
diff --git a/src/mbgl/layermanager/fill_layer_factory.cpp b/src/mbgl/layermanager/fill_layer_factory.cpp
index f7f24c58a1..265fdc69f6 100644
--- a/src/mbgl/layermanager/fill_layer_factory.cpp
+++ b/src/mbgl/layermanager/fill_layer_factory.cpp
@@ -30,7 +30,7 @@ FillLayerFactory::createLayout(const LayoutParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
using namespace style;
using LayoutType = PatternLayout<FillBucket, FillLayerProperties, FillPattern>;
- return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies);
+ return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters);
}
std::unique_ptr<RenderLayer> FillLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {
diff --git a/src/mbgl/layermanager/line_layer_factory.cpp b/src/mbgl/layermanager/line_layer_factory.cpp
index b0f2827a80..5770b19f33 100644
--- a/src/mbgl/layermanager/line_layer_factory.cpp
+++ b/src/mbgl/layermanager/line_layer_factory.cpp
@@ -29,7 +29,7 @@ std::unique_ptr<Layout> LineLayerFactory::createLayout(const LayoutParameters& p
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
using namespace style;
using LayoutType = PatternLayout<LineBucket, LineLayerProperties, LinePattern, LineLayoutProperties::PossiblyEvaluated>;
- return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies);
+ return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters);
}
std::unique_ptr<RenderLayer> LineLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {
diff --git a/src/mbgl/layermanager/symbol_layer_factory.cpp b/src/mbgl/layermanager/symbol_layer_factory.cpp
index 7141f5a223..11a4f09ec3 100644
--- a/src/mbgl/layermanager/symbol_layer_factory.cpp
+++ b/src/mbgl/layermanager/symbol_layer_factory.cpp
@@ -27,11 +27,7 @@ std::unique_ptr<style::Layer> SymbolLayerFactory::createLayer(const std::string&
std::unique_ptr<Layout> SymbolLayerFactory::createLayout(const LayoutParameters& parameters,
std::unique_ptr<GeometryTileLayer> tileLayer,
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
- return std::make_unique<SymbolLayout>(parameters.bucketParameters,
- group,
- std::move(tileLayer),
- parameters.imageDependencies,
- parameters.glyphDependencies);
+ return std::make_unique<SymbolLayout>(parameters.bucketParameters, group, std::move(tileLayer), parameters);
}
std::unique_ptr<RenderLayer> SymbolLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {
diff --git a/src/mbgl/layout/layout.hpp b/src/mbgl/layout/layout.hpp
index d1f03792c1..91d3e3f596 100644
--- a/src/mbgl/layout/layout.hpp
+++ b/src/mbgl/layout/layout.hpp
@@ -38,6 +38,7 @@ public:
const BucketParameters& bucketParameters;
GlyphDependencies& glyphDependencies;
ImageDependencies& imageDependencies;
+ std::set<std::string>& availableImages;
};
} // namespace mbgl
diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp
index d6d878955f..48531e836b 100644
--- a/src/mbgl/layout/pattern_layout.hpp
+++ b/src/mbgl/layout/pattern_layout.hpp
@@ -1,8 +1,9 @@
#pragma once
+#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/layout/layout.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
-#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layer_properties.hpp>
namespace mbgl {
@@ -32,11 +33,11 @@ public:
PatternLayout(const BucketParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& group,
std::unique_ptr<GeometryTileLayer> sourceLayer_,
- ImageDependencies& patternDependencies)
- : sourceLayer(std::move(sourceLayer_)),
- zoom(parameters.tileID.overscaledZ),
- overscaling(parameters.tileID.overscaleFactor()),
- hasPattern(false) {
+ const LayoutParameters& layoutParameters)
+ : sourceLayer(std::move(sourceLayer_)),
+ zoom(parameters.tileID.overscaledZ),
+ overscaling(parameters.tileID.overscaleFactor()),
+ hasPattern(false) {
assert(!group.empty());
auto leaderLayerProperties = staticImmutableCast<LayerPropertiesType>(group.front());
layout = leaderLayerProperties->layerImpl().layout.evaluate(PropertyEvaluationParameters(zoom));
@@ -47,15 +48,15 @@ public:
const std::string& layerId = layerProperties->baseImpl->id;
const auto& evaluated = style::getEvaluated<LayerPropertiesType>(layerProperties);
const auto patternProperty = evaluated.template get<PatternPropertyType>();
- const auto constantPattern = patternProperty.constantOr(Faded<std::basic_string<char> >{ "", ""});
+ const auto constantPattern = patternProperty.constantOr(Faded<style::expression::Image>{"", ""});
// determine if layer group has any layers that use *-pattern property and add
// constant pattern dependencies.
if (!patternProperty.isConstant()) {
hasPattern = true;
- } else if (!constantPattern.to.empty()){
+ } else if (!constantPattern.to.id().empty()) {
hasPattern = true;
- patternDependencies.emplace(constantPattern.to, ImageType::Pattern);
- patternDependencies.emplace(constantPattern.from, ImageType::Pattern);
+ layoutParameters.imageDependencies.emplace(constantPattern.to.id(), ImageType::Pattern);
+ layoutParameters.imageDependencies.emplace(constantPattern.from.id(), ImageType::Pattern);
}
layerPropertiesMap.emplace(layerId, layerProperties);
}
@@ -77,15 +78,22 @@ public:
if (!patternProperty.isConstant()) {
// For layers with non-data-constant pattern properties, evaluate their expression and add
// the patterns to the dependency vector
- const auto min = patternProperty.evaluate(*feature, zoom - 1, PatternPropertyType::defaultValue());
- const auto mid = patternProperty.evaluate(*feature, zoom, PatternPropertyType::defaultValue());
- const auto max = patternProperty.evaluate(*feature, zoom + 1, PatternPropertyType::defaultValue());
-
- patternDependencies.emplace(min.to, ImageType::Pattern);
- patternDependencies.emplace(mid.to, ImageType::Pattern);
- patternDependencies.emplace(max.to, ImageType::Pattern);
- patternDependencyMap.emplace(layerId, PatternDependency {min.to, mid.to, max.to});
-
+ const auto min = patternProperty.evaluate(*feature,
+ zoom - 1,
+ layoutParameters.availableImages,
+ PatternPropertyType::defaultValue());
+ const auto mid = patternProperty.evaluate(
+ *feature, zoom, layoutParameters.availableImages, PatternPropertyType::defaultValue());
+ const auto max = patternProperty.evaluate(*feature,
+ zoom + 1,
+ layoutParameters.availableImages,
+ PatternPropertyType::defaultValue());
+
+ layoutParameters.imageDependencies.emplace(min.to.id(), ImageType::Pattern);
+ layoutParameters.imageDependencies.emplace(mid.to.id(), ImageType::Pattern);
+ layoutParameters.imageDependencies.emplace(max.to.id(), ImageType::Pattern);
+ patternDependencyMap.emplace(layerId,
+ PatternDependency{min.to.id(), mid.to.id(), max.to.id()});
}
}
}
diff --git a/src/mbgl/layout/symbol_feature.hpp b/src/mbgl/layout/symbol_feature.hpp
index 03d8e5018d..d0aced1b19 100644
--- a/src/mbgl/layout/symbol_feature.hpp
+++ b/src/mbgl/layout/symbol_feature.hpp
@@ -1,8 +1,9 @@
#pragma once
+#include <mbgl/style/expression/image.hpp>
+#include <mbgl/text/tagged_string.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/util/optional.hpp>
-#include <mbgl/text/tagged_string.hpp>
#include <array>
#include <string>
@@ -29,7 +30,7 @@ public:
std::unique_ptr<GeometryTileFeature> feature;
GeometryCollection geometry;
optional<TaggedString> formattedText;
- optional<std::string> icon;
+ optional<style::expression::Image> icon;
float sortKey = 0.0f;
std::size_t index;
bool allowsVerticalWritingMode = false;
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index d0227c36c5..af0b1bd21b 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -81,8 +81,7 @@ inline Immutable<style::SymbolLayoutProperties::PossiblyEvaluated> createLayout(
SymbolLayout::SymbolLayout(const BucketParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& layers,
std::unique_ptr<GeometryTileLayer> sourceLayer_,
- ImageDependencies& imageDependencies,
- GlyphDependencies& glyphDependencies)
+ const LayoutParameters& layoutParameters)
: bucketLeaderID(layers.front()->baseImpl->id),
sourceLayer(std::move(sourceLayer_)),
overscaling(parameters.tileID.overscaleFactor()),
@@ -141,7 +140,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
ft.index = i;
if (hasText) {
- auto formatted = layout->evaluate<TextField>(zoom, ft);
+ auto formatted = layout->evaluate<TextField>(zoom, ft, layoutParameters.availableImages);
auto textTransform = layout->evaluate<TextTransform>(zoom, ft);
FontStack baseFontStack = layout->evaluate<TextFont>(zoom, ft);
@@ -168,7 +167,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
// Loop through all characters of this text and collect unique codepoints.
for (std::size_t j = 0; j < ft.formattedText->length(); j++) {
const auto& sectionFontStack = formatted.sections[ft.formattedText->getSectionIndex(j)].fontStack;
- GlyphIDs& dependencies = glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack];
+ GlyphIDs& dependencies =
+ layoutParameters.glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack];
char16_t codePoint = ft.formattedText->getCharCodeAt(j);
dependencies.insert(codePoint);
if (canVerticalizeText || (allowVerticalPlacement && ft.formattedText->allowsVerticalWritingMode())) {
@@ -180,8 +180,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
}
if (hasIcon) {
- ft.icon = layout->evaluate<IconImage>(zoom, ft);
- imageDependencies.emplace(*ft.icon, ImageType::Icon);
+ ft.icon = layout->evaluate<IconImage>(zoom, ft, layoutParameters.availableImages);
+ layoutParameters.imageDependencies.emplace(ft.icon->id(), ImageType::Icon);
}
if (ft.formattedText || ft.icon) {
@@ -448,14 +448,13 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
// if feature has icon, get sprite atlas position
SymbolContent iconType{SymbolContent::None};
if (feature.icon) {
- auto image = imageMap.find(*feature.icon);
+ auto image = imageMap.find(feature.icon->id());
if (image != imageMap.end()) {
iconType = SymbolContent::IconRGBA;
- shapedIcon = PositionedIcon::shapeIcon(
- imagePositions.at(*feature.icon),
- layout->evaluate<IconOffset>(zoom, feature),
- layout->evaluate<IconAnchor>(zoom, feature),
- layout->evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
+ shapedIcon = PositionedIcon::shapeIcon(imagePositions.at(feature.icon->id()),
+ layout->evaluate<IconOffset>(zoom, feature),
+ layout->evaluate<IconAnchor>(zoom, feature),
+ layout->evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
if (image->second->sdf) {
iconType = SymbolContent::IconSDF;
}
diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp
index 1abcaaa5d6..2b99c2fa24 100644
--- a/src/mbgl/layout/symbol_layout.hpp
+++ b/src/mbgl/layout/symbol_layout.hpp
@@ -27,9 +27,8 @@ public:
SymbolLayout(const BucketParameters&,
const std::vector<Immutable<style::LayerProperties>>&,
std::unique_ptr<GeometryTileLayer>,
- ImageDependencies&,
- GlyphDependencies&);
-
+ const LayoutParameters& parameters);
+
~SymbolLayout() final = default;
void prepareSymbols(const GlyphMap&, const GlyphPositions&,
diff --git a/src/mbgl/renderer/cross_faded_property_evaluator.cpp b/src/mbgl/renderer/cross_faded_property_evaluator.cpp
index 7be9c2bcf5..65f5b31467 100644
--- a/src/mbgl/renderer/cross_faded_property_evaluator.cpp
+++ b/src/mbgl/renderer/cross_faded_property_evaluator.cpp
@@ -1,4 +1,5 @@
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
+#include <mbgl/style/expression/image.hpp>
#include <mbgl/util/chrono.hpp>
#include <cmath>
@@ -30,7 +31,7 @@ Faded<T> CrossFadedPropertyEvaluator<T>::calculate(const T& min, const T& mid, c
: Faded<T> { max, mid };
}
-template class CrossFadedPropertyEvaluator<std::string>;
+template class CrossFadedPropertyEvaluator<style::expression::Image>;
template class CrossFadedPropertyEvaluator<std::vector<float>>;
} // namespace mbgl
diff --git a/src/mbgl/renderer/data_driven_property_evaluator.hpp b/src/mbgl/renderer/data_driven_property_evaluator.hpp
index efac9e4532..c2e6d9f283 100644
--- a/src/mbgl/renderer/data_driven_property_evaluator.hpp
+++ b/src/mbgl/renderer/data_driven_property_evaluator.hpp
@@ -26,14 +26,14 @@ public:
ResultType operator()(const style::PropertyExpression<T>& expression) const {
if (useIntegerZoom) { // Compiler will optimize out the unused branch.
- if (!expression.isFeatureConstant()) {
+ if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) {
auto returnExpression = expression;
returnExpression.useIntegerZoom = true;
return ResultType(returnExpression);
- }
+ }
return ResultType(expression.evaluate(floor(parameters.z)));
} else {
- if (!expression.isFeatureConstant()) {
+ if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) {
return ResultType(expression);
}
return ResultType(expression.evaluate(parameters.z));
@@ -63,7 +63,7 @@ public:
}
ResultType operator()(const style::PropertyExpression<T>& expression) const {
- if (!expression.isFeatureConstant()) {
+ if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) {
return ResultType(expression);
} else {
const T evaluated = expression.evaluate(floor(parameters.z));
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp
index 2ea753d8aa..4927ade8e9 100644
--- a/src/mbgl/renderer/image_manager.cpp
+++ b/src/mbgl/renderer/image_manager.cpp
@@ -43,6 +43,7 @@ void ImageManager::addImage(Immutable<style::Image::Impl> image_) {
if (requestedImages.find(image_->id) != requestedImages.end()) {
requestedImagesCacheSize += image_->image.bytes();
}
+ availableImages.emplace(image_->id);
images.emplace(image_->id, std::move(image_));
}
@@ -81,6 +82,7 @@ void ImageManager::removeImage(const std::string& id) {
requestedImages.erase(requestedIt);
}
images.erase(it);
+ availableImages.erase(id);
updatedImageVersions.erase(id);
}
@@ -169,6 +171,10 @@ void ImageManager::reduceMemoryUseIfCacheSizeExceedsLimit() {
}
}
+const std::set<std::string>& ImageManager::getAvailableImages() const {
+ return availableImages;
+}
+
void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) {
ImageDependencies missingDependencies;
diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp
index 5ed6e237f0..7d5884edc1 100644
--- a/src/mbgl/renderer/image_manager.hpp
+++ b/src/mbgl/renderer/image_manager.hpp
@@ -47,6 +47,7 @@ public:
void notifyIfMissingImageAdded();
void reduceMemoryUse();
void reduceMemoryUseIfCacheSizeExceedsLimit();
+ const std::set<std::string>& getAvailableImages() const;
ImageVersionMap updatedImageVersions;
@@ -62,6 +63,8 @@ private:
std::map<std::string, std::set<ImageRequestor*>> requestedImages;
std::size_t requestedImagesCacheSize = 0ul;
ImageMap images;
+ // Mirror of 'ImageMap images;' keys.
+ std::set<std::string> availableImages;
ImageManagerObserver* observer = nullptr;
};
diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp
index 6f76efda7a..694addcc97 100644
--- a/src/mbgl/renderer/layers/render_background_layer.cpp
+++ b/src/mbgl/renderer/layers/render_background_layer.cpp
@@ -105,8 +105,10 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) {
const auto& evaluated = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).evaluated;
const auto& crossfade = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).crossfade;
if (!evaluated.get<BackgroundPattern>().to.empty()) {
- optional<ImagePosition> imagePosA = parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().from);
- optional<ImagePosition> imagePosB = parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().to);
+ optional<ImagePosition> imagePosA =
+ parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().from.id());
+ optional<ImagePosition> imagePosB =
+ parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().to.id());
if (!imagePosA || !imagePosB)
return;
@@ -176,8 +178,8 @@ void RenderBackgroundLayer::prepare(const LayerPrepareParameters& params) {
if (!evaluated.get<BackgroundPattern>().to.empty()) {
// Ensures that the pattern bitmap gets copied to atlas bitmap.
// Atlas bitmap is uploaded to atlas texture in upload.
- addPatternIfNeeded(evaluated.get<BackgroundPattern>().from, params);
- addPatternIfNeeded(evaluated.get<BackgroundPattern>().to, params);
+ addPatternIfNeeded(evaluated.get<BackgroundPattern>().from.id(), params);
+ addPatternIfNeeded(evaluated.get<BackgroundPattern>().to.id(), params);
}
}
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
index fc830e462c..af0bc788d0 100644
--- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
@@ -1,20 +1,21 @@
-#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/gfx/cull_face_mode.hpp>
+#include <mbgl/gfx/render_pass.hpp>
+#include <mbgl/gfx/renderer_backend.hpp>
+#include <mbgl/programs/fill_extrusion_program.hpp>
+#include <mbgl/programs/programs.hpp>
#include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp>
-#include <mbgl/renderer/render_tile.hpp>
-#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_static_data.hpp>
-#include <mbgl/programs/programs.hpp>
-#include <mbgl/programs/fill_extrusion_program.hpp>
-#include <mbgl/tile/tile.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
-#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/util/math.hpp>
-#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/gfx/renderer_backend.hpp>
-#include <mbgl/gfx/render_pass.hpp>
-#include <mbgl/gfx/cull_face_mode.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -171,7 +172,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
}
} else {
// Draw textured extrusions
- const auto fillPatternValue = evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<std::basic_string<char> >{"", ""});
+ const auto fillPatternValue =
+ evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<expression::Image>{"", ""});
auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) {
for (const RenderTile& tile : *renderTiles) {
const LayerRenderData* renderData = getRenderDataForPass(tile, parameters.pass);
@@ -179,8 +181,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
continue;
}
auto& bucket = static_cast<FillExtrusionBucket&>(*renderData->bucket);
- optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from);
- optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to);
+ optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from.id());
+ optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to.id());
draw(
parameters.programs.getFillExtrusionLayerPrograms().fillExtrusionPattern,
diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp
index e855866eea..bbfcef7aba 100644
--- a/src/mbgl/renderer/layers/render_fill_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_layer.cpp
@@ -1,21 +1,22 @@
-#include <mbgl/renderer/layers/render_fill_layer.hpp>
-#include <mbgl/renderer/buckets/fill_bucket.hpp>
-#include <mbgl/renderer/render_tile.hpp>
-#include <mbgl/renderer/render_source.hpp>
-#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/renderer/image_manager.hpp>
-#include <mbgl/programs/programs.hpp>
-#include <mbgl/programs/fill_program.hpp>
-#include <mbgl/tile/tile.hpp>
-#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/gfx/renderer_backend.hpp>
-#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/context.hpp>
+#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/renderable.hpp>
-#include <mbgl/util/math.hpp>
-#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/gfx/renderer_backend.hpp>
+#include <mbgl/programs/fill_program.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/renderer/buckets/fill_bucket.hpp>
+#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/renderer/layers/render_fill_layer.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/style/expression/image.hpp>
+#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -171,9 +172,9 @@ void RenderFillLayer::render(PaintParameters& parameters) {
const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties);
const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties);
- const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<std::basic_string<char>>{"", ""});
- optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from);
- optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to);
+ const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<expression::Image>{"", ""});
+ optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from.id());
+ optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to.id());
auto draw = [&] (auto& programInstance,
const auto& drawMode,
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index e5bbe74bf9..588cf6286c 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -1,20 +1,21 @@
-#include <mbgl/renderer/layers/render_line_layer.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/geometry/line_atlas.hpp>
+#include <mbgl/gfx/cull_face_mode.hpp>
+#include <mbgl/programs/line_program.hpp>
+#include <mbgl/programs/programs.hpp>
#include <mbgl/renderer/buckets/line_bucket.hpp>
-#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/renderer/layers/render_line_layer.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/upload_parameters.hpp>
-#include <mbgl/renderer/paint_parameters.hpp>
-#include <mbgl/renderer/image_manager.hpp>
-#include <mbgl/programs/programs.hpp>
-#include <mbgl/programs/line_program.hpp>
-#include <mbgl/geometry/line_atlas.hpp>
-#include <mbgl/tile/tile.hpp>
+#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
-#include <mbgl/gfx/cull_face_mode.hpp>
-#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/util/math.hpp>
-#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/util/intersection_tests.hpp>
+#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -168,11 +169,11 @@ void RenderLineLayer::render(PaintParameters& parameters) {
});
} else if (!unevaluated.get<LinePattern>().isUndefined()) {
- const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""});
+ const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<expression::Image>{"", ""});
const Size& texsize = tile.getIconAtlasTexture().size;
- optional<ImagePosition> posA = tile.getPattern(linePatternValue.from);
- optional<ImagePosition> posB = tile.getPattern(linePatternValue.to);
+ optional<ImagePosition> posA = tile.getPattern(linePatternValue.from.id());
+ optional<ImagePosition> posB = tile.getPattern(linePatternValue.to.id());
draw(parameters.programs.getLineLayerPrograms().linePattern,
LinePatternProgram::layoutUniformValues(
diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
index 1198e43aae..5e412855a4 100644
--- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp
+++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
@@ -93,16 +93,19 @@ public:
}
template <class Feature>
- Faded<T> evaluate(const Feature& feature, float zoom, T defaultValue) const {
+ Faded<T> evaluate(const Feature& feature,
+ float zoom,
+ const std::set<std::string>& availableImages,
+ T defaultValue) const {
return this->match(
[&] (const Faded<T>& constant_) { return constant_; },
[&] (const style::PropertyExpression<T>& expression) {
if (!expression.isZoomConstant()) {
- const T min = expression.evaluate(floor(zoom), feature, defaultValue);
- const T max = expression.evaluate(floor(zoom) + 1, feature, defaultValue);
+ const T min = expression.evaluate(floor(zoom), feature, availableImages, defaultValue);
+ const T max = expression.evaluate(floor(zoom) + 1, feature, availableImages, defaultValue);
return Faded<T> {min, max};
} else {
- const T evaluated = expression.evaluate(feature, defaultValue);
+ const T evaluated = expression.evaluate(feature, availableImages, defaultValue);
return Faded<T> {evaluated, evaluated};
}
}
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 646c1983a2..4b3b8f6c6a 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -1,13 +1,14 @@
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/style/expression/case.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/dsl_impl.hpp>
-#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/format_expression.hpp>
+#include <mbgl/style/expression/image_expression.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/match.hpp>
-#include <mbgl/style/expression/case.hpp>
-#include <mbgl/style/expression/format_expression.hpp>
+#include <mbgl/style/expression/step.hpp>
#include <mbgl/util/string.hpp>
#include <cassert>
@@ -46,6 +47,10 @@ std::unique_ptr<Expression> convertTokenStringToFormatExpression(const std::stri
return std::make_unique<FormatExpression>(sections);
}
+std::unique_ptr<Expression> convertTokenStringToImageExpression(const std::string& source) {
+ return std::make_unique<ImageExpression>(convertTokenStringToExpression(source));
+}
+
std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& source) {
std::vector<std::unique_ptr<Expression>> inputs;
@@ -149,11 +154,11 @@ template optional<PropertyExpression<TextTransformType>>
convertFunctionToExpression<TextTransformType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TranslateAnchorType>>
convertFunctionToExpression<TranslateAnchorType>(const Convertible&, Error&, bool);
-
template optional<PropertyExpression<Formatted>>
convertFunctionToExpression<Formatted>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::vector<TextWritingModeType>>>
convertFunctionToExpression<std::vector<TextWritingModeType>>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<Image>> convertFunctionToExpression<Image>(const Convertible&, Error&, bool);
// Ad-hoc Converters for double and int64_t. We should replace float with double wholesale,
// and promote the int64_t Converter to general use (and it should check that the input is
@@ -207,35 +212,35 @@ static bool interpolatable(type::Type type) {
static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error, bool convertTokens = false) {
return type.match(
- [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<float>(value, error);
if (!result) {
return nullopt;
}
return literal(double(*result));
},
- [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<bool>(value, error);
if (!result) {
return nullopt;
}
return literal(*result);
},
- [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::StringType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<std::string>(value, error);
if (!result) {
return nullopt;
}
return convertTokens ? convertTokenStringToExpression(*result) : literal(*result);
},
- [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<Color>(value, error);
if (!result) {
return nullopt;
}
return literal(*result);
},
- [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::Array& array) -> optional<std::unique_ptr<Expression>> {
if (!isArray(value)) {
error.message = "value must be an array";
return nullopt;
@@ -277,27 +282,27 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con
}
);
},
- [&] (const type::NullType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::NullType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
- [&] (const type::ObjectType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::ObjectType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
- [&] (const type::ErrorType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::ErrorType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
- [&] (const type::ValueType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::ValueType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
- [&] (const type::CollatorType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::CollatorType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
- [&] (const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<std::string>(value, error);
if (!result) {
return nullopt;
@@ -305,8 +310,15 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con
return convertTokens ?
convertTokenStringToFormatExpression(*result) :
literal(Formatted(result->c_str()));
- }
- );
+ },
+ [&](const type::ImageType&) -> optional<std::unique_ptr<Expression>> {
+ auto result = convert<std::string>(value, error);
+ if (!result) {
+ return nullopt;
+ }
+ return convertTokens ? std::make_unique<ImageExpression>(convertTokenStringToImageExpression(*result))
+ : literal(Image(result->c_str()));
+ });
}
static optional<std::map<double, std::unique_ptr<Expression>>> convertStops(type::Type type,
@@ -749,29 +761,31 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ
if (functionType == FunctionType::Identity) {
return type.match(
- [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::StringType&) -> optional<std::unique_ptr<Expression>> {
return string(get(literal(*property)), defaultExpr());
},
- [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
return number(get(literal(*property)), defaultExpr());
},
- [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
return boolean(get(literal(*property)), defaultExpr());
},
- [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
return toColor(get(literal(*property)), defaultExpr());
},
- [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::Array& array) -> optional<std::unique_ptr<Expression>> {
return assertion(array, get(literal(*property)), defaultExpr());
},
- [&] (const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
return toFormatted(get(literal(*property)), defaultExpr());
},
- [&] (const auto&) -> optional<std::unique_ptr<Expression>> {
+ [&](const type::ImageType&) -> optional<std::unique_ptr<Expression>> {
+ return toImage(get(literal(*property)), defaultExpr());
+ },
+ [&](const auto&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
- }
- );
+ });
}
auto stopsValue = objectMember(value, "stops");
diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp
index 5c2f720a60..5e03189e64 100644
--- a/src/mbgl/style/conversion/property_value.cpp
+++ b/src/mbgl/style/conversion/property_value.cpp
@@ -39,7 +39,8 @@ optional<PropertyValue<T>> Converter<PropertyValue<T>>::operator()(const Convert
} else if (!allowDataExpressions && !(*expression).isFeatureConstant()) {
error.message = "data expressions not supported";
return nullopt;
- } else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant()) {
+ } else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant() ||
+ !(*expression).isRuntimeConstant()) {
return { std::move(*expression) };
} else if ((*expression).getExpression().getKind() == Kind::Literal) {
optional<T> constant = fromExpressionValue<T>(
@@ -81,6 +82,11 @@ template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<Text
template optional<PropertyValue<TranslateAnchorType>> Converter<PropertyValue<TranslateAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<mbgl::style::expression::Formatted>> Converter<PropertyValue<mbgl::style::expression::Formatted>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<std::vector<TextWritingModeType>>> Converter<PropertyValue<std::vector<TextWritingModeType>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<mbgl::style::expression::Image>>
+Converter<PropertyValue<mbgl::style::expression::Image>>::operator()(conversion::Convertible const&,
+ conversion::Error&,
+ bool,
+ bool) const;
} // namespace conversion
} // namespace style
diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp
index 7520bcac9c..3816182450 100644
--- a/src/mbgl/style/conversion/stringify.hpp
+++ b/src/mbgl/style/conversion/stringify.hpp
@@ -142,6 +142,11 @@ void stringify(Writer& writer, const expression::Formatted& v) {
}
template <class Writer>
+void stringify(Writer& writer, const expression::Image& v) {
+ stringify(writer, expression::ValueConverter<mbgl::Value>::fromExpressionValue(v));
+}
+
+template <class Writer>
void stringify(Writer& writer, const Undefined&) {
assert(false); // Should be omitted entirely instead.
writer.Null();
diff --git a/src/mbgl/style/expression/check_subtype.cpp b/src/mbgl/style/expression/check_subtype.cpp
index 73e6e3bff7..9895bce667 100644
--- a/src/mbgl/style/expression/check_subtype.cpp
+++ b/src/mbgl/style/expression/check_subtype.cpp
@@ -32,18 +32,9 @@ optional<std::string> checkSubtype(const Type& expected, const Type& t) {
},
[&] (const ValueType&) -> optional<std::string> {
if (t.is<ValueType>()) return {};
-
- const Type members[] = {
- Null,
- Boolean,
- Number,
- String,
- Object,
- Color,
- Formatted,
- Array(Value)
- };
-
+
+ const Type members[] = {Null, Boolean, Number, String, Object, Color, Formatted, Image, Array(Value)};
+
for (const auto& member : members) {
const auto err = checkSubtype(member, t);
if (!err) {
diff --git a/src/mbgl/style/expression/coalesce.cpp b/src/mbgl/style/expression/coalesce.cpp
index 6b43e68ac6..ab30e7a8df 100644
--- a/src/mbgl/style/expression/coalesce.cpp
+++ b/src/mbgl/style/expression/coalesce.cpp
@@ -8,8 +8,22 @@ namespace expression {
EvaluationResult Coalesce::evaluate(const EvaluationContext& params) const {
EvaluationResult result = Null;
+ std::size_t argsCount = args.size();
+ optional<Image> requestedImage;
for (const auto& arg : args) {
+ --argsCount;
result = arg->evaluate(params);
+ // We need to keep track of the first requested image in a coalesce statement.
+ // If coalesce can't find a valid image, we return the first requested image.
+ if (getType() == type::Image && result) {
+ const auto image = fromExpressionValue<Image>(*result);
+ if (image && !image->isAvailable()) {
+ if (!requestedImage) requestedImage = Image(image->id());
+ if (!argsCount) result = *requestedImage;
+ continue;
+ }
+ }
+
if (!result || *result != Null) break;
}
return result;
diff --git a/src/mbgl/style/expression/coercion.cpp b/src/mbgl/style/expression/coercion.cpp
index 284d6f2e3e..d65558e28d 100644
--- a/src/mbgl/style/expression/coercion.cpp
+++ b/src/mbgl/style/expression/coercion.cpp
@@ -9,13 +9,12 @@ namespace style {
namespace expression {
EvaluationResult toBoolean(const Value& v) {
- return v.match(
- [&] (double f) { return static_cast<bool>(f); },
- [&] (const std::string& s) { return s.length() > 0; },
- [&] (bool b) { return b; },
- [&] (const NullValue&) { return false; },
- [&] (const auto&) { return true; }
- );
+ return v.match([&](double f) { return static_cast<bool>(f); },
+ [&](const std::string& s) { return s.length() > 0; },
+ [&](bool b) { return b; },
+ [&](const NullValue&) { return false; },
+ [&](const Image& i) { return i.isAvailable(); },
+ [&](const auto&) { return true; });
}
EvaluationResult toNumber(const Value& v) {
@@ -86,6 +85,10 @@ EvaluationResult toFormatted(const Value& formattedValue) {
return Formatted(toString(formattedValue).c_str());
}
+EvaluationResult toImage(const Value& imageValue) {
+ return Image(toString(imageValue).c_str());
+}
+
Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_) :
Expression(Kind::Coercion, std::move(type_)),
inputs(std::move(inputs_))
@@ -102,6 +105,8 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in
coerceSingleValue = [] (const Value& v) -> EvaluationResult { return toString(v); };
} else if (t.is<type::FormattedType>()) {
coerceSingleValue = toFormatted;
+ } else if (t.is<type::ImageType>()) {
+ coerceSingleValue = toImage;
} else {
assert(false);
}
@@ -115,6 +120,8 @@ mbgl::Value Coercion::serialize() const {
serialized.push_back(inputs[0]->serialize());
serialized.emplace_back(std::unordered_map<std::string, mbgl::Value>());
return serialized;
+ } else if (getType().is<type::ImageType>()) {
+ return std::vector<mbgl::Value>{{std::string("image")}, inputs[0]->serialize()};
} else {
return Expression::serialize();
}
@@ -148,11 +155,13 @@ ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) {
auto it = types.find(*toString(arrayMember(value, 0)));
assert(it != types.end());
- if ((it->second == type::Boolean || it->second == type::String || it->second == type::Formatted) && length != 2) {
+ if ((it->second == type::Boolean || it->second == type::String || it->second == type::Formatted ||
+ it->second == type::Image) &&
+ length != 2) {
ctx.error("Expected one argument.");
return ParseResult();
}
-
+
/**
* Special form for error-coalescing coercion expressions "to-number",
* "to-color". Since these coercions can fail at runtime, they accept multiple
diff --git a/src/mbgl/style/expression/dsl.cpp b/src/mbgl/style/expression/dsl.cpp
index fac7dfbbd9..6405149fe9 100644
--- a/src/mbgl/style/expression/dsl.cpp
+++ b/src/mbgl/style/expression/dsl.cpp
@@ -1,14 +1,15 @@
-#include <mbgl/style/expression/dsl.hpp>
-#include <mbgl/style/expression/dsl_impl.hpp>
-#include <mbgl/style/expression/error.hpp>
-#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/assertion.hpp>
#include <mbgl/style/expression/coercion.hpp>
#include <mbgl/style/expression/comparison.hpp>
-#include <mbgl/style/expression/step.hpp>
-#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/dsl.hpp>
+#include <mbgl/style/expression/dsl_impl.hpp>
+#include <mbgl/style/expression/error.hpp>
#include <mbgl/style/expression/format_expression.hpp>
+#include <mbgl/style/expression/image_expression.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/literal.hpp>
+#include <mbgl/style/expression/step.hpp>
#include <mapbox/geojsonvt.hpp>
#include <mbgl/style/conversion/json.hpp>
@@ -122,7 +123,11 @@ std::unique_ptr<Expression> toFormatted(std::unique_ptr<Expression> value,
std::unique_ptr<Expression> def) {
return coercion(type::Formatted, std::move(value), std::move(def));
}
-
+
+std::unique_ptr<Expression> toImage(std::unique_ptr<Expression> value, std::unique_ptr<Expression> def) {
+ return coercion(type::Image, std::move(value), std::move(def));
+}
+
std::unique_ptr<Expression> get(const char* value) {
return get(literal(value));
}
@@ -237,6 +242,14 @@ std::unique_ptr<Expression> format(std::unique_ptr<Expression> input) {
return std::make_unique<FormatExpression>(sections);
}
+std::unique_ptr<Expression> image(const char* value) {
+ return std::make_unique<Literal>(Image(value));
+}
+
+std::unique_ptr<Expression> image(std::unique_ptr<Expression> expression) {
+ return std::make_unique<ImageExpression>(std::move(expression));
+}
+
} // namespace dsl
} // namespace expression
} // namespace style
diff --git a/src/mbgl/style/expression/expression.cpp b/src/mbgl/style/expression/expression.cpp
index 6bfda99064..3252bb632f 100644
--- a/src/mbgl/style/expression/expression.cpp
+++ b/src/mbgl/style/expression/expression.cpp
@@ -25,12 +25,22 @@ public:
return optional<mbgl::Value>();
}
};
-
-EvaluationResult Expression::evaluate(optional<float> zoom, const Feature& feature, optional<double> colorRampParameter) const {
+
+EvaluationResult Expression::evaluate(optional<float> zoom,
+ const Feature& feature,
+ optional<double> colorRampParameter) const {
GeoJSONFeature f(feature);
return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter));
}
+EvaluationResult Expression::evaluate(optional<float> zoom,
+ const Feature& feature,
+ optional<double> colorRampParameter,
+ const std::set<std::string>& availableImages) const {
+ GeoJSONFeature f(feature);
+ return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter).withAvailableImages(&availableImages));
+}
+
EvaluationResult Expression::evaluate(optional<mbgl::Value> accumulated, const Feature& feature) const {
GeoJSONFeature f(feature);
return this->evaluate(EvaluationContext(accumulated, &f));
diff --git a/src/mbgl/style/expression/image.cpp b/src/mbgl/style/expression/image.cpp
new file mode 100644
index 0000000000..1dc7acde56
--- /dev/null
+++ b/src/mbgl/style/expression/image.cpp
@@ -0,0 +1,67 @@
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/style/expression/image.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+Image::Image(std::string imageID_, bool available_) : imageID(std::move(imageID_)), available(available_) {}
+
+Image::Image(std::string imageID_) : Image(std::move(imageID_), false) {}
+
+Image::Image(const char* imageID_) : Image(std::string(imageID_)) {
+ assert(imageID_);
+}
+
+bool Image::operator==(const Image& other) const {
+ return imageID == other.imageID && available == other.available;
+}
+
+mbgl::Value Image::toValue() const {
+ return mapbox::base::ValueObject{{"name", imageID}, {"available", available}};
+}
+
+const std::string& Image::id() const {
+ return imageID;
+}
+
+bool Image::isAvailable() const {
+ return available;
+}
+
+bool Image::empty() const {
+ return imageID.empty();
+}
+
+} // namespace expression
+
+namespace conversion {
+using namespace mbgl::style::expression;
+optional<Image> Converter<Image>::operator()(const Convertible& value, Error& error) const {
+ if (isArray(value)) {
+ Convertible imageParameters = arrayMember(value, 0);
+ std::size_t imageParametersLength = arrayLength(imageParameters);
+ if (imageParametersLength < 1) {
+ error.message = "Image has to contain an ID.";
+ return nullopt;
+ }
+
+ optional<std::string> imageID = toString(arrayMember(imageParameters, 0));
+ if (!imageID) {
+ error.message = "Image has to contain an ID.";
+ return nullopt;
+ }
+
+ return Image(*imageID, false);
+ } else if (optional<std::string> result = toString(value)) {
+ return Image(*result, false);
+ } else {
+ error.message = "Image must be plain string or array type.";
+ return nullopt;
+ }
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/image_expression.cpp b/src/mbgl/style/expression/image_expression.cpp
new file mode 100644
index 0000000000..df535d4e81
--- /dev/null
+++ b/src/mbgl/style/expression/image_expression.cpp
@@ -0,0 +1,68 @@
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/style/expression/image.hpp>
+#include <mbgl/style/expression/image_expression.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+ImageExpression::ImageExpression(std::unique_ptr<Expression> imageID_)
+ : Expression(Kind::ImageExpression, type::Image), imageID(std::move(imageID_)) {
+ assert(imageID);
+}
+
+using namespace mbgl::style::conversion;
+
+ParseResult ImageExpression::parse(const Convertible& value, ParsingContext& ctx) {
+ std::size_t argsLength = arrayLength(value);
+ if (argsLength < 2) {
+ ctx.error("Invalid number of arguments for 'image' expression.");
+ return ParseResult();
+ }
+
+ // Parse expression that evaluates to image id.
+ auto imageIDArg = arrayMember(value, 1);
+ ParseResult imageIDExpr = ctx.parse(imageIDArg, 1, {type::String});
+ if (!imageIDExpr) {
+ return ParseResult();
+ }
+
+ return ParseResult(std::make_unique<ImageExpression>(std::move(*imageIDExpr)));
+}
+
+void ImageExpression::eachChild(const std::function<void(const Expression&)>& fn) const {
+ fn(*imageID);
+}
+
+bool ImageExpression::operator==(const Expression& e) const {
+ if (e.getKind() == Kind::ImageExpression) {
+ auto rhs = static_cast<const ImageExpression*>(&e);
+ return *imageID == *rhs->imageID;
+ }
+ return false;
+}
+
+mbgl::Value ImageExpression::serialize() const {
+ std::vector<mbgl::Value> serialized{{getOperator()}};
+ serialized.push_back(imageID->serialize());
+ return serialized;
+}
+
+EvaluationResult ImageExpression::evaluate(const EvaluationContext& ctx) const {
+ auto imageIDResult = imageID->evaluate(ctx);
+ if (!imageIDResult) {
+ return imageIDResult.error();
+ }
+
+ optional<std::string> evaluatedImageID = toString(*imageIDResult);
+ if (!evaluatedImageID) {
+ return EvaluationError({"Could not evaluate ID for 'image' expression."});
+ }
+
+ bool available = ctx.availableImages && ctx.availableImages->count(*evaluatedImageID);
+ return Image(*evaluatedImageID, available);
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp
index 4c4684c86a..eb823bc77c 100644
--- a/src/mbgl/style/expression/is_constant.cpp
+++ b/src/mbgl/style/expression/is_constant.cpp
@@ -49,6 +49,19 @@ bool isZoomConstant(const Expression& e) {
return isGlobalPropertyConstant(e, std::array<std::string, 1>{{"zoom"}});
}
+bool isRuntimeConstant(const Expression& expression) {
+ if (expression.getKind() == Kind::ImageExpression) {
+ return false;
+ }
+
+ bool runtimeConstant = true;
+ expression.eachChild([&](const Expression& e) {
+ if (runtimeConstant && !isRuntimeConstant(e)) {
+ runtimeConstant = false;
+ }
+ });
+ return runtimeConstant;
+}
} // namespace expression
} // namespace style
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 699190608b..ae991b2e88 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -4,22 +4,23 @@
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/type.hpp>
-#include <mbgl/style/expression/expression.hpp>
-#include <mbgl/style/expression/at.hpp>
#include <mbgl/style/expression/assertion.hpp>
+#include <mbgl/style/expression/at.hpp>
#include <mbgl/style/expression/boolean_operator.hpp>
#include <mbgl/style/expression/case.hpp>
#include <mbgl/style/expression/coalesce.hpp>
#include <mbgl/style/expression/coercion.hpp>
-#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/comparison.hpp>
-#include <mbgl/style/expression/number_format.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/format_expression.hpp>
+#include <mbgl/style/expression/image_expression.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/length.hpp>
#include <mbgl/style/expression/let.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/match.hpp>
+#include <mbgl/style/expression/number_format.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/find_zoom_curve.hpp>
@@ -117,7 +118,7 @@ MAPBOX_ETERNAL_CONSTEXPR const auto expressionRegistry =
{"coalesce", Coalesce::parse},
{"collator", CollatorExpression::parse},
{"format", FormatExpression::parse},
- {"image", Assertion::parse}, // TODO: replace once we implement image expressions
+ {"image", ImageExpression::parse},
{"interpolate", parseInterpolate},
{"length", Length::parse},
{"let", Let::parse},
@@ -193,7 +194,8 @@ ParseResult ParsingContext::parse(const Convertible& value, optional<TypeAnnotat
const type::Type actual = (*parsed)->getType();
if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object || expected->is<type::Array>()) && actual == type::Value) {
parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::assert)) };
- } else if ((*expected == type::Color || *expected == type::Formatted) && (actual == type::Value || actual == type::String)) {
+ } else if ((*expected == type::Color || *expected == type::Formatted || *expected == type::Image) &&
+ (actual == type::Value || actual == type::String)) {
parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::coerce)) };
} else {
checkType((*parsed)->getType());
@@ -205,8 +207,9 @@ ParseResult ParsingContext::parse(const Convertible& value, optional<TypeAnnotat
// If an expression's arguments are all constant, we can evaluate
// it immediately and replace it with a literal value in the
- // parsed result.
- if ((*parsed)->getKind() != Kind::Literal && isConstant(**parsed)) {
+ // parsed/compiled result. Expressions that expect an image should
+ // not be resolved here so we can later get the available images.
+ if ((*parsed)->getKind() != Kind::Literal && (*parsed)->getType() != type::Image && isConstant(**parsed)) {
EvaluationContext params(nullptr);
EvaluationResult evaluated((*parsed)->evaluate(params));
if (!evaluated) {
diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp
index 6d18f1b9bd..7609230b52 100644
--- a/src/mbgl/style/expression/value.cpp
+++ b/src/mbgl/style/expression/value.cpp
@@ -8,81 +8,78 @@ namespace style {
namespace expression {
type::Type typeOf(const Value& value) {
- return value.match(
- [&](bool) -> type::Type { return type::Boolean; },
- [&](double) -> type::Type { return type::Number; },
- [&](const std::string&) -> type::Type { return type::String; },
- [&](const Color&) -> type::Type { return type::Color; },
- [&](const Collator&) -> type::Type { return type::Collator; },
- [&](const Formatted&) -> type::Type { return type::Formatted; },
- [&](const NullValue&) -> type::Type { return type::Null; },
- [&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; },
- [&](const std::vector<Value>& arr) -> type::Type {
- optional<type::Type> itemType;
- for (const auto& item : arr) {
- const type::Type t = typeOf(item);
- if (!itemType) {
- itemType = {t};
- } else if (*itemType == t) {
- continue;
- } else {
- itemType = {type::Value};
- break;
- }
- }
-
- return type::Array(itemType.value_or(type::Value), arr.size());
- }
- );
+ return value.match([&](bool) -> type::Type { return type::Boolean; },
+ [&](double) -> type::Type { return type::Number; },
+ [&](const std::string&) -> type::Type { return type::String; },
+ [&](const Color&) -> type::Type { return type::Color; },
+ [&](const Collator&) -> type::Type { return type::Collator; },
+ [&](const Formatted&) -> type::Type { return type::Formatted; },
+ [&](const Image&) -> type::Type { return type::Image; },
+ [&](const NullValue&) -> type::Type { return type::Null; },
+ [&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; },
+ [&](const std::vector<Value>& arr) -> type::Type {
+ optional<type::Type> itemType;
+ for (const auto& item : arr) {
+ const type::Type t = typeOf(item);
+ if (!itemType) {
+ itemType = {t};
+ } else if (*itemType == t) {
+ continue;
+ } else {
+ itemType = {type::Value};
+ break;
+ }
+ }
+
+ return type::Array(itemType.value_or(type::Value), arr.size());
+ });
}
std::string toString(const Value& value) {
- return value.match(
- [](const NullValue&) { return std::string(); },
- [](const Color& c) { return c.stringify(); }, // avoid quoting
- [](const Formatted& f) { return f.toString(); },
- [](const std::string& s) { return s; }, // avoid quoting
- [](const auto& v_) { return stringify(v_); }
- );
+ return value.match([](const NullValue&) { return std::string(); },
+ [](const Color& c) { return c.stringify(); }, // avoid quoting
+ [](const Formatted& f) { return f.toString(); },
+ [](const Image& i) { return i.id(); },
+ [](const std::string& s) { return s; }, // avoid quoting
+ [](const auto& v_) { return stringify(v_); });
}
void writeJSON(rapidjson::Writer<rapidjson::StringBuffer>& writer, const Value& value) {
- value.match(
- [&] (const NullValue&) { writer.Null(); },
- [&] (bool b) { writer.Bool(b); },
- [&] (double f) {
- // make sure integer values are stringified without trailing ".0".
- f == std::floor(f) ? writer.Int(f) : writer.Double(f);
- },
- [&] (const std::string& s) { writer.String(s); },
- [&] (const Color& c) { writer.String(c.stringify()); },
- [&] (const Collator&) {
- // Collators are excluded from constant folding and there's no Literal parser
- // for them so there shouldn't be any way to serialize this value.
- assert(false);
- },
- [&] (const Formatted& f) {
- // `stringify` in turns calls ValueConverter::fromExpressionValue below
- // Serialization strategy for Formatted objects is to return the constant
- // expression that would generate them.
- mbgl::style::conversion::stringify(writer, f);
- },
- [&] (const std::vector<Value>& arr) {
- writer.StartArray();
- for(const auto& item : arr) {
- writeJSON(writer, item);
- }
- writer.EndArray();
- },
- [&] (const std::unordered_map<std::string, Value>& obj) {
- writer.StartObject();
- for(const auto& entry : obj) {
- writer.Key(entry.first.c_str());
- writeJSON(writer, entry.second);
- }
- writer.EndObject();
- }
- );
+ value.match([&](const NullValue&) { writer.Null(); },
+ [&](bool b) { writer.Bool(b); },
+ [&](double f) {
+ // make sure integer values are stringified without trailing ".0".
+ f == std::floor(f) ? writer.Int(f) : writer.Double(f);
+ },
+ [&](const std::string& s) { writer.String(s); },
+ [&](const Color& c) { writer.String(c.stringify()); },
+ [&](const Collator&) {
+ // Collators are excluded from constant folding and there's no Literal parser
+ // for them so there shouldn't be any way to serialize this value.
+ assert(false);
+ },
+ [&](const Formatted& f) {
+ // `stringify` in turns calls ValueConverter::fromExpressionValue below
+ // Serialization strategy for Formatted objects is to return the constant
+ // expression that would generate them.
+ mbgl::style::conversion::stringify(writer, f);
+ },
+ [&](const Image& i) { mbgl::style::conversion::stringify(writer, i); },
+ [&](const std::vector<Value>& arr) {
+ writer.StartArray();
+ for (const auto& item : arr) {
+ writeJSON(writer, item);
+ }
+ writer.EndArray();
+ },
+ [&](const std::unordered_map<std::string, Value>& obj) {
+ writer.StartObject();
+ for (const auto& entry : obj) {
+ writer.Key(entry.first.c_str());
+ writeJSON(writer, entry.second);
+ }
+ writer.EndObject();
+ });
}
std::string stringify(const Value& value) {
@@ -129,7 +126,7 @@ Value ValueConverter<mbgl::Value>::toExpressionValue(const mbgl::Value& value) {
mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) {
return value.match(
- [&](const Color& color)->mbgl::Value {
+ [&](const Color& color) -> mbgl::Value {
std::array<double, 4> array = color.toArray();
return std::vector<mbgl::Value>{
std::string("rgba"),
@@ -139,13 +136,13 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
array[3],
};
},
- [&](const Collator&)->mbgl::Value {
+ [&](const Collator&) -> mbgl::Value {
// fromExpressionValue can't be used for Collator values,
// because they have no meaningful representation as an mbgl::Value
assert(false);
return mbgl::Value();
},
- [&](const Formatted& formatted)->mbgl::Value {
+ [&](const Formatted& formatted) -> mbgl::Value {
// Serialization strategy for Formatted objects is to return the constant
// expression that would generate them.
std::vector<mbgl::Value> serialized;
@@ -175,7 +172,8 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
}
return serialized;
},
- [&](const std::vector<Value>& values)->mbgl::Value {
+ [&](const Image& i) -> mbgl::Value { return i.toValue(); },
+ [&](const std::vector<Value>& values) -> mbgl::Value {
std::vector<mbgl::Value> converted;
converted.reserve(values.size());
for (const Value& v : values) {
@@ -183,7 +181,7 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
}
return converted;
},
- [&](const std::unordered_map<std::string, Value>& values)->mbgl::Value {
+ [&](const std::unordered_map<std::string, Value>& values) -> mbgl::Value {
std::unordered_map<std::string, mbgl::Value> converted;
converted.reserve(values.size());
for(const auto& entry : values) {
@@ -191,8 +189,7 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
}
return converted;
},
- [&](const auto& a)->mbgl::Value { return a; }
- );
+ [&](const auto& a) -> mbgl::Value { return a; });
}
Value ValueConverter<float>::toExpressionValue(const float value) {
@@ -302,6 +299,10 @@ template <> type::Type valueTypeToExpressionType<std::string>() { return type::S
template <> type::Type valueTypeToExpressionType<Color>() { return type::Color; }
template <> type::Type valueTypeToExpressionType<Collator>() { return type::Collator; }
template <> type::Type valueTypeToExpressionType<Formatted>() { return type::Formatted; }
+template <>
+type::Type valueTypeToExpressionType<Image>() {
+ return type::Image;
+}
template <> type::Type valueTypeToExpressionType<std::unordered_map<std::string, Value>>() { return type::Object; }
template <> type::Type valueTypeToExpressionType<std::vector<Value>>() { return type::Array(type::Value); }
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
index 9187784452..6629044018 100644
--- a/src/mbgl/style/layers/background_layer.cpp
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -64,7 +64,7 @@ void BackgroundLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringB
// Paint properties
PropertyValue<Color> BackgroundLayer::getDefaultBackgroundColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& BackgroundLayer::getBackgroundColor() const {
@@ -91,7 +91,7 @@ TransitionOptions BackgroundLayer::getBackgroundColorTransition() const {
}
PropertyValue<float> BackgroundLayer::getDefaultBackgroundOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& BackgroundLayer::getBackgroundOpacity() const {
@@ -117,15 +117,15 @@ TransitionOptions BackgroundLayer::getBackgroundOpacityTransition() const {
return impl().paint.template get<BackgroundOpacity>().options;
}
-PropertyValue<std::string> BackgroundLayer::getDefaultBackgroundPattern() {
- return { "" };
+PropertyValue<expression::Image> BackgroundLayer::getDefaultBackgroundPattern() {
+ return {{}};
}
-const PropertyValue<std::string>& BackgroundLayer::getBackgroundPattern() const {
+const PropertyValue<expression::Image>& BackgroundLayer::getBackgroundPattern() const {
return impl().paint.template get<BackgroundPattern>().value;
}
-void BackgroundLayer::setBackgroundPattern(const PropertyValue<std::string>& value) {
+void BackgroundLayer::setBackgroundPattern(const PropertyValue<expression::Image>& value) {
if (value == getBackgroundPattern())
return;
auto impl_ = mutableImpl();
@@ -208,7 +208,8 @@ optional<Error> BackgroundLayer::setPaintProperty(const std::string& name, const
if (property == Property::BackgroundPattern) {
Error error;
- optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, false, false);
+ optional<PropertyValue<expression::Image>> typedValue =
+ convert<PropertyValue<expression::Image>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/background_layer_properties.hpp b/src/mbgl/style/layers/background_layer_properties.hpp
index 11328f78bb..b926295c00 100644
--- a/src/mbgl/style/layers/background_layer_properties.hpp
+++ b/src/mbgl/style/layers/background_layer_properties.hpp
@@ -24,8 +24,8 @@ struct BackgroundOpacity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
-struct BackgroundPattern : CrossFadedPaintProperty<std::string> {
- static std::string defaultValue() { return ""; }
+struct BackgroundPattern : CrossFadedPaintProperty<expression::Image> {
+ static expression::Image defaultValue() { return {}; }
};
class BackgroundPaintProperties : public Properties<
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index 145d76a9a8..619c58c366 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -64,7 +64,7 @@ void CircleLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe
// Paint properties
PropertyValue<float> CircleLayer::getDefaultCircleBlur() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& CircleLayer::getCircleBlur() const {
@@ -91,7 +91,7 @@ TransitionOptions CircleLayer::getCircleBlurTransition() const {
}
PropertyValue<Color> CircleLayer::getDefaultCircleColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& CircleLayer::getCircleColor() const {
@@ -118,7 +118,7 @@ TransitionOptions CircleLayer::getCircleColorTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& CircleLayer::getCircleOpacity() const {
@@ -145,7 +145,7 @@ TransitionOptions CircleLayer::getCircleOpacityTransition() const {
}
PropertyValue<AlignmentType> CircleLayer::getDefaultCirclePitchAlignment() {
- return { AlignmentType::Viewport };
+ return {AlignmentType::Viewport};
}
const PropertyValue<AlignmentType>& CircleLayer::getCirclePitchAlignment() const {
@@ -172,7 +172,7 @@ TransitionOptions CircleLayer::getCirclePitchAlignmentTransition() const {
}
PropertyValue<CirclePitchScaleType> CircleLayer::getDefaultCirclePitchScale() {
- return { CirclePitchScaleType::Map };
+ return {CirclePitchScaleType::Map};
}
const PropertyValue<CirclePitchScaleType>& CircleLayer::getCirclePitchScale() const {
@@ -199,7 +199,7 @@ TransitionOptions CircleLayer::getCirclePitchScaleTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleRadius() {
- return { 5 };
+ return {5};
}
const PropertyValue<float>& CircleLayer::getCircleRadius() const {
@@ -226,7 +226,7 @@ TransitionOptions CircleLayer::getCircleRadiusTransition() const {
}
PropertyValue<Color> CircleLayer::getDefaultCircleStrokeColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& CircleLayer::getCircleStrokeColor() const {
@@ -253,7 +253,7 @@ TransitionOptions CircleLayer::getCircleStrokeColorTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleStrokeOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& CircleLayer::getCircleStrokeOpacity() const {
@@ -280,7 +280,7 @@ TransitionOptions CircleLayer::getCircleStrokeOpacityTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleStrokeWidth() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& CircleLayer::getCircleStrokeWidth() const {
@@ -307,7 +307,7 @@ TransitionOptions CircleLayer::getCircleStrokeWidthTransition() const {
}
PropertyValue<std::array<float, 2>> CircleLayer::getDefaultCircleTranslate() {
- return { {{ 0, 0 }} };
+ return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& CircleLayer::getCircleTranslate() const {
@@ -334,7 +334,7 @@ TransitionOptions CircleLayer::getCircleTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> CircleLayer::getDefaultCircleTranslateAnchor() {
- return { TranslateAnchorType::Map };
+ return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& CircleLayer::getCircleTranslateAnchor() const {
@@ -497,7 +497,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::CirclePitchScale) {
Error error;
- optional<PropertyValue<CirclePitchScaleType>> typedValue = convert<PropertyValue<CirclePitchScaleType>>(value, error, false, false);
+ optional<PropertyValue<CirclePitchScaleType>> typedValue =
+ convert<PropertyValue<CirclePitchScaleType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -509,7 +510,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::CircleTranslate) {
Error error;
- optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ optional<PropertyValue<std::array<float, 2>>> typedValue =
+ convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -521,7 +523,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::CircleTranslateAnchor) {
Error error;
- optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ optional<PropertyValue<TranslateAnchorType>> typedValue =
+ convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp
index a5f7a584df..5204421d0b 100644
--- a/src/mbgl/style/layers/circle_layer_properties.hpp
+++ b/src/mbgl/style/layers/circle_layer_properties.hpp
@@ -53,7 +53,7 @@ struct CircleStrokeWidth : DataDrivenPaintProperty<float, attributes::stroke_wid
};
struct CircleTranslate : PaintProperty<std::array<float, 2>> {
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct CircleTranslateAnchor : PaintProperty<TranslateAnchorType> {
diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp
index 87e196926f..e04e192298 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer.cpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp
@@ -64,7 +64,7 @@ void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::Stri
// Paint properties
PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionBase() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionBase() const {
@@ -91,7 +91,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionBaseTransition() const {
}
PropertyValue<Color> FillExtrusionLayer::getDefaultFillExtrusionColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& FillExtrusionLayer::getFillExtrusionColor() const {
@@ -118,7 +118,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionColorTransition() const {
}
PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionHeight() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionHeight() const {
@@ -145,7 +145,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionHeightTransition() const {
}
PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionOpacity() const {
@@ -171,15 +171,15 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionOpacityTransition() const
return impl().paint.template get<FillExtrusionOpacity>().options;
}
-PropertyValue<std::string> FillExtrusionLayer::getDefaultFillExtrusionPattern() {
- return { "" };
+PropertyValue<expression::Image> FillExtrusionLayer::getDefaultFillExtrusionPattern() {
+ return {{}};
}
-const PropertyValue<std::string>& FillExtrusionLayer::getFillExtrusionPattern() const {
+const PropertyValue<expression::Image>& FillExtrusionLayer::getFillExtrusionPattern() const {
return impl().paint.template get<FillExtrusionPattern>().value;
}
-void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue<std::string>& value) {
+void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue<expression::Image>& value) {
if (value == getFillExtrusionPattern())
return;
auto impl_ = mutableImpl();
@@ -199,7 +199,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionPatternTransition() const
}
PropertyValue<std::array<float, 2>> FillExtrusionLayer::getDefaultFillExtrusionTranslate() {
- return { {{ 0, 0 }} };
+ return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& FillExtrusionLayer::getFillExtrusionTranslate() const {
@@ -226,7 +226,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateTransition() cons
}
PropertyValue<TranslateAnchorType> FillExtrusionLayer::getDefaultFillExtrusionTranslateAnchor() {
- return { TranslateAnchorType::Map };
+ return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& FillExtrusionLayer::getFillExtrusionTranslateAnchor() const {
@@ -253,7 +253,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateAnchorTransition(
}
PropertyValue<bool> FillExtrusionLayer::getDefaultFillExtrusionVerticalGradient() {
- return { true };
+ return {true};
}
const PropertyValue<bool>& FillExtrusionLayer::getFillExtrusionVerticalGradient() const {
@@ -382,7 +382,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co
if (property == Property::FillExtrusionPattern) {
Error error;
- optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false);
+ optional<PropertyValue<expression::Image>> typedValue =
+ convert<PropertyValue<expression::Image>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -394,7 +395,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co
if (property == Property::FillExtrusionTranslate) {
Error error;
- optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ optional<PropertyValue<std::array<float, 2>>> typedValue =
+ convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -406,7 +408,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co
if (property == Property::FillExtrusionTranslateAnchor) {
Error error;
- optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ optional<PropertyValue<TranslateAnchorType>> typedValue =
+ convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
index 6936d5e0c4..60a2340b0d 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer_properties.hpp
@@ -32,12 +32,12 @@ struct FillExtrusionOpacity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
-struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
- static std::string defaultValue() { return ""; }
+struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
+ static expression::Image defaultValue() { return {}; }
};
struct FillExtrusionTranslate : PaintProperty<std::array<float, 2>> {
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct FillExtrusionTranslateAnchor : PaintProperty<TranslateAnchorType> {
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
index e3d6c6c708..ad1f0ae847 100644
--- a/src/mbgl/style/layers/fill_layer.cpp
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -64,7 +64,7 @@ void FillLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>
// Paint properties
PropertyValue<bool> FillLayer::getDefaultFillAntialias() {
- return { true };
+ return {true};
}
const PropertyValue<bool>& FillLayer::getFillAntialias() const {
@@ -91,7 +91,7 @@ TransitionOptions FillLayer::getFillAntialiasTransition() const {
}
PropertyValue<Color> FillLayer::getDefaultFillColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& FillLayer::getFillColor() const {
@@ -118,7 +118,7 @@ TransitionOptions FillLayer::getFillColorTransition() const {
}
PropertyValue<float> FillLayer::getDefaultFillOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& FillLayer::getFillOpacity() const {
@@ -145,7 +145,7 @@ TransitionOptions FillLayer::getFillOpacityTransition() const {
}
PropertyValue<Color> FillLayer::getDefaultFillOutlineColor() {
- return { {} };
+ return {{}};
}
const PropertyValue<Color>& FillLayer::getFillOutlineColor() const {
@@ -171,15 +171,15 @@ TransitionOptions FillLayer::getFillOutlineColorTransition() const {
return impl().paint.template get<FillOutlineColor>().options;
}
-PropertyValue<std::string> FillLayer::getDefaultFillPattern() {
- return { "" };
+PropertyValue<expression::Image> FillLayer::getDefaultFillPattern() {
+ return {{}};
}
-const PropertyValue<std::string>& FillLayer::getFillPattern() const {
+const PropertyValue<expression::Image>& FillLayer::getFillPattern() const {
return impl().paint.template get<FillPattern>().value;
}
-void FillLayer::setFillPattern(const PropertyValue<std::string>& value) {
+void FillLayer::setFillPattern(const PropertyValue<expression::Image>& value) {
if (value == getFillPattern())
return;
auto impl_ = mutableImpl();
@@ -199,7 +199,7 @@ TransitionOptions FillLayer::getFillPatternTransition() const {
}
PropertyValue<std::array<float, 2>> FillLayer::getDefaultFillTranslate() {
- return { {{ 0, 0 }} };
+ return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& FillLayer::getFillTranslate() const {
@@ -226,7 +226,7 @@ TransitionOptions FillLayer::getFillTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> FillLayer::getDefaultFillTranslateAnchor() {
- return { TranslateAnchorType::Map };
+ return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& FillLayer::getFillTranslateAnchor() const {
@@ -351,7 +351,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::FillPattern) {
Error error;
- optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false);
+ optional<PropertyValue<expression::Image>> typedValue =
+ convert<PropertyValue<expression::Image>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -363,7 +364,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::FillTranslate) {
Error error;
- optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ optional<PropertyValue<std::array<float, 2>>> typedValue =
+ convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -375,7 +377,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::FillTranslateAnchor) {
Error error;
- optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ optional<PropertyValue<TranslateAnchorType>> typedValue =
+ convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/fill_layer_properties.hpp b/src/mbgl/style/layers/fill_layer_properties.hpp
index 38ca506199..ad8ed84892 100644
--- a/src/mbgl/style/layers/fill_layer_properties.hpp
+++ b/src/mbgl/style/layers/fill_layer_properties.hpp
@@ -32,12 +32,12 @@ struct FillOutlineColor : DataDrivenPaintProperty<Color, attributes::outline_col
static Color defaultValue() { return {}; }
};
-struct FillPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
- static std::string defaultValue() { return ""; }
+struct FillPattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
+ static expression::Image defaultValue() { return {}; }
};
struct FillTranslate : PaintProperty<std::array<float, 2>> {
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct FillTranslateAnchor : PaintProperty<TranslateAnchorType> {
diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp
index 332c65c6b4..234dda6c73 100644
--- a/src/mbgl/style/layers/heatmap_layer.cpp
+++ b/src/mbgl/style/layers/heatmap_layer.cpp
@@ -93,7 +93,7 @@ TransitionOptions HeatmapLayer::getHeatmapColorTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapIntensity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapIntensity() const {
@@ -120,7 +120,7 @@ TransitionOptions HeatmapLayer::getHeatmapIntensityTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapOpacity() const {
@@ -147,7 +147,7 @@ TransitionOptions HeatmapLayer::getHeatmapOpacityTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapRadius() {
- return { 30 };
+ return {30};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapRadius() const {
@@ -174,7 +174,7 @@ TransitionOptions HeatmapLayer::getHeatmapRadiusTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapWeight() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapWeight() const {
diff --git a/src/mbgl/style/layers/hillshade_layer.cpp b/src/mbgl/style/layers/hillshade_layer.cpp
index a55c079c49..5d84b7ded3 100644
--- a/src/mbgl/style/layers/hillshade_layer.cpp
+++ b/src/mbgl/style/layers/hillshade_layer.cpp
@@ -64,7 +64,7 @@ void HillshadeLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBu
// Paint properties
PropertyValue<Color> HillshadeLayer::getDefaultHillshadeAccentColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& HillshadeLayer::getHillshadeAccentColor() const {
@@ -91,7 +91,7 @@ TransitionOptions HillshadeLayer::getHillshadeAccentColorTransition() const {
}
PropertyValue<float> HillshadeLayer::getDefaultHillshadeExaggeration() {
- return { 0.5 };
+ return {0.5};
}
const PropertyValue<float>& HillshadeLayer::getHillshadeExaggeration() const {
@@ -118,7 +118,7 @@ TransitionOptions HillshadeLayer::getHillshadeExaggerationTransition() const {
}
PropertyValue<Color> HillshadeLayer::getDefaultHillshadeHighlightColor() {
- return { Color::white() };
+ return {Color::white()};
}
const PropertyValue<Color>& HillshadeLayer::getHillshadeHighlightColor() const {
@@ -145,7 +145,7 @@ TransitionOptions HillshadeLayer::getHillshadeHighlightColorTransition() const {
}
PropertyValue<HillshadeIlluminationAnchorType> HillshadeLayer::getDefaultHillshadeIlluminationAnchor() {
- return { HillshadeIlluminationAnchorType::Viewport };
+ return {HillshadeIlluminationAnchorType::Viewport};
}
const PropertyValue<HillshadeIlluminationAnchorType>& HillshadeLayer::getHillshadeIlluminationAnchor() const {
@@ -172,7 +172,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationAnchorTransition() con
}
PropertyValue<float> HillshadeLayer::getDefaultHillshadeIlluminationDirection() {
- return { 335 };
+ return {335};
}
const PropertyValue<float>& HillshadeLayer::getHillshadeIlluminationDirection() const {
@@ -199,7 +199,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationDirectionTransition()
}
PropertyValue<Color> HillshadeLayer::getDefaultHillshadeShadowColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& HillshadeLayer::getHillshadeShadowColor() const {
@@ -320,7 +320,8 @@ optional<Error> HillshadeLayer::setPaintProperty(const std::string& name, const
if (property == Property::HillshadeIlluminationAnchor) {
Error error;
- optional<PropertyValue<HillshadeIlluminationAnchorType>> typedValue = convert<PropertyValue<HillshadeIlluminationAnchorType>>(value, error, false, false);
+ optional<PropertyValue<HillshadeIlluminationAnchorType>> typedValue =
+ convert<PropertyValue<HillshadeIlluminationAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index 775288264f..a47e5b95b4 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -77,6 +77,15 @@ layerCapabilities['heatmap'] = defaults.require('Source')
.set('TileKind', 'Geometry')
.finalize();
layerCapabilities['raster'] = defaults.require('Source').set('TileKind', 'Raster').finalize();
+
+// Splits lines that are over 120 characters at the firts occurance of '='.
+const split120Line = line => {
+ if (line.length > 120) {
+ return line.replace('=', '=\n ');
+ }
+ return line;
+};
+
%>
// static
const LayerTypeInfo* <%- camelize(type) %>Layer::Impl::staticTypeInfo() noexcept {
@@ -155,7 +164,7 @@ void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(const <%- pro
std::string rawValue = R"JSON(<%- JSON.stringify(property.default) %>)JSON";
return *conversion::convertJSON<<%- propertyValueType(property)%>>(rawValue, error);
<% } else { -%>
- return { <%- defaultValue(property) %> };
+ return {<%- defaultValue(property) %>};
<% } -%>
}
@@ -243,7 +252,7 @@ optional<Error> <%- camelize(type) %>Layer::setPaintProperty(const std::string&
%>
if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) {
Error error;
- <%- key %>;
+ <%- split120Line(key) %>;
if (!typedValue) {
return error;
}
@@ -323,7 +332,7 @@ optional<Error> <%- camelize(type) %>Layer::setLayoutProperty(const std::string&
%>
if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) {
Error error;
- <%- key %>;
+ <%- split120Line(key) %>;
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 309a81ae2b..813ef68dec 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -129,7 +129,7 @@ void LineLayer::setLineRoundLimit(const PropertyValue<float>& value) {
// Paint properties
PropertyValue<float> LineLayer::getDefaultLineBlur() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& LineLayer::getLineBlur() const {
@@ -156,7 +156,7 @@ TransitionOptions LineLayer::getLineBlurTransition() const {
}
PropertyValue<Color> LineLayer::getDefaultLineColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& LineLayer::getLineColor() const {
@@ -183,7 +183,7 @@ TransitionOptions LineLayer::getLineColorTransition() const {
}
PropertyValue<std::vector<float>> LineLayer::getDefaultLineDasharray() {
- return { { } };
+ return {{}};
}
const PropertyValue<std::vector<float>>& LineLayer::getLineDasharray() const {
@@ -210,7 +210,7 @@ TransitionOptions LineLayer::getLineDasharrayTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineGapWidth() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& LineLayer::getLineGapWidth() const {
@@ -237,7 +237,7 @@ TransitionOptions LineLayer::getLineGapWidthTransition() const {
}
ColorRampPropertyValue LineLayer::getDefaultLineGradient() {
- return { {} };
+ return {{}};
}
const ColorRampPropertyValue& LineLayer::getLineGradient() const {
@@ -264,7 +264,7 @@ TransitionOptions LineLayer::getLineGradientTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineOffset() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& LineLayer::getLineOffset() const {
@@ -291,7 +291,7 @@ TransitionOptions LineLayer::getLineOffsetTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& LineLayer::getLineOpacity() const {
@@ -317,15 +317,15 @@ TransitionOptions LineLayer::getLineOpacityTransition() const {
return impl().paint.template get<LineOpacity>().options;
}
-PropertyValue<std::string> LineLayer::getDefaultLinePattern() {
- return { "" };
+PropertyValue<expression::Image> LineLayer::getDefaultLinePattern() {
+ return {{}};
}
-const PropertyValue<std::string>& LineLayer::getLinePattern() const {
+const PropertyValue<expression::Image>& LineLayer::getLinePattern() const {
return impl().paint.template get<LinePattern>().value;
}
-void LineLayer::setLinePattern(const PropertyValue<std::string>& value) {
+void LineLayer::setLinePattern(const PropertyValue<expression::Image>& value) {
if (value == getLinePattern())
return;
auto impl_ = mutableImpl();
@@ -345,7 +345,7 @@ TransitionOptions LineLayer::getLinePatternTransition() const {
}
PropertyValue<std::array<float, 2>> LineLayer::getDefaultLineTranslate() {
- return { {{ 0, 0 }} };
+ return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& LineLayer::getLineTranslate() const {
@@ -372,7 +372,7 @@ TransitionOptions LineLayer::getLineTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> LineLayer::getDefaultLineTranslateAnchor() {
- return { TranslateAnchorType::Map };
+ return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& LineLayer::getLineTranslateAnchor() const {
@@ -399,7 +399,7 @@ TransitionOptions LineLayer::getLineTranslateAnchorTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineWidth() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& LineLayer::getLineWidth() const {
@@ -552,7 +552,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LineDasharray) {
Error error;
- optional<PropertyValue<std::vector<float>>> typedValue = convert<PropertyValue<std::vector<float>>>(value, error, false, false);
+ optional<PropertyValue<std::vector<float>>> typedValue =
+ convert<PropertyValue<std::vector<float>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -576,7 +577,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LinePattern) {
Error error;
- optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false);
+ optional<PropertyValue<expression::Image>> typedValue =
+ convert<PropertyValue<expression::Image>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -588,7 +590,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LineTranslate) {
Error error;
- optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ optional<PropertyValue<std::array<float, 2>>> typedValue =
+ convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -600,7 +603,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LineTranslateAnchor) {
Error error;
- optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ optional<PropertyValue<TranslateAnchorType>> typedValue =
+ convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
index 2ecbb10993..29ba9ec641 100644
--- a/src/mbgl/style/layers/line_layer_properties.hpp
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -45,7 +45,7 @@ struct LineColor : DataDrivenPaintProperty<Color, attributes::color, uniforms::c
};
struct LineDasharray : CrossFadedPaintProperty<std::vector<float>> {
- static std::vector<float> defaultValue() { return { }; }
+ static std::vector<float> defaultValue() { return {}; }
};
struct LineFloorWidth : DataDrivenPaintProperty<float, attributes::floorwidth, uniforms::floorwidth> {
@@ -68,12 +68,12 @@ struct LineOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform
static float defaultValue() { return 1; }
};
-struct LinePattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
- static std::string defaultValue() { return ""; }
+struct LinePattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
+ static expression::Image defaultValue() { return {}; }
};
struct LineTranslate : PaintProperty<std::array<float, 2>> {
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct LineTranslateAnchor : PaintProperty<TranslateAnchorType> {
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
index 359e502f3e..b990409886 100644
--- a/src/mbgl/style/layers/raster_layer.cpp
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -64,7 +64,7 @@ void RasterLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe
// Paint properties
PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMax() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& RasterLayer::getRasterBrightnessMax() const {
@@ -91,7 +91,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMaxTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMin() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& RasterLayer::getRasterBrightnessMin() const {
@@ -118,7 +118,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMinTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterContrast() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& RasterLayer::getRasterContrast() const {
@@ -145,7 +145,7 @@ TransitionOptions RasterLayer::getRasterContrastTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterFadeDuration() {
- return { 300 };
+ return {300};
}
const PropertyValue<float>& RasterLayer::getRasterFadeDuration() const {
@@ -172,7 +172,7 @@ TransitionOptions RasterLayer::getRasterFadeDurationTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterHueRotate() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& RasterLayer::getRasterHueRotate() const {
@@ -199,7 +199,7 @@ TransitionOptions RasterLayer::getRasterHueRotateTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& RasterLayer::getRasterOpacity() const {
@@ -226,7 +226,7 @@ TransitionOptions RasterLayer::getRasterOpacityTransition() const {
}
PropertyValue<RasterResamplingType> RasterLayer::getDefaultRasterResampling() {
- return { RasterResamplingType::Linear };
+ return {RasterResamplingType::Linear};
}
const PropertyValue<RasterResamplingType>& RasterLayer::getRasterResampling() const {
@@ -253,7 +253,7 @@ TransitionOptions RasterLayer::getRasterResamplingTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterSaturation() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& RasterLayer::getRasterSaturation() const {
@@ -383,7 +383,8 @@ optional<Error> RasterLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::RasterResampling) {
Error error;
- optional<PropertyValue<RasterResamplingType>> typedValue = convert<PropertyValue<RasterResamplingType>>(value, error, false, false);
+ optional<PropertyValue<RasterResamplingType>> typedValue =
+ convert<PropertyValue<RasterResamplingType>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index b3ee0f698c..1383293d6d 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -109,15 +109,15 @@ void SymbolLayer::setIconIgnorePlacement(const PropertyValue<bool>& value) {
baseImpl = std::move(impl_);
observer->onLayerChanged(*this);
}
-PropertyValue<std::string> SymbolLayer::getDefaultIconImage() {
+PropertyValue<expression::Image> SymbolLayer::getDefaultIconImage() {
return IconImage::defaultValue();
}
-const PropertyValue<std::string>& SymbolLayer::getIconImage() const {
+const PropertyValue<expression::Image>& SymbolLayer::getIconImage() const {
return impl().layout.get<IconImage>();
}
-void SymbolLayer::setIconImage(const PropertyValue<std::string>& value) {
+void SymbolLayer::setIconImage(const PropertyValue<expression::Image>& value) {
if (value == getIconImage())
return;
auto impl_ = mutableImpl();
@@ -721,7 +721,7 @@ void SymbolLayer::setTextWritingMode(const PropertyValue<std::vector<TextWriting
// Paint properties
PropertyValue<Color> SymbolLayer::getDefaultIconColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& SymbolLayer::getIconColor() const {
@@ -748,7 +748,7 @@ TransitionOptions SymbolLayer::getIconColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& SymbolLayer::getIconHaloBlur() const {
@@ -775,7 +775,7 @@ TransitionOptions SymbolLayer::getIconHaloBlurTransition() const {
}
PropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() {
- return { {} };
+ return {{}};
}
const PropertyValue<Color>& SymbolLayer::getIconHaloColor() const {
@@ -802,7 +802,7 @@ TransitionOptions SymbolLayer::getIconHaloColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& SymbolLayer::getIconHaloWidth() const {
@@ -829,7 +829,7 @@ TransitionOptions SymbolLayer::getIconHaloWidthTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultIconOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& SymbolLayer::getIconOpacity() const {
@@ -856,7 +856,7 @@ TransitionOptions SymbolLayer::getIconOpacityTransition() const {
}
PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconTranslate() {
- return { {{ 0, 0 }} };
+ return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& SymbolLayer::getIconTranslate() const {
@@ -883,7 +883,7 @@ TransitionOptions SymbolLayer::getIconTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultIconTranslateAnchor() {
- return { TranslateAnchorType::Map };
+ return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& SymbolLayer::getIconTranslateAnchor() const {
@@ -910,7 +910,7 @@ TransitionOptions SymbolLayer::getIconTranslateAnchorTransition() const {
}
PropertyValue<Color> SymbolLayer::getDefaultTextColor() {
- return { Color::black() };
+ return {Color::black()};
}
const PropertyValue<Color>& SymbolLayer::getTextColor() const {
@@ -937,7 +937,7 @@ TransitionOptions SymbolLayer::getTextColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& SymbolLayer::getTextHaloBlur() const {
@@ -964,7 +964,7 @@ TransitionOptions SymbolLayer::getTextHaloBlurTransition() const {
}
PropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() {
- return { {} };
+ return {{}};
}
const PropertyValue<Color>& SymbolLayer::getTextHaloColor() const {
@@ -991,7 +991,7 @@ TransitionOptions SymbolLayer::getTextHaloColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() {
- return { 0 };
+ return {0};
}
const PropertyValue<float>& SymbolLayer::getTextHaloWidth() const {
@@ -1018,7 +1018,7 @@ TransitionOptions SymbolLayer::getTextHaloWidthTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultTextOpacity() {
- return { 1 };
+ return {1};
}
const PropertyValue<float>& SymbolLayer::getTextOpacity() const {
@@ -1045,7 +1045,7 @@ TransitionOptions SymbolLayer::getTextOpacityTransition() const {
}
PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextTranslate() {
- return { {{ 0, 0 }} };
+ return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& SymbolLayer::getTextTranslate() const {
@@ -1072,7 +1072,7 @@ TransitionOptions SymbolLayer::getTextTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultTextTranslateAnchor() {
- return { TranslateAnchorType::Map };
+ return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& SymbolLayer::getTextTranslateAnchor() const {
@@ -1332,7 +1332,8 @@ optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::IconTranslate || property == Property::TextTranslate) {
Error error;
- optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ optional<PropertyValue<std::array<float, 2>>> typedValue =
+ convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1351,7 +1352,8 @@ optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::IconTranslateAnchor || property == Property::TextTranslateAnchor) {
Error error;
- optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ optional<PropertyValue<TranslateAnchorType>> typedValue =
+ convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1665,7 +1667,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconAnchor || property == Property::TextAnchor) {
Error error;
- optional<PropertyValue<SymbolAnchorType>> typedValue = convert<PropertyValue<SymbolAnchorType>>(value, error, true, false);
+ optional<PropertyValue<SymbolAnchorType>> typedValue =
+ convert<PropertyValue<SymbolAnchorType>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1684,7 +1687,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconImage) {
Error error;
- optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, true);
+ optional<PropertyValue<expression::Image>> typedValue =
+ convert<PropertyValue<expression::Image>>(value, error, true, true);
if (!typedValue) {
return error;
}
@@ -1696,7 +1700,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconOffset || property == Property::TextOffset) {
Error error;
- optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, true, false);
+ optional<PropertyValue<std::array<float, 2>>> typedValue =
+ convert<PropertyValue<std::array<float, 2>>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1827,7 +1832,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconTextFit) {
Error error;
- optional<PropertyValue<IconTextFitType>> typedValue = convert<PropertyValue<IconTextFitType>>(value, error, false, false);
+ optional<PropertyValue<IconTextFitType>> typedValue =
+ convert<PropertyValue<IconTextFitType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1839,7 +1845,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconTextFitPadding) {
Error error;
- optional<PropertyValue<std::array<float, 4>>> typedValue = convert<PropertyValue<std::array<float, 4>>>(value, error, false, false);
+ optional<PropertyValue<std::array<float, 4>>> typedValue =
+ convert<PropertyValue<std::array<float, 4>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1851,7 +1858,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::SymbolPlacement) {
Error error;
- optional<PropertyValue<SymbolPlacementType>> typedValue = convert<PropertyValue<SymbolPlacementType>>(value, error, false, false);
+ optional<PropertyValue<SymbolPlacementType>> typedValue =
+ convert<PropertyValue<SymbolPlacementType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1863,7 +1871,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::SymbolZOrder) {
Error error;
- optional<PropertyValue<SymbolZOrderType>> typedValue = convert<PropertyValue<SymbolZOrderType>>(value, error, false, false);
+ optional<PropertyValue<SymbolZOrderType>> typedValue =
+ convert<PropertyValue<SymbolZOrderType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1875,7 +1884,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextField) {
Error error;
- optional<PropertyValue<expression::Formatted>> typedValue = convert<PropertyValue<expression::Formatted>>(value, error, true, true);
+ optional<PropertyValue<expression::Formatted>> typedValue =
+ convert<PropertyValue<expression::Formatted>>(value, error, true, true);
if (!typedValue) {
return error;
}
@@ -1887,7 +1897,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextFont) {
Error error;
- optional<PropertyValue<std::vector<std::string>>> typedValue = convert<PropertyValue<std::vector<std::string>>>(value, error, true, false);
+ optional<PropertyValue<std::vector<std::string>>> typedValue =
+ convert<PropertyValue<std::vector<std::string>>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1911,7 +1922,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextTransform) {
Error error;
- optional<PropertyValue<TextTransformType>> typedValue = convert<PropertyValue<TextTransformType>>(value, error, true, false);
+ optional<PropertyValue<TextTransformType>> typedValue =
+ convert<PropertyValue<TextTransformType>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1923,7 +1935,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextVariableAnchor) {
Error error;
- optional<PropertyValue<std::vector<TextVariableAnchorType>>> typedValue = convert<PropertyValue<std::vector<TextVariableAnchorType>>>(value, error, false, false);
+ optional<PropertyValue<std::vector<TextVariableAnchorType>>> typedValue =
+ convert<PropertyValue<std::vector<TextVariableAnchorType>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1935,7 +1948,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextWritingMode) {
Error error;
- optional<PropertyValue<std::vector<TextWritingModeType>>> typedValue = convert<PropertyValue<std::vector<TextWritingModeType>>>(value, error, false, false);
+ optional<PropertyValue<std::vector<TextWritingModeType>>> typedValue =
+ convert<PropertyValue<std::vector<TextWritingModeType>>>(value, error, false, false);
if (!typedValue) {
return error;
}
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index e44e7e404f..6552589971 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -31,9 +31,9 @@ struct IconIgnorePlacement : LayoutProperty<bool> {
static bool defaultValue() { return false; }
};
-struct IconImage : DataDrivenLayoutProperty<std::string> {
+struct IconImage : DataDrivenLayoutProperty<expression::Image> {
static constexpr const char *name() { return "icon-image"; }
- static std::string defaultValue() { return ""; }
+ static expression::Image defaultValue() { return {}; }
};
struct IconKeepUpright : LayoutProperty<bool> {
@@ -43,7 +43,7 @@ struct IconKeepUpright : LayoutProperty<bool> {
struct IconOffset : DataDrivenLayoutProperty<std::array<float, 2>> {
static constexpr const char *name() { return "icon-offset"; }
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct IconOptional : LayoutProperty<bool> {
@@ -83,7 +83,7 @@ struct IconTextFit : LayoutProperty<IconTextFitType> {
struct IconTextFitPadding : LayoutProperty<std::array<float, 4>> {
static constexpr const char *name() { return "icon-text-fit-padding"; }
- static std::array<float, 4> defaultValue() { return {{ 0, 0, 0, 0 }}; }
+ static std::array<float, 4> defaultValue() { return {{0, 0, 0, 0}}; }
};
struct SymbolAvoidEdges : LayoutProperty<bool> {
@@ -123,12 +123,12 @@ struct TextAnchor : DataDrivenLayoutProperty<SymbolAnchorType> {
struct TextField : DataDrivenLayoutProperty<expression::Formatted> {
static constexpr const char *name() { return "text-field"; }
- static expression::Formatted defaultValue() { return ""; }
+ static expression::Formatted defaultValue() { return {}; }
};
struct TextFont : DataDrivenLayoutProperty<std::vector<std::string>> {
static constexpr const char *name() { return "text-font"; }
- static std::vector<std::string> defaultValue() { return { "Open Sans Regular", "Arial Unicode MS Regular" }; }
+ static std::vector<std::string> defaultValue() { return {{"Open Sans Regular"}, {"Arial Unicode MS Regular"}}; }
};
struct TextIgnorePlacement : LayoutProperty<bool> {
@@ -168,7 +168,7 @@ struct TextMaxWidth : DataDrivenLayoutProperty<float> {
struct TextOffset : DataDrivenLayoutProperty<std::array<float, 2>> {
static constexpr const char *name() { return "text-offset"; }
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct TextOptional : LayoutProperty<bool> {
@@ -213,12 +213,12 @@ struct TextTransform : DataDrivenLayoutProperty<TextTransformType> {
struct TextVariableAnchor : LayoutProperty<std::vector<TextVariableAnchorType>> {
static constexpr const char *name() { return "text-variable-anchor"; }
- static std::vector<TextVariableAnchorType> defaultValue() { return { }; }
+ static std::vector<TextVariableAnchorType> defaultValue() { return {}; }
};
struct TextWritingMode : LayoutProperty<std::vector<TextWritingModeType>> {
static constexpr const char *name() { return "text-writing-mode"; }
- static std::vector<TextWritingModeType> defaultValue() { return { }; }
+ static std::vector<TextWritingModeType> defaultValue() { return {}; }
};
struct IconColor : DataDrivenPaintProperty<Color, attributes::fill_color, uniforms::fill_color> {
@@ -242,7 +242,7 @@ struct IconOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform
};
struct IconTranslate : PaintProperty<std::array<float, 2>> {
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct IconTranslateAnchor : PaintProperty<TranslateAnchorType> {
@@ -273,7 +273,7 @@ struct TextOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform
};
struct TextTranslate : PaintProperty<std::array<float, 2>> {
- static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
+ static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct TextTranslateAnchor : PaintProperty<TranslateAnchorType> {
diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp
index db0e54330c..9c8996fcbe 100644
--- a/src/mbgl/style/properties.hpp
+++ b/src/mbgl/style/properties.hpp
@@ -169,8 +169,10 @@ public:
}
template <class T>
- static T evaluate(float z, const GeometryTileFeature& feature,
- const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) {
+ static T evaluate(float z,
+ const GeometryTileFeature& feature,
+ const PossiblyEvaluatedPropertyValue<T>& v,
+ const T& defaultValue) {
return v.match(
[&] (const T& t) {
return t;
@@ -181,6 +183,17 @@ public:
}
template <class T>
+ static T evaluate(float z,
+ const GeometryTileFeature& feature,
+ const PossiblyEvaluatedPropertyValue<T>& v,
+ const T& defaultValue,
+ const std::set<std::string>& availableImages) {
+ return v.match(
+ [&](const T& t) { return t; },
+ [&](const PropertyExpression<T>& t) { return t.evaluate(z, feature, availableImages, defaultValue); });
+ }
+
+ template <class T>
static T evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state,
const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) {
return v.match([&](const T& t) { return t; },
@@ -197,6 +210,11 @@ public:
return evaluate(z, feature, state, this->template get<P>(), P::defaultValue());
}
+ template <class P>
+ auto evaluate(float z, const GeometryTileFeature& feature, const std::set<std::string>& availableImages) const {
+ return evaluate(z, feature, this->template get<P>(), P::defaultValue(), availableImages);
+ }
+
Evaluated evaluate(float z, const GeometryTileFeature& feature) const {
return Evaluated {
evaluate<Ps>(z, feature)...
diff --git a/src/mbgl/style/property_expression.cpp b/src/mbgl/style/property_expression.cpp
index 9ebecc4b40..d531181e71 100644
--- a/src/mbgl/style/property_expression.cpp
+++ b/src/mbgl/style/property_expression.cpp
@@ -8,6 +8,7 @@ PropertyExpressionBase::PropertyExpressionBase(std::unique_ptr<expression::Expre
zoomCurve(expression::findZoomCurveChecked(expression.get())) {
isZoomConstant_ = expression::isZoomConstant(*expression);
isFeatureConstant_ = expression::isFeatureConstant(*expression);
+ isRuntimeConstant_ = expression::isRuntimeConstant(*expression);
}
bool PropertyExpressionBase::isZoomConstant() const noexcept {
@@ -18,19 +19,8 @@ bool PropertyExpressionBase::isFeatureConstant() const noexcept {
return isFeatureConstant_;
}
-bool PropertyExpressionBase::canEvaluateWith(const expression::EvaluationContext& context) const noexcept {
- if (context.zoom) {
- if (context.feature != nullptr) {
- return !isFeatureConstant();
- }
- return !isZoomConstant() && isFeatureConstant();
- }
-
- if (context.feature != nullptr) {
- return isZoomConstant() && !isFeatureConstant();
- }
-
- return true;
+bool PropertyExpressionBase::isRuntimeConstant() const noexcept {
+ return isRuntimeConstant_;
}
float PropertyExpressionBase::interpolationFactor(const Range<float>& inputLevels, const float inputValue) const noexcept {
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 9f9c41d229..4a3d91455a 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -182,7 +182,8 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_, bool r
pending = true;
++correlationID;
- worker.self().invoke(&GeometryTileWorker::setData, std::move(data_), resetLayers, correlationID);
+ worker.self().invoke(
+ &GeometryTileWorker::setData, std::move(data_), imageManager.getAvailableImages(), resetLayers, correlationID);
}
std::unique_ptr<TileRenderData> GeometryTile::createRenderData() {
@@ -212,7 +213,8 @@ void GeometryTile::setLayers(const std::vector<Immutable<LayerProperties>>& laye
}
++correlationID;
- worker.self().invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID);
+ worker.self().invoke(
+ &GeometryTileWorker::setLayers, std::move(impls), imageManager.getAvailableImages(), correlationID);
}
void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) {
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index 7815e62b75..de53c69aee 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -116,10 +116,14 @@ GeometryTileWorker::~GeometryTileWorker() = default;
completed parse.
*/
-void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_, bool resetLayers_, uint64_t correlationID_) {
+void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
+ std::set<std::string> availableImages_,
+ bool resetLayers_,
+ uint64_t correlationID_) {
try {
data = std::move(data_);
correlationID = correlationID_;
+ availableImages = std::move(availableImages_);
if (resetLayers_) layers = nullopt;
switch (state) {
@@ -139,10 +143,13 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
}
}
-void GeometryTileWorker::setLayers(std::vector<Immutable<LayerProperties>> layers_, uint64_t correlationID_) {
+void GeometryTileWorker::setLayers(std::vector<Immutable<LayerProperties>> layers_,
+ std::set<std::string> availableImages_,
+ uint64_t correlationID_) {
try {
layers = std::move(layers_);
correlationID = correlationID_;
+ availableImages = std::move(availableImages_);
switch (state) {
case Idle:
@@ -365,7 +372,8 @@ void GeometryTileWorker::parse() {
// and either immediately create a bucket if no images/glyphs are used, or the Layout is stored until
// the images/glyphs are available to add the features to the buckets.
if (leaderImpl.getTypeInfo()->layout == LayerTypeInfo::Layout::Required) {
- std::unique_ptr<Layout> layout = LayerManager::get()->createLayout({parameters, glyphDependencies, imageDependencies}, std::move(geometryLayer), group);
+ std::unique_ptr<Layout> layout = LayerManager::get()->createLayout(
+ {parameters, glyphDependencies, imageDependencies, availableImages}, std::move(geometryLayer), group);
if (layout->hasDependencies()) {
layouts.push_back(std::move(layout));
} else {
diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp
index 96b4e2e83a..38f7cb9fa6 100644
--- a/src/mbgl/tile/geometry_tile_worker.hpp
+++ b/src/mbgl/tile/geometry_tile_worker.hpp
@@ -38,8 +38,13 @@ public:
const bool showCollisionBoxes_);
~GeometryTileWorker();
- void setLayers(std::vector<Immutable<style::LayerProperties>>, uint64_t correlationID);
- void setData(std::unique_ptr<const GeometryTileData>, bool resetLayers, uint64_t correlationID);
+ void setLayers(std::vector<Immutable<style::LayerProperties>>,
+ std::set<std::string> availableImages,
+ uint64_t correlationID);
+ void setData(std::unique_ptr<const GeometryTileData>,
+ std::set<std::string> availableImages,
+ bool resetLayers,
+ uint64_t correlationID);
void setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_);
void onGlyphsAvailable(GlyphMap glyphs);
@@ -96,7 +101,8 @@ private:
ImageMap imageMap;
ImageMap patternMap;
ImageVersionMap versionMap;
-
+ std::set<std::string> availableImages;
+
bool showCollisionBoxes;
bool firstLoad = true;
};