summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp8
-rw-r--r--src/mbgl/layout/symbol_layout.cpp32
-rw-r--r--src/mbgl/programs/symbol_program.hpp4
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.cpp4
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.cpp4
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp2
-rw-r--r--src/mbgl/renderer/render_layer.cpp2
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp4
-rw-r--r--src/mbgl/shaders/source.cpp374
-rw-r--r--src/mbgl/shaders/symbol_icon.cpp2
-rw-r--r--src/mbgl/shaders/symbol_sdf.cpp4
-rw-r--r--src/mbgl/style/conversion/color_ramp_property_value.cpp2
-rw-r--r--src/mbgl/style/conversion/constant.cpp56
-rw-r--r--src/mbgl/style/conversion/coordinate.cpp1
-rw-r--r--src/mbgl/style/conversion/custom_geometry_source_options.cpp1
-rw-r--r--src/mbgl/style/conversion/filter.cpp3
-rw-r--r--src/mbgl/style/conversion/function.cpp68
-rw-r--r--src/mbgl/style/conversion/geojson.cpp1
-rw-r--r--src/mbgl/style/conversion/geojson_options.cpp11
-rw-r--r--src/mbgl/style/conversion/get_json_type.cpp1
-rw-r--r--src/mbgl/style/conversion/json.hpp4
-rw-r--r--src/mbgl/style/conversion/layer.cpp24
-rw-r--r--src/mbgl/style/conversion/light.cpp1
-rw-r--r--src/mbgl/style/conversion/make_property_setters.hpp239
-rw-r--r--src/mbgl/style/conversion/make_property_setters.hpp.ejs46
-rw-r--r--src/mbgl/style/conversion/position.cpp1
-rw-r--r--src/mbgl/style/conversion/property_setter.hpp71
-rw-r--r--src/mbgl/style/conversion/property_value.cpp83
-rw-r--r--src/mbgl/style/conversion/source.cpp1
-rw-r--r--src/mbgl/style/conversion/tileset.cpp1
-rw-r--r--src/mbgl/style/conversion/transition_options.cpp1
-rw-r--r--src/mbgl/style/expression/array_assertion.cpp1
-rw-r--r--src/mbgl/style/expression/assertion.cpp1
-rw-r--r--src/mbgl/style/expression/at.cpp1
-rw-r--r--src/mbgl/style/expression/boolean_operator.cpp1
-rw-r--r--src/mbgl/style/expression/case.cpp1
-rw-r--r--src/mbgl/style/expression/coalesce.cpp1
-rw-r--r--src/mbgl/style/expression/coercion.cpp1
-rw-r--r--src/mbgl/style/expression/collator_expression.cpp1
-rw-r--r--src/mbgl/style/expression/comparison.cpp1
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp1
-rw-r--r--src/mbgl/style/expression/interpolate.cpp1
-rw-r--r--src/mbgl/style/expression/is_constant.cpp4
-rw-r--r--src/mbgl/style/expression/is_expression.cpp3
-rw-r--r--src/mbgl/style/expression/length.cpp1
-rw-r--r--src/mbgl/style/expression/let.cpp1
-rw-r--r--src/mbgl/style/expression/literal.cpp1
-rw-r--r--src/mbgl/style/expression/match.cpp1
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp1
-rw-r--r--src/mbgl/style/expression/step.cpp1
-rw-r--r--src/mbgl/style/layer.cpp20
-rw-r--r--src/mbgl/style/layers/background_layer.cpp145
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp346
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.cpp2
-rw-r--r--src/mbgl/style/layers/custom_layer.cpp10
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer.cpp256
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer_impl.cpp2
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp256
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.cpp2
-rw-r--r--src/mbgl/style/layers/heatmap_layer.cpp193
-rw-r--r--src/mbgl/style/layers/heatmap_layer_impl.cpp2
-rw-r--r--src/mbgl/style/layers/heatmap_layer_properties.hpp3
-rw-r--r--src/mbgl/style/layers/hillshade_layer.cpp215
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs149
-rw-r--r--src/mbgl/style/layers/layer_properties.hpp.ejs3
-rw-r--r--src/mbgl/style/layers/line_layer.cpp393
-rw-r--r--src/mbgl/style/layers/line_layer_impl.cpp2
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp250
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp939
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp2
-rw-r--r--src/mbgl/style/parser.cpp30
-rw-r--r--src/mbgl/style/rapidjson_conversion.hpp2
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp1
-rw-r--r--src/mbgl/text/collision_index.cpp44
-rw-r--r--src/mbgl/text/collision_index.hpp14
-rw-r--r--src/mbgl/text/glyph_manager.cpp7
-rw-r--r--src/mbgl/text/glyph_manager.hpp3
-rw-r--r--src/mbgl/text/placement.cpp24
-rw-r--r--src/mbgl/tile/geometry_tile.cpp2
-rw-r--r--src/mbgl/tile/raster_dem_tile.cpp2
-rw-r--r--src/mbgl/tile/raster_tile.cpp2
-rw-r--r--src/mbgl/tile/tile.cpp10
-rw-r--r--src/mbgl/tile/tile.hpp9
-rw-r--r--src/mbgl/util/fnv_hash.hpp11
-rw-r--r--src/mbgl/util/font_stack.cpp40
-rw-r--r--src/mbgl/util/logging.cpp2
-rw-r--r--src/mbgl/util/tile_cover.cpp1
87 files changed, 3801 insertions, 673 deletions
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp
index 41eedf17dc..1baf83179e 100644
--- a/src/mbgl/annotation/annotation_manager.cpp
+++ b/src/mbgl/annotation/annotation_manager.cpp
@@ -140,7 +140,13 @@ std::unique_ptr<AnnotationTileData> AnnotationManager::getTileData(const Canonic
auto pointLayer = tileData->addLayer(PointLayerID);
LatLngBounds tileBounds(tileID);
-
+ // Hack for https://github.com/mapbox/mapbox-gl-native/issues/12472
+ // To handle precision issues, query a slightly larger area than the tile bounds
+ // Symbols at a border can be included in vector data for both tiles
+ // The rendering/querying logic will make sure the symbols show up in only one of the tiles
+ tileBounds.extend(LatLng(tileBounds.south() - 0.000000001, tileBounds.west() - 0.000000001));
+ tileBounds.extend(LatLng(tileBounds.north() + 0.000000001, tileBounds.east() + 0.000000001));
+
symbolTree.query(boost::geometry::index::intersects(tileBounds),
boost::make_function_output_iterator([&](const auto& val){
val->updateLayer(tileID, *pointLayer);
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 41469f293d..ab718351ab 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -258,11 +258,6 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
const float textMaxBoxScale = tilePixelRatio * textMaxSize / glyphSize;
const float iconBoxScale = tilePixelRatio * layoutIconSize;
const float symbolSpacing = tilePixelRatio * layout.get<SymbolSpacing>();
- // CJL: I'm not sure why SymbolPlacementType::Line -> avoidEdges = false. It seems redundant since
- // getAnchors will already avoid generating anchors outside the tile bounds.
- // However, SymbolPlacementType::LineCenter allows anchors outside tile boundaries, so its behavior
- // here should match SymbolPlacement::Point
- const bool avoidEdges = layout.get<SymbolAvoidEdges>() && layout.get<SymbolPlacement>() != SymbolPlacementType::Line;
const float textPadding = layout.get<TextPadding>() * tilePixelRatio;
const float iconPadding = layout.get<IconPadding>() * tilePixelRatio;
const float textMaxAngle = layout.get<TextMaxAngle>() * util::DEG2RAD;
@@ -274,25 +269,14 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
IndexedSubfeature indexedFeature(feature.index, sourceLayer->getName(), bucketLeaderID, symbolInstances.size());
auto addSymbolInstance = [&] (const GeometryCoordinates& line, Anchor& anchor) {
- // https://github.com/mapbox/vector-tile-spec/tree/master/2.1#41-layers
- // +-------------------+ Symbols with anchors located on tile edges
- // |(0,0) || are duplicated on neighbor tiles.
- // | ||
- // | || In continuous mode, to avoid overdraw we
- // | || skip symbols located on the extent edges.
- // | Tile || In still mode, we include the features in
- // | || the buffers for both tiles and clip them
- // | || at draw time.
- // | ||
- // +-------------------| In this scenario, the inner bounding box
- // +-------------------+ is called 'withinPlus0', and the outer
- // (extent,extent) is called 'inside'.
- const bool withinPlus0 = anchor.point.x >= 0 && anchor.point.x < util::EXTENT && anchor.point.y >= 0 && anchor.point.y < util::EXTENT;
- const bool inside = withinPlus0 || anchor.point.x == util::EXTENT || anchor.point.y == util::EXTENT;
-
- if (avoidEdges && !inside) return;
-
- if (mode == MapMode::Tile || withinPlus0) {
+ const bool anchorInsideTile = anchor.point.x >= 0 && anchor.point.x < util::EXTENT && anchor.point.y >= 0 && anchor.point.y < util::EXTENT;
+
+ if (mode == MapMode::Tile || anchorInsideTile) {
+ // For static/continuous rendering, only add symbols anchored within this tile:
+ // neighboring symbols will be added as part of the neighboring tiles.
+ // In tiled rendering mode, add all symbols in the buffers so that we can:
+ // (1) render symbols that overlap into this tile
+ // (2) approximate collision detection effects from neighboring symbols
symbolInstances.emplace_back(anchor, line, shapedTextOrientations, shapedIcon,
layout.evaluate(zoom, feature), layoutTextSize,
textBoxScale, textPadding, textPlacement, textOffset,
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index 0378cc0970..651f12828f 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -66,8 +66,8 @@ struct SymbolLayoutAttributes : gl::Attributes<
{{
tx,
ty,
- static_cast<uint16_t>(sizeData.min * 10),
- static_cast<uint16_t>(sizeData.max * 10)
+ static_cast<uint16_t>(sizeData.min * 256),
+ static_cast<uint16_t>(sizeData.max * 256)
}}
};
}
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp
index 027e864be5..a3f652fc6e 100644
--- a/src/mbgl/renderer/buckets/symbol_bucket.cpp
+++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp
@@ -193,8 +193,8 @@ void SymbolBucket::sortFeatures(const float angle) {
std::sort(symbolInstanceIndexes.begin(), symbolInstanceIndexes.end(), [sin, cos, this](size_t &aIndex, size_t &bIndex) {
const SymbolInstance& a = symbolInstances[aIndex];
const SymbolInstance& b = symbolInstances[bIndex];
- const int32_t aRotated = static_cast<int32_t>(std::lround(sin * a.anchor.point.x + cos * a.anchor.point.y));
- const int32_t bRotated = static_cast<int32_t>(std::lround(sin * b.anchor.point.x + cos * b.anchor.point.y));
+ const int32_t aRotated = static_cast<int32_t>(::lround(sin * a.anchor.point.x + cos * a.anchor.point.y));
+ const int32_t bRotated = static_cast<int32_t>(::lround(sin * b.anchor.point.x + cos * b.anchor.point.y));
return aRotated != bRotated ?
aRotated < bRotated :
a.dataFeatureIndex > b.dataFeatureIndex;
diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
index 25eef98fcf..8bcd3f1837 100644
--- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp
+++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
@@ -59,8 +59,8 @@ bool RenderHillshadeLayer::hasTransition() const {
void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src) {
if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D)
return;
-
- RenderRasterDEMSource* demsrc = dynamic_cast<RenderRasterDEMSource*>(src);
+
+ RenderRasterDEMSource* demsrc = static_cast<RenderRasterDEMSource*>(src);
const uint8_t TERRAIN_RGB_MAXZOOM = 15;
const uint8_t maxzoom = demsrc != nullptr ? demsrc->getMaxZoom() : TERRAIN_RGB_MAXZOOM;
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
index 63fcb6cfd5..f9e4e7c043 100644
--- a/src/mbgl/renderer/layers/render_symbol_layer.cpp
+++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp
@@ -126,7 +126,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) {
);
};
- assert(dynamic_cast<GeometryTile*>(&tile.tile));
+ assert(tile.tile.kind == Tile::Kind::Geometry);
GeometryTile& geometryTile = static_cast<GeometryTile&>(tile.tile);
if (bucket.hasIconData()) {
diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp
index a667d5837e..4cd033da75 100644
--- a/src/mbgl/renderer/render_layer.cpp
+++ b/src/mbgl/renderer/render_layer.cpp
@@ -91,7 +91,7 @@ void RenderLayer::checkRenderability(const PaintParameters& parameters,
activeBindingCount - parameters.context.minimumRequiredVertexBindingCount);
hasRenderFailures = true;
} else if (activeBindingCount > parameters.context.minimumRequiredVertexBindingCount) {
- Log::Error(Event::OpenGL,
+ Log::Warning(Event::OpenGL,
"The layer '%s' uses more data-driven properties than some devices may support. "
"Though it will render correctly on this device, it may have rendering errors "
"on other devices. To ensure compatibility with all devices, use %d fewer "
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index fea27403c9..d3f72b89b9 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -173,6 +173,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
renderLayers.at(entry.first)->setImpl(entry.second.after);
}
+ if (!layerDiff.removed.empty() || !layerDiff.added.empty() || !layerDiff.changed.empty()) {
+ glyphManager->evict(fontStacks(*updateParameters.layers));
+ }
+
// Update layers for class and zoom changes.
for (const auto& entry : renderLayers) {
RenderLayer& layer = *entry.second;
diff --git a/src/mbgl/shaders/source.cpp b/src/mbgl/shaders/source.cpp
index d5a4593ad9..242b726004 100644
--- a/src/mbgl/shaders/source.cpp
+++ b/src/mbgl/shaders/source.cpp
@@ -1272,193 +1272,193 @@ const char* source() {
0xaf, 0xea, 0x39, 0x92, 0x2d, 0xac, 0x48, 0x1c,
0xf1, 0x0c, 0x60, 0x84, 0xdf, 0x0e, 0xde, 0x75,
0x24, 0xee, 0x6f, 0x87, 0xef, 0x3a, 0x9a, 0x51,
- 0xe1, 0xa1, 0x3b, 0x1c, 0xa8, 0x53, 0xf7, 0x0f,
- 0x81, 0xb3, 0x4f, 0x48, 0xdc, 0x1a, 0x0e, 0xba,
- 0xff, 0xba, 0x9e, 0x9a, 0x86, 0x7b, 0xad, 0x9e,
- 0x24, 0x4b, 0xb4, 0xe1, 0x37, 0xd7, 0xa9, 0xba,
- 0xdc, 0x79, 0x4d, 0xee, 0xfb, 0xdb, 0x68, 0xa0,
- 0xf6, 0x82, 0x1b, 0xde, 0x09, 0x0c, 0x73, 0x91,
- 0x18, 0xde, 0x09, 0x90, 0x5c, 0xd0, 0xbd, 0x8d,
- 0xd6, 0x5f, 0xcf, 0x02, 0x72, 0x8b, 0x27, 0x17,
- 0x55, 0x54, 0x16, 0x99, 0x65, 0xa2, 0xf1, 0xa1,
- 0xc7, 0x97, 0x90, 0xa5, 0x6e, 0x14, 0x54, 0x66,
- 0x9c, 0x84, 0xa5, 0xbb, 0xe9, 0xc5, 0x37, 0x46,
- 0x5e, 0xad, 0x45, 0xa9, 0xdf, 0xc4, 0xec, 0xc5,
- 0xb1, 0x86, 0xd0, 0x54, 0xab, 0x5f, 0x0f, 0xbf,
- 0x3c, 0x3b, 0xd6, 0x9d, 0x8a, 0xc6, 0x9c, 0x0d,
- 0x52, 0xba, 0x2f, 0xfc, 0x1f, 0x5b, 0x5f, 0xf8,
- 0xf6, 0xcf, 0x1d, 0x69, 0xa7, 0x50, 0x0f, 0x56,
- 0x01, 0xe6, 0xef, 0x75, 0x1a, 0x9c, 0xd3, 0xdc,
- 0xa1, 0x13, 0x2e, 0x2e, 0xeb, 0x54, 0xc4, 0x81,
- 0x97, 0x76, 0x67, 0x61, 0x10, 0xa9, 0xd7, 0x0a,
- 0x19, 0xdb, 0x0d, 0xf1, 0x8a, 0x6b, 0xda, 0xc7,
- 0x7a, 0x48, 0x62, 0x78, 0x2c, 0x6b, 0xfd, 0x44,
- 0xfd, 0xef, 0xc0, 0x58, 0xb6, 0x88, 0x56, 0x40,
- 0x12, 0x2f, 0xe1, 0xed, 0x6c, 0xda, 0x19, 0x48,
- 0x92, 0x67, 0xf2, 0xba, 0x49, 0x33, 0x65, 0xf1,
- 0x0d, 0xb7, 0xee, 0x8b, 0xd1, 0x01, 0x5d, 0x5f,
- 0x4b, 0x8e, 0x5b, 0xe2, 0x10, 0xbc, 0xd6, 0x74,
- 0x58, 0xb2, 0xc9, 0x43, 0x6f, 0x0d, 0xde, 0x7d,
- 0xce, 0x31, 0x6a, 0x13, 0xfb, 0xd6, 0x84, 0xa3,
- 0x69, 0x9b, 0x79, 0xdc, 0xeb, 0xad, 0x28, 0x5c,
- 0xa5, 0xc8, 0x1b, 0xca, 0xd4, 0x7e, 0x56, 0x1e,
- 0x58, 0xc3, 0x02, 0xcb, 0x44, 0x4d, 0xd7, 0x75,
- 0xd5, 0x84, 0xae, 0x9b, 0xf9, 0xfa, 0x22, 0xf6,
- 0x75, 0x45, 0xe3, 0xca, 0x92, 0x8d, 0xd5, 0x75,
- 0x79, 0xc6, 0x28, 0x67, 0x4e, 0x0b, 0x2f, 0xb6,
- 0xba, 0x02, 0x5f, 0x65, 0x10, 0x61, 0xdb, 0x92,
- 0x45, 0x47, 0xe0, 0x0d, 0x19, 0x16, 0x5e, 0xb8,
- 0x19, 0xc5, 0xed, 0x95, 0x20, 0x1e, 0x3d, 0xc6,
- 0xfc, 0x47, 0xa7, 0x9c, 0xe1, 0xc0, 0xe1, 0xdd,
- 0x4f, 0x8a, 0xfd, 0x56, 0x6c, 0x7e, 0x86, 0x30,
- 0xa1, 0xa3, 0x87, 0xf2, 0x5e, 0x6c, 0x05, 0x01,
- 0xef, 0x9a, 0x85, 0xfa, 0xa6, 0x96, 0xe2, 0x94,
- 0xaf, 0xa0, 0x35, 0xc4, 0x8e, 0xf2, 0xda, 0xd0,
- 0x58, 0x76, 0xca, 0xbf, 0x4e, 0x9c, 0x54, 0x51,
- 0xf6, 0x45, 0x35, 0x1f, 0x87, 0x55, 0x52, 0x87,
- 0xb5, 0xe8, 0x76, 0x6d, 0x58, 0x8b, 0xaa, 0xec,
- 0x0d, 0x8e, 0x65, 0xae, 0x20, 0x9f, 0xe8, 0xdb,
- 0xeb, 0x02, 0x1c, 0x9b, 0x20, 0xe8, 0xd3, 0x06,
- 0xa6, 0xa2, 0x38, 0x5e, 0xb4, 0x96, 0xaa, 0x23,
- 0x19, 0xb4, 0x3f, 0x4e, 0x73, 0xa4, 0x37, 0x56,
- 0xbb, 0x6c, 0x74, 0x3e, 0xd7, 0x47, 0x33, 0xfe,
- 0xdb, 0xb7, 0xa5, 0x1a, 0x4d, 0x68, 0xb6, 0xe4,
- 0x62, 0x44, 0x0f, 0xf9, 0xa1, 0xe5, 0xaa, 0x05,
- 0x6e, 0xd6, 0x4b, 0x23, 0x77, 0x42, 0x3b, 0xbb,
- 0x1a, 0x9c, 0x99, 0x64, 0x11, 0xc0, 0x6c, 0x30,
- 0x8e, 0x7c, 0x8a, 0xe9, 0x97, 0x0a, 0x02, 0x2b,
- 0xa3, 0x59, 0x40, 0x62, 0xe9, 0x5d, 0xb4, 0x68,
- 0x2c, 0x68, 0x82, 0xc7, 0xec, 0x6f, 0x2e, 0x78,
- 0x38, 0x1d, 0x9f, 0xd8, 0xdd, 0x17, 0xf2, 0xd0,
- 0xdb, 0xa6, 0x27, 0x69, 0x12, 0x39, 0xf9, 0x64,
- 0x31, 0x0a, 0x6f, 0x2e, 0x2d, 0xde, 0xe2, 0x0b,
- 0x4e, 0x5b, 0xda, 0x97, 0x57, 0x1c, 0xaa, 0xd1,
- 0x5e, 0x09, 0x9d, 0x2b, 0xf2, 0x46, 0xcb, 0xdf,
- 0xe5, 0xbd, 0x43, 0x5b, 0x3d, 0x1e, 0xfa, 0xc2,
- 0xb5, 0x61, 0x69, 0x2e, 0xe1, 0x03, 0x74, 0xa6,
- 0xe4, 0x5a, 0x5c, 0x57, 0x37, 0x37, 0x5c, 0x7e,
- 0xb9, 0xa2, 0xbb, 0x2d, 0x9d, 0xbd, 0x8b, 0xd3,
- 0xef, 0x28, 0xbd, 0x13, 0x0d, 0xc2, 0xff, 0x8b,
- 0x33, 0xd8, 0x09, 0x01, 0xdc, 0x1f, 0x5d, 0x84,
- 0x42, 0x4f, 0x5e, 0xbe, 0x47, 0xcf, 0x36, 0x29,
- 0xac, 0x65, 0x4a, 0xf6, 0x44, 0xe5, 0x14, 0x8e,
- 0x76, 0xcc, 0xdb, 0x39, 0xd5, 0xb5, 0xb2, 0x64,
- 0x9d, 0x4e, 0x8c, 0xba, 0xcb, 0x89, 0x3b, 0xfd,
- 0x30, 0x46, 0x14, 0xa2, 0x4b, 0xf8, 0x8f, 0xb2,
- 0x65, 0xe3, 0x33, 0x49, 0x3e, 0xe0, 0x8e, 0x39,
- 0x1b, 0x18, 0x7d, 0x05, 0xdc, 0x8a, 0x08, 0x88,
- 0x00, 0x8b, 0xe8, 0xd1, 0x22, 0xdd, 0x08, 0xe0,
- 0xfb, 0xc3, 0x75, 0x4a, 0x86, 0x49, 0x29, 0x47,
- 0x5a, 0x28, 0x16, 0xd5, 0xed, 0xec, 0x18, 0xcb,
- 0xde, 0x12, 0x89, 0x10, 0xb4, 0x16, 0xbd, 0xda,
- 0xfc, 0x1f, 0x10, 0x1c, 0xce, 0x40, 0x61, 0xef,
- 0x28, 0x10, 0xed, 0x0e, 0xd6, 0x13, 0x56, 0x3d,
- 0x7a, 0xc8, 0x59, 0xae, 0x27, 0xde, 0xed, 0x4c,
- 0x0f, 0xca, 0xf4, 0x50, 0x7b, 0xf9, 0x1f, 0x46,
- 0x51, 0xd3, 0x43, 0x19, 0x53, 0xde, 0xf0, 0x5a,
- 0xc6, 0x54, 0xaa, 0x7c, 0x32, 0x63, 0x17, 0x37,
- 0x78, 0x76, 0xb8, 0xd5, 0x1a, 0x5d, 0x16, 0x16,
- 0x5e, 0x94, 0x34, 0x61, 0x6d, 0xca, 0x1b, 0xb0,
- 0x36, 0x95, 0x2a, 0xb1, 0xb6, 0x8b, 0x1b, 0xb0,
- 0x76, 0xab, 0x7d, 0x01, 0x6f, 0x6b, 0x68, 0x40,
- 0x0d, 0x8f, 0x33, 0x4c, 0x79, 0x3d, 0xae, 0xa6,
- 0x4e, 0x25, 0xba, 0x76, 0x71, 0x03, 0xc6, 0x6e,
- 0xb5, 0xab, 0x91, 0xae, 0x7f, 0x52, 0xa5, 0x8b,
- 0xaf, 0x40, 0xb9, 0xf6, 0x71, 0x95, 0x55, 0x7a,
- 0x15, 0xc2, 0x05, 0x0f, 0xa2, 0x87, 0x67, 0x9e,
- 0xba, 0x27, 0xa3, 0xe2, 0xb5, 0x8d, 0x9c, 0xd5,
- 0x56, 0xc8, 0x6d, 0x6d, 0x69, 0x78, 0x3a, 0xbb,
- 0x77, 0x80, 0xfb, 0xf2, 0xeb, 0xf0, 0x3a, 0x56,
- 0x34, 0x8b, 0x1f, 0x92, 0x7c, 0xaa, 0xff, 0xac,
- 0x7c, 0xdc, 0x63, 0x8a, 0x3b, 0x05, 0x5e, 0x59,
- 0xf7, 0xcc, 0xc7, 0x05, 0x58, 0xc9, 0xf3, 0x1a,
- 0xb0, 0xb3, 0xf8, 0x1e, 0xc1, 0xd5, 0x7f, 0x56,
- 0x62, 0x67, 0x8a, 0x3b, 0x05, 0x9e, 0x58, 0x87,
- 0x9d, 0x0b, 0xb0, 0x92, 0xb7, 0x7d, 0x26, 0x8f,
- 0x82, 0x2c, 0x2e, 0xa6, 0x67, 0xaa, 0xfe, 0x75,
- 0x89, 0x29, 0xee, 0x14, 0x38, 0x5c, 0x1d, 0x5e,
- 0x2e, 0xc0, 0x4a, 0x56, 0x75, 0x15, 0x76, 0xda,
- 0x5b, 0x4d, 0xff, 0x55, 0x8f, 0x9b, 0x7a, 0xc7,
- 0x65, 0x31, 0xb2, 0x46, 0xcc, 0xb4, 0xd7, 0x5b,
- 0x15, 0x4b, 0xfa, 0x4c, 0xed, 0xb6, 0x45, 0xb3,
- 0xed, 0xce, 0x6e, 0xfb, 0x27, 0xb3, 0xdb, 0xbe,
- 0x92, 0xb1, 0x5d, 0xf0, 0xac, 0x44, 0x91, 0x57,
- 0x9a, 0x17, 0x4d, 0xc6, 0xd5, 0x25, 0xbe, 0x6d,
- 0x8a, 0xbc, 0xcb, 0x64, 0x4d, 0xaf, 0x3b, 0xa6,
- 0x89, 0x72, 0x5f, 0xe4, 0x7a, 0x19, 0x6c, 0xad,
- 0xa0, 0x63, 0xa5, 0x1c, 0x9d, 0x2c, 0x28, 0xb7,
- 0x68, 0xc6, 0x20, 0xb5, 0xe3, 0x90, 0xc6, 0x45,
- 0xc5, 0x09, 0x48, 0x83, 0x88, 0xdf, 0x18, 0x81,
- 0x64, 0xaf, 0x33, 0x21, 0x13, 0x34, 0xfb, 0x89,
- 0x08, 0x25, 0x56, 0x0e, 0xd0, 0x81, 0x09, 0x9d,
- 0x31, 0x64, 0x28, 0x1a, 0xf4, 0xc6, 0xe7, 0xd4,
- 0xa7, 0xfe, 0xa5, 0x4e, 0xc0, 0x8a, 0x07, 0x94,
- 0x7c, 0x0f, 0x63, 0x3b, 0xc6, 0xd3, 0x01, 0xda,
- 0xab, 0x19, 0x2d, 0x86, 0x89, 0xa9, 0x1e, 0x30,
- 0x45, 0x91, 0xd1, 0xc3, 0x8e, 0x0b, 0x18, 0x5e,
- 0x67, 0xbc, 0x91, 0x97, 0xce, 0x0b, 0xc3, 0xc5,
- 0x72, 0x49, 0x4a, 0xa0, 0xa9, 0xd0, 0xfb, 0x14,
- 0xcb, 0x11, 0x73, 0xd9, 0xdb, 0x6e, 0xe0, 0x94,
- 0x17, 0xfd, 0xea, 0x51, 0xff, 0x39, 0x4c, 0xee,
- 0xdb, 0x98, 0xdb, 0x6f, 0xdf, 0xd4, 0xfe, 0x19,
- 0x99, 0xd9, 0x99, 0xa5, 0x48, 0x1a, 0x25, 0x5a,
- 0x7f, 0xac, 0x00, 0x75, 0xbd, 0x28, 0x9c, 0xc7,
- 0x78, 0x56, 0x1c, 0x23, 0xf1, 0x3f, 0x26, 0xaf,
- 0x3a, 0x58, 0x91, 0xf0, 0x03, 0x60, 0xeb, 0x45,
- 0x5c, 0x1b, 0xf3, 0x99, 0x53, 0xb2, 0xe1, 0x84,
- 0x5d, 0xec, 0xe8, 0xe5, 0x8a, 0xdd, 0xc1, 0x9b,
- 0x04, 0xe4, 0xb0, 0x39, 0xea, 0xc7, 0xb8, 0x65,
- 0x88, 0x56, 0xf9, 0xe4, 0x09, 0x63, 0xc3, 0x7d,
- 0xe4, 0xf6, 0xa1, 0xed, 0x95, 0x7a, 0x1b, 0x0c,
- 0x1b, 0xb2, 0xc0, 0x5d, 0x65, 0xf5, 0xa6, 0xdc,
- 0x90, 0xb1, 0x17, 0x1b, 0xbe, 0x6c, 0x29, 0x41,
- 0x89, 0x30, 0xe7, 0xe7, 0x93, 0xcb, 0xc0, 0xa3,
- 0xb0, 0x4f, 0x80, 0x4d, 0x6d, 0x7f, 0xbd, 0xdd,
- 0x15, 0xc2, 0xee, 0x0a, 0xe1, 0x8b, 0xbb, 0x42,
- 0x30, 0x5c, 0xc5, 0x7d, 0x2d, 0xe6, 0x3c, 0x34,
- 0xb3, 0x25, 0xca, 0xcf, 0xe2, 0xb2, 0x41, 0x3d,
- 0xe2, 0xd5, 0xa6, 0xbe, 0xe9, 0x2d, 0xdc, 0x3e,
- 0xc8, 0x6b, 0x0c, 0x52, 0x67, 0xd5, 0xe3, 0x30,
- 0x7c, 0x17, 0x7b, 0x41, 0xa1, 0xb9, 0x4c, 0x3c,
- 0x32, 0x56, 0x6d, 0x95, 0x1f, 0x9b, 0x35, 0xad,
- 0x1d, 0xc1, 0xa1, 0xc0, 0x6a, 0xf1, 0xe2, 0x2b,
- 0x0e, 0x15, 0xdf, 0xe8, 0xec, 0xbb, 0xef, 0xc7,
- 0xaf, 0xff, 0x29, 0x8e, 0xac, 0xd0, 0x51, 0x2f,
- 0xbf, 0xfb, 0xe1, 0xe5, 0xf8, 0x87, 0x17, 0x7f,
- 0xff, 0xfb, 0x0b, 0x98, 0x8c, 0xe1, 0xe0, 0xb0,
- 0x5f, 0x7e, 0xfb, 0x50, 0x65, 0x7c, 0x40, 0x55,
- 0xe3, 0x64, 0x0b, 0x3b, 0xe3, 0x7d, 0x5b, 0x08,
- 0xef, 0xd5, 0xb6, 0x77, 0x7f, 0xc6, 0xb9, 0x7b,
- 0xb6, 0xab, 0xdd, 0x89, 0x51, 0xac, 0xf2, 0x7e,
- 0xad, 0xda, 0x80, 0xe4, 0xbc, 0xb3, 0xa9, 0xb3,
- 0x7c, 0xdd, 0x86, 0x51, 0xe8, 0x4a, 0x9b, 0xd0,
- 0xcd, 0xac, 0x39, 0x57, 0x1b, 0x73, 0x6e, 0x64,
- 0x86, 0xb9, 0xeb, 0xf7, 0x6b, 0x05, 0x3b, 0xca,
- 0xcd, 0x2c, 0x20, 0x57, 0x19, 0x40, 0x6e, 0x66,
- 0xbd, 0xe0, 0x33, 0x42, 0x2e, 0xb2, 0x36, 0x3a,
- 0x54, 0x1d, 0x33, 0x72, 0xc9, 0x7b, 0x17, 0x45,
- 0x23, 0x82, 0x55, 0x76, 0x59, 0x3a, 0x23, 0xcc,
- 0x8c, 0xc9, 0x3a, 0x45, 0xef, 0xb1, 0x6b, 0x4b,
- 0xc8, 0xca, 0xde, 0x6c, 0x3c, 0xd4, 0x6d, 0x8a,
- 0x29, 0xca, 0x26, 0xfc, 0x12, 0xea, 0xd4, 0x66,
- 0xc7, 0x7d, 0xd1, 0x32, 0x9d, 0xee, 0xb9, 0xbb,
- 0x42, 0x1e, 0x0c, 0xf6, 0xd3, 0xc7, 0xf5, 0x6c,
- 0x86, 0x9e, 0xd8, 0xa3, 0xc3, 0xa7, 0xf4, 0x60,
- 0x9f, 0xe3, 0x8a, 0x00, 0x62, 0xf8, 0xb7, 0x2d,
- 0x8c, 0x4b, 0xe6, 0x5d, 0xf2, 0xba, 0x87, 0xc6,
- 0x36, 0xed, 0xa9, 0x32, 0x85, 0x58, 0xcb, 0x2c,
- 0xd6, 0x1e, 0x1c, 0xf4, 0xc3, 0xe7, 0x00, 0x5b,
- 0x1e, 0x27, 0x4f, 0x2c, 0xac, 0xdb, 0xdb, 0xa0,
- 0x4d, 0x51, 0x8c, 0x24, 0xbe, 0x8c, 0xad, 0x45,
- 0x5f, 0x7d, 0x4b, 0xae, 0xd0, 0x7d, 0x38, 0x52,
- 0xa1, 0x35, 0x6a, 0xf9, 0x56, 0xad, 0xf2, 0xa2,
- 0x19, 0xaf, 0x99, 0xd5, 0x7b, 0x81, 0xd2, 0x54,
- 0x33, 0x3e, 0x53, 0x0a, 0xa5, 0x81, 0x03, 0xdc,
- 0x13, 0xa5, 0xb7, 0x7d, 0x8e, 0xe8, 0x28, 0xaf,
- 0xbf, 0xad, 0x57, 0x6e, 0x34, 0x80, 0xae, 0x03,
- 0xad, 0xc3, 0xa3, 0x7a, 0x52, 0xf8, 0x78, 0x83,
- 0xe7, 0x6c, 0x28, 0x5d, 0xb9, 0xa7, 0xf8, 0x2d,
- 0x5c, 0x93, 0xff, 0x7f, 0xc9, 0x73, 0xe5, 0xd5
+ 0x91, 0xcf, 0x31, 0xa6, 0xa5, 0x93, 0xc2, 0x8b,
+ 0xc0, 0xe9, 0x27, 0x2c, 0x6e, 0x0d, 0x09, 0x8d,
+ 0x40, 0x6d, 0x57, 0x4d, 0x03, 0xbe, 0x56, 0x57,
+ 0x92, 0x29, 0xda, 0xf0, 0x9b, 0xeb, 0x54, 0x5d,
+ 0xef, 0xbc, 0x26, 0x07, 0xfe, 0x6d, 0x74, 0x50,
+ 0x7b, 0xc9, 0x0d, 0xf7, 0x04, 0x96, 0xb9, 0x48,
+ 0x0c, 0xf7, 0x04, 0x48, 0x2e, 0xe8, 0xde, 0x46,
+ 0x6b, 0xb0, 0x67, 0x01, 0x39, 0xc6, 0x93, 0x93,
+ 0x2a, 0xaa, 0x8b, 0xcc, 0x34, 0xd1, 0xfc, 0xd0,
+ 0xe3, 0x6b, 0xc8, 0x52, 0x37, 0x0a, 0x2a, 0xb3,
+ 0x4e, 0xc2, 0xd2, 0xdd, 0xf6, 0xe2, 0x1b, 0x23,
+ 0xb1, 0xd6, 0xa2, 0xd4, 0x6f, 0x62, 0xf7, 0xe2,
+ 0x58, 0x43, 0x68, 0xaa, 0xd5, 0xaf, 0x87, 0x5f,
+ 0x9e, 0x1d, 0xeb, 0x56, 0x45, 0x63, 0xce, 0x26,
+ 0x29, 0xdd, 0x17, 0xfe, 0x8f, 0xed, 0x2f, 0x7c,
+ 0xff, 0xe7, 0x8e, 0xb4, 0x53, 0xa8, 0x07, 0xab,
+ 0x00, 0xf3, 0xf7, 0x3a, 0x0d, 0xce, 0x69, 0xee,
+ 0xd0, 0x0d, 0x17, 0x97, 0x75, 0x2a, 0xe2, 0xc0,
+ 0x4b, 0xbb, 0xb3, 0x30, 0x88, 0xd4, 0x7b, 0x85,
+ 0x8c, 0x2d, 0x87, 0x78, 0xc9, 0x35, 0xed, 0x63,
+ 0x3d, 0x24, 0x31, 0x3c, 0x98, 0xb5, 0x86, 0xa2,
+ 0xfe, 0x77, 0x60, 0x6c, 0x5b, 0x44, 0x2b, 0x20,
+ 0x8b, 0x97, 0xf0, 0x76, 0xb6, 0xed, 0x0c, 0x64,
+ 0xc9, 0x33, 0x79, 0xe1, 0xa4, 0xd9, 0xb2, 0xf8,
+ 0x86, 0x5b, 0x03, 0xb1, 0x1f, 0xd0, 0x05, 0xb6,
+ 0xe4, 0xb9, 0x25, 0x1e, 0xc1, 0x6b, 0x4d, 0xc7,
+ 0x25, 0x1b, 0x3d, 0x06, 0x6a, 0x6b, 0xf0, 0xf6,
+ 0x73, 0x0e, 0x52, 0x9b, 0xd8, 0xb7, 0x26, 0x1c,
+ 0x4d, 0xdb, 0xcc, 0xe5, 0x5e, 0x6f, 0x45, 0xe1,
+ 0x2a, 0x49, 0xde, 0x50, 0x26, 0xf7, 0xb3, 0x32,
+ 0xc1, 0x1a, 0x26, 0x58, 0x26, 0x6a, 0xba, 0xb0,
+ 0xab, 0x26, 0x74, 0xdd, 0xcc, 0xd7, 0x57, 0xb1,
+ 0xaf, 0x2b, 0x1a, 0x57, 0x96, 0x6c, 0xac, 0xae,
+ 0xcb, 0x33, 0x46, 0x59, 0x73, 0x5a, 0x78, 0xb5,
+ 0xd5, 0x15, 0xf8, 0x2e, 0x83, 0x08, 0xdb, 0x96,
+ 0x2d, 0x3a, 0x02, 0xef, 0xc8, 0xb0, 0xf0, 0xc2,
+ 0xcd, 0x29, 0x6e, 0xaf, 0x04, 0x71, 0xe9, 0x31,
+ 0x66, 0x40, 0x3a, 0xe5, 0x1c, 0x07, 0x0e, 0xf7,
+ 0x7e, 0x52, 0xec, 0xb7, 0x62, 0xf3, 0x33, 0x84,
+ 0x09, 0x1d, 0x3e, 0x94, 0xf9, 0x62, 0x2b, 0x08,
+ 0x78, 0xdb, 0x2c, 0xd4, 0x37, 0xb5, 0x14, 0xa7,
+ 0x7c, 0x09, 0xad, 0x21, 0x76, 0x94, 0xdf, 0x86,
+ 0xc6, 0xb2, 0x53, 0xfe, 0x75, 0xe2, 0x24, 0x8b,
+ 0xb2, 0xaf, 0xaa, 0xf9, 0x40, 0xac, 0x92, 0x3b,
+ 0xac, 0x45, 0xb7, 0x6b, 0xc3, 0x5a, 0x54, 0xe5,
+ 0x6f, 0x70, 0x6c, 0x73, 0x05, 0x09, 0x45, 0xdf,
+ 0x5f, 0x17, 0xe0, 0xd8, 0x04, 0x41, 0x9f, 0x36,
+ 0x30, 0x15, 0xc5, 0xf1, 0xa2, 0xbd, 0x54, 0x1d,
+ 0xca, 0xa0, 0xff, 0x71, 0xa2, 0x23, 0xbd, 0xb1,
+ 0xda, 0x65, 0xb3, 0xf3, 0xb9, 0x3e, 0x9c, 0xf1,
+ 0xdf, 0xbe, 0x2d, 0xd7, 0x68, 0x42, 0xb3, 0x65,
+ 0x17, 0x23, 0x7c, 0xc8, 0x0f, 0x2d, 0x57, 0x31,
+ 0x70, 0xf3, 0x5e, 0x1a, 0xc9, 0x13, 0xda, 0xd9,
+ 0xd5, 0xe0, 0xd4, 0x24, 0x9b, 0x00, 0xe6, 0x83,
+ 0x71, 0x24, 0x54, 0x4c, 0xc0, 0x54, 0x10, 0x59,
+ 0x19, 0xcd, 0x02, 0x12, 0x4b, 0xef, 0xa2, 0x45,
+ 0x63, 0x41, 0x23, 0x3c, 0xe6, 0x7f, 0x73, 0xc1,
+ 0xc3, 0xf1, 0xf8, 0xc4, 0xee, 0xbe, 0x90, 0x89,
+ 0xde, 0x36, 0x3e, 0x49, 0xa3, 0xc8, 0xc9, 0x27,
+ 0x8b, 0x52, 0x78, 0x73, 0x79, 0xf1, 0x16, 0xdf,
+ 0x70, 0xda, 0xf2, 0xbe, 0xbc, 0xe4, 0x50, 0x8d,
+ 0xf6, 0x4a, 0xe8, 0x5c, 0x91, 0x39, 0x5a, 0xfe,
+ 0x2e, 0x6f, 0x1e, 0xda, 0xea, 0xf9, 0xd0, 0x17,
+ 0xae, 0x0f, 0x4b, 0x83, 0x09, 0x1f, 0xa0, 0x33,
+ 0x25, 0xd9, 0xe2, 0xba, 0xba, 0xd9, 0xe1, 0xf2,
+ 0xcb, 0x15, 0xdd, 0x6e, 0xe9, 0xfc, 0x5d, 0x9c,
+ 0x80, 0x47, 0x69, 0x9e, 0x68, 0x12, 0xfe, 0x5f,
+ 0x9c, 0xc1, 0x4e, 0x08, 0xe0, 0xfe, 0xe8, 0x22,
+ 0x14, 0x7a, 0xf4, 0xf2, 0x3d, 0xfa, 0xb6, 0x49,
+ 0x61, 0x2d, 0x53, 0xd2, 0x27, 0xaa, 0xa7, 0x70,
+ 0xb4, 0x63, 0xe6, 0xce, 0xa9, 0xae, 0x95, 0x25,
+ 0xeb, 0x74, 0x62, 0x14, 0x5e, 0x4e, 0xdd, 0xe9,
+ 0x87, 0x31, 0xa2, 0x10, 0x5d, 0xc2, 0x7f, 0x94,
+ 0x35, 0x1b, 0x1f, 0x4a, 0xf2, 0x01, 0x77, 0xcc,
+ 0xf9, 0xc0, 0xe8, 0x2b, 0xe0, 0x56, 0x44, 0x40,
+ 0x04, 0x58, 0x44, 0xcf, 0x16, 0xe9, 0x4e, 0x00,
+ 0x5f, 0x20, 0xae, 0x53, 0x32, 0x4d, 0x4a, 0x39,
+ 0xd2, 0x42, 0xb1, 0xa8, 0x70, 0x67, 0xc7, 0x58,
+ 0xf6, 0x96, 0x48, 0x84, 0xa0, 0xb5, 0xe8, 0xdd,
+ 0xe6, 0xff, 0x80, 0xe0, 0x70, 0x06, 0x2a, 0x7b,
+ 0x47, 0x81, 0x68, 0x77, 0xb0, 0x9e, 0xb0, 0xea,
+ 0xd1, 0x53, 0xce, 0x72, 0x3d, 0xf1, 0x6e, 0x67,
+ 0x7c, 0x50, 0xc6, 0x87, 0xda, 0xeb, 0xff, 0x30,
+ 0x8a, 0x9a, 0x9e, 0xca, 0x98, 0xf2, 0x86, 0xf7,
+ 0x32, 0xa6, 0x52, 0xe5, 0xa3, 0x19, 0xbb, 0xb8,
+ 0xc1, 0xb7, 0xc3, 0xad, 0xd6, 0xe8, 0xb4, 0xb0,
+ 0xf0, 0xa2, 0xa4, 0x09, 0x6b, 0x53, 0xde, 0x80,
+ 0xb5, 0xa9, 0x54, 0x89, 0xb5, 0x5d, 0xdc, 0x80,
+ 0xb5, 0x5b, 0xed, 0x0b, 0x78, 0x5d, 0x43, 0x03,
+ 0x6a, 0x78, 0x9e, 0x61, 0xca, 0xeb, 0x71, 0x35,
+ 0x75, 0x2a, 0xd1, 0xb5, 0x8b, 0x1b, 0x30, 0x76,
+ 0xab, 0x5d, 0x8d, 0x74, 0xfd, 0xa3, 0x2a, 0x5d,
+ 0x7c, 0x05, 0xca, 0xb5, 0xcf, 0xab, 0xac, 0xd2,
+ 0xab, 0x10, 0x2e, 0xf8, 0x10, 0x3d, 0x3c, 0x03,
+ 0xd5, 0x3d, 0x99, 0x15, 0xaf, 0x6d, 0xe6, 0xac,
+ 0xb6, 0x43, 0x6e, 0x6b, 0x4d, 0xc3, 0xd3, 0xd9,
+ 0xbd, 0x05, 0xdc, 0x97, 0x5f, 0x87, 0xd7, 0xb1,
+ 0xa3, 0x59, 0xfc, 0x90, 0xe4, 0x53, 0xfd, 0x67,
+ 0xe5, 0xf3, 0x1e, 0x53, 0xdc, 0x29, 0xf0, 0xca,
+ 0xba, 0x87, 0x3e, 0x2e, 0xc0, 0x4a, 0x9e, 0xd7,
+ 0x80, 0x9d, 0xc5, 0xf7, 0x08, 0xae, 0xfe, 0xb3,
+ 0x12, 0x3b, 0x53, 0xdc, 0x29, 0xf0, 0xc4, 0x3a,
+ 0xec, 0x5c, 0x80, 0x95, 0xbc, 0xed, 0x33, 0x79,
+ 0x16, 0x64, 0x71, 0x31, 0x3d, 0x53, 0xf5, 0xef,
+ 0x4b, 0x4c, 0x71, 0xa7, 0xc0, 0xe1, 0xea, 0xf0,
+ 0x72, 0x01, 0x56, 0xb2, 0xaa, 0xab, 0xb0, 0xd3,
+ 0xfe, 0x6a, 0xfa, 0xaf, 0x7a, 0xdc, 0xd4, 0x4b,
+ 0x2e, 0x8b, 0x91, 0x35, 0x62, 0xa6, 0xfd, 0xde,
+ 0xaa, 0x58, 0xd2, 0x67, 0x6a, 0xb9, 0x2d, 0x1a,
+ 0x6e, 0x77, 0x96, 0xdb, 0x3f, 0x9d, 0xe5, 0xf6,
+ 0x95, 0x8c, 0xef, 0x82, 0xa7, 0x25, 0x0a, 0xbd,
+ 0xd2, 0xc0, 0x68, 0xb2, 0xae, 0x2e, 0xf1, 0x7d,
+ 0x53, 0xe4, 0x5d, 0x26, 0x6b, 0x7a, 0xe1, 0x31,
+ 0x4d, 0x94, 0x0b, 0x23, 0xd7, 0xcb, 0x60, 0x73,
+ 0x05, 0x1d, 0x2b, 0xed, 0xe8, 0x64, 0x41, 0xf9,
+ 0x45, 0x33, 0x06, 0xa9, 0x9d, 0x87, 0x34, 0x2e,
+ 0x2a, 0x56, 0x40, 0x1a, 0x44, 0xfc, 0xce, 0x08,
+ 0x64, 0x7b, 0x9d, 0x0d, 0x99, 0xa0, 0xd9, 0xcf,
+ 0x44, 0x28, 0xb9, 0x72, 0x80, 0x4e, 0x4c, 0xe8,
+ 0x90, 0x21, 0xc3, 0xd1, 0xa0, 0x47, 0x3e, 0xa7,
+ 0x3f, 0xf5, 0x2f, 0x75, 0x12, 0x56, 0x3c, 0xa2,
+ 0xe4, 0x9b, 0x18, 0xdb, 0x39, 0x9e, 0x8e, 0xd0,
+ 0x5e, 0xcd, 0x68, 0x31, 0x54, 0x4c, 0xf5, 0x80,
+ 0x29, 0x92, 0x8c, 0x1e, 0x76, 0x5c, 0xc0, 0xf0,
+ 0x3a, 0xe3, 0x8d, 0xbc, 0x74, 0x5e, 0x18, 0x2e,
+ 0x96, 0x4b, 0x52, 0x02, 0x5d, 0x85, 0xde, 0xa8,
+ 0x58, 0xce, 0x98, 0xcb, 0xde, 0x76, 0x03, 0xa7,
+ 0xdc, 0xe8, 0x57, 0x8f, 0xfa, 0xcf, 0x61, 0x74,
+ 0xdf, 0xc6, 0xe0, 0x7e, 0xfb, 0xc6, 0xf6, 0xcf,
+ 0xc8, 0xd0, 0xce, 0x2c, 0x45, 0xd2, 0x28, 0xd1,
+ 0xfa, 0x63, 0x05, 0xa8, 0xeb, 0x45, 0xe1, 0x3c,
+ 0xc6, 0xd3, 0xe2, 0x18, 0x89, 0xff, 0x31, 0x79,
+ 0xd6, 0xc1, 0x8a, 0x84, 0x1f, 0x00, 0x5b, 0x2f,
+ 0xe2, 0xda, 0x98, 0xd3, 0x9c, 0x12, 0x0e, 0x27,
+ 0xec, 0x66, 0x47, 0xaf, 0x57, 0xec, 0x0e, 0xde,
+ 0x24, 0x20, 0x89, 0xcd, 0x51, 0x43, 0xc6, 0x2d,
+ 0x43, 0xb4, 0xca, 0x67, 0x4f, 0x18, 0x1b, 0xee,
+ 0x23, 0xb7, 0x0f, 0x6d, 0xaf, 0xd4, 0xdb, 0x60,
+ 0xe8, 0x90, 0x05, 0xee, 0x2a, 0xab, 0x37, 0xe5,
+ 0x8a, 0x8c, 0xbd, 0xd8, 0xf0, 0x65, 0x4b, 0x09,
+ 0x4a, 0x84, 0x39, 0x3f, 0xa1, 0x5c, 0x06, 0x1e,
+ 0x85, 0x7e, 0x02, 0x6c, 0x6a, 0xfb, 0xeb, 0xed,
+ 0x2e, 0x11, 0x76, 0x97, 0x08, 0x5f, 0xdc, 0x25,
+ 0x82, 0xe1, 0x2a, 0xee, 0x8b, 0x31, 0xe7, 0xb1,
+ 0x99, 0x2d, 0x53, 0x7e, 0x16, 0xd7, 0x0d, 0xea,
+ 0x21, 0xaf, 0x36, 0xf6, 0x4d, 0x6f, 0xe1, 0xfe,
+ 0x41, 0x5e, 0x64, 0x90, 0x42, 0xab, 0x1e, 0x88,
+ 0xe1, 0xdb, 0xd8, 0x0b, 0x0a, 0xcf, 0x65, 0x62,
+ 0x92, 0xb1, 0x72, 0xab, 0x7c, 0xd9, 0xac, 0x69,
+ 0xed, 0x08, 0x0e, 0x07, 0x56, 0x8b, 0x17, 0x5f,
+ 0x72, 0xa8, 0x18, 0x47, 0x67, 0xdf, 0x7d, 0x3f,
+ 0x7e, 0xfd, 0x4f, 0x71, 0x64, 0x85, 0x8f, 0x7a,
+ 0xf9, 0xdd, 0x0f, 0x2f, 0xc7, 0x3f, 0xbc, 0xf8,
+ 0xfb, 0xdf, 0x5f, 0xc0, 0x64, 0x0c, 0x07, 0x87,
+ 0xfd, 0xf2, 0xfb, 0x87, 0x2a, 0xf3, 0x03, 0x2a,
+ 0x1b, 0x27, 0x5b, 0x58, 0x1a, 0xef, 0xdb, 0x46,
+ 0x78, 0xaf, 0xd6, 0xbd, 0xfb, 0x33, 0xcf, 0xdd,
+ 0xb3, 0x65, 0xed, 0x4e, 0xcc, 0x62, 0x95, 0x37,
+ 0x6c, 0xd5, 0x26, 0x24, 0xe7, 0xad, 0x4d, 0x9d,
+ 0xed, 0xeb, 0x36, 0xcc, 0x42, 0x57, 0x5a, 0x85,
+ 0x6e, 0x66, 0xcf, 0xb9, 0xda, 0x9c, 0x73, 0x23,
+ 0x43, 0xcc, 0x5d, 0xbf, 0x61, 0x2b, 0x58, 0x52,
+ 0x6e, 0x66, 0x03, 0xb9, 0xca, 0x04, 0x72, 0x33,
+ 0xfb, 0x05, 0x9f, 0x11, 0x72, 0x91, 0xb5, 0xd9,
+ 0xa1, 0xea, 0x98, 0x91, 0x4b, 0xde, 0xbb, 0x28,
+ 0x9a, 0x11, 0xac, 0xb2, 0xcb, 0xd2, 0x19, 0x61,
+ 0x66, 0x4c, 0xd6, 0x29, 0x7a, 0x90, 0x5d, 0x5b,
+ 0x42, 0x56, 0x16, 0x67, 0xe3, 0xa5, 0x6e, 0x53,
+ 0x4c, 0x51, 0x36, 0xe1, 0xd7, 0x50, 0xa7, 0x36,
+ 0x3b, 0xee, 0x8b, 0x96, 0xe9, 0x74, 0xcf, 0xdd,
+ 0x15, 0xf2, 0x60, 0xb0, 0x9f, 0x3f, 0xae, 0x67,
+ 0x33, 0xf4, 0xc6, 0x26, 0x33, 0x02, 0xc8, 0x52,
+ 0x1c, 0x5b, 0xc4, 0x31, 0x2b, 0x68, 0xd3, 0x05,
+ 0xce, 0x74, 0xc9, 0xf3, 0x1e, 0x1a, 0xdb, 0xb4,
+ 0xa7, 0xca, 0x14, 0x62, 0x2d, 0xb3, 0x58, 0x7b,
+ 0x70, 0xd0, 0x0f, 0x9f, 0x03, 0x6c, 0x79, 0x9c,
+ 0x3c, 0xb1, 0xb0, 0x6e, 0x6f, 0x83, 0x36, 0x45,
+ 0x32, 0x92, 0xf8, 0x32, 0xb6, 0x16, 0x7d, 0xf5,
+ 0x2d, 0xb9, 0x42, 0xf7, 0xe1, 0x48, 0x85, 0xd6,
+ 0xa8, 0xe5, 0x7b, 0xb5, 0xca, 0xab, 0x66, 0xbc,
+ 0x68, 0x56, 0x6f, 0x06, 0x4a, 0x53, 0xcd, 0xf8,
+ 0x4c, 0x29, 0x9c, 0x06, 0x0e, 0x70, 0x4f, 0x94,
+ 0xde, 0xf7, 0x39, 0xa2, 0xa3, 0xbc, 0x00, 0xb7,
+ 0x5e, 0xba, 0xd1, 0x00, 0xba, 0x0e, 0xb4, 0x0e,
+ 0x8f, 0xea, 0x49, 0xe1, 0xe3, 0x0d, 0x9e, 0xb4,
+ 0xa1, 0x74, 0xe5, 0x9e, 0xe2, 0xb7, 0x70, 0x51,
+ 0xfe, 0xff, 0x01, 0x25, 0x68, 0xe6, 0xc5
};
static std::string decompressed = util::decompress(std::string(reinterpret_cast<const char*>(compressed), sizeof(compressed)));
return decompressed.c_str();
diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp
index 9e33b99def..db758b656b 100644
--- a/src/mbgl/shaders/symbol_icon.cpp
+++ b/src/mbgl/shaders/symbol_icon.cpp
@@ -8,7 +8,7 @@ namespace shaders {
const char* symbol_icon::name = "symbol_icon";
const char* symbol_icon::vertexSource = source() + 59607;
-const char* symbol_icon::fragmentSource = source() + 63011;
+const char* symbol_icon::fragmentSource = source() + 63013;
} // namespace shaders
} // namespace mbgl
diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp
index 3443b4f21c..de9d3729a3 100644
--- a/src/mbgl/shaders/symbol_sdf.cpp
+++ b/src/mbgl/shaders/symbol_sdf.cpp
@@ -7,8 +7,8 @@ namespace mbgl {
namespace shaders {
const char* symbol_sdf::name = "symbol_sdf";
-const char* symbol_sdf::vertexSource = source() + 63461;
-const char* symbol_sdf::fragmentSource = source() + 69382;
+const char* symbol_sdf::vertexSource = source() + 63463;
+const char* symbol_sdf::fragmentSource = source() + 69386;
} // namespace shaders
} // namespace mbgl
diff --git a/src/mbgl/style/conversion/color_ramp_property_value.cpp b/src/mbgl/style/conversion/color_ramp_property_value.cpp
index f29438b6a2..0da16c67ee 100644
--- a/src/mbgl/style/conversion/color_ramp_property_value.cpp
+++ b/src/mbgl/style/conversion/color_ramp_property_value.cpp
@@ -1,6 +1,6 @@
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/is_expression.hpp>
diff --git a/src/mbgl/style/conversion/constant.cpp b/src/mbgl/style/conversion/constant.cpp
index d432b5f051..de4ab22269 100644
--- a/src/mbgl/style/conversion/constant.cpp
+++ b/src/mbgl/style/conversion/constant.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
@@ -31,6 +32,38 @@ optional<std::string> Converter<std::string>::operator()(const Convertible& valu
return *converted;
}
+template <class T>
+optional<T> Converter<T, typename std::enable_if_t<std::is_enum<T>::value>>::operator()(const Convertible& value, Error& error) const {
+ optional<std::string> string = toString(value);
+ if (!string) {
+ error.message = "value must be a string";
+ return nullopt;
+ }
+
+ const auto result = Enum<T>::toEnum(*string);
+ if (!result) {
+ error.message = "value must be a valid enumeration value";
+ return nullopt;
+ }
+
+ return *result;
+}
+
+template optional<AlignmentType> Converter<AlignmentType>::operator()(const Convertible&, Error&) const;
+template optional<CirclePitchScaleType> Converter<CirclePitchScaleType>::operator()(const Convertible&, Error&) const;
+template optional<HillshadeIlluminationAnchorType> Converter<HillshadeIlluminationAnchorType>::operator()(const Convertible&, Error&) const;
+template optional<IconTextFitType> Converter<IconTextFitType>::operator()(const Convertible&, Error&) const;
+template optional<LightAnchorType> Converter<LightAnchorType>::operator()(const Convertible&, Error&) const;
+template optional<LineCapType> Converter<LineCapType>::operator()(const Convertible&, Error&) const;
+template optional<LineJoinType> Converter<LineJoinType>::operator()(const Convertible&, Error&) const;
+template optional<RasterResamplingType> Converter<RasterResamplingType>::operator()(const Convertible&, Error&) const;
+template optional<SymbolAnchorType> Converter<SymbolAnchorType>::operator()(const Convertible&, Error&) const;
+template optional<SymbolPlacementType> Converter<SymbolPlacementType>::operator()(const Convertible&, Error&) const;
+template optional<TextJustifyType> Converter<TextJustifyType>::operator()(const Convertible&, Error&) const;
+template optional<TextTransformType> Converter<TextTransformType>::operator()(const Convertible&, Error&) const;
+template optional<TranslateAnchorType> Converter<TranslateAnchorType>::operator()(const Convertible&, Error&) const;
+template optional<VisibilityType> Converter<VisibilityType>::operator()(const Convertible&, Error&) const;
+
optional<Color> Converter<Color>::operator()(const Convertible& value, Error& error) const {
optional<std::string> string = toString(value);
if (!string) {
@@ -47,6 +80,29 @@ optional<Color> Converter<Color>::operator()(const Convertible& value, Error& er
return *color;
}
+template <size_t N>
+optional<std::array<float, N>> Converter<std::array<float, N>>::operator()(const Convertible& value, Error& error) const {
+ if (!isArray(value) || arrayLength(value) != N) {
+ error.message = "value must be an array of " + util::toString(N) + " numbers";
+ return nullopt;
+ }
+
+ std::array<float, N> result;
+ for (size_t i = 0; i < N; i++) {
+ optional<float> n = toNumber(arrayMember(value, i));
+ if (!n) {
+ error.message = "value must be an array of " + util::toString(N) + " numbers";
+ return nullopt;
+ }
+ result[i] = *n;
+ }
+ return result;
+}
+
+template optional<std::array<float, 2>> Converter<std::array<float, 2>>::operator()(const Convertible&, Error&) const;
+template optional<std::array<float, 3>> Converter<std::array<float, 3>>::operator()(const Convertible&, Error&) const;
+template optional<std::array<float, 4>> Converter<std::array<float, 4>>::operator()(const Convertible&, Error&) const;
+
optional<std::vector<float>> Converter<std::vector<float>>::operator()(const Convertible& value, Error& error) const {
if (!isArray(value)) {
error.message = "value must be an array";
diff --git a/src/mbgl/style/conversion/coordinate.cpp b/src/mbgl/style/conversion/coordinate.cpp
index 20abd45e26..ee03bffb30 100644
--- a/src/mbgl/style/conversion/coordinate.cpp
+++ b/src/mbgl/style/conversion/coordinate.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/coordinate.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/conversion/custom_geometry_source_options.cpp b/src/mbgl/style/conversion/custom_geometry_source_options.cpp
index 8983f9f479..491509c28f 100644
--- a/src/mbgl/style/conversion/custom_geometry_source_options.cpp
+++ b/src/mbgl/style/conversion/custom_geometry_source_options.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/custom_geometry_source_options.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/conversion/filter.cpp b/src/mbgl/style/conversion/filter.cpp
index 5114c61778..fc25ab0b0d 100644
--- a/src/mbgl/style/conversion/filter.cpp
+++ b/src/mbgl/style/conversion/filter.cpp
@@ -1,10 +1,11 @@
#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/literal.hpp>
-#include <mbgl/util/geometry.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/type.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/boolean_operator.hpp>
+#include <mbgl/util/geometry.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/conversion/function.cpp b/src/mbgl/style/conversion/function.cpp
index 1cc49e483a..6aadaad3b3 100644
--- a/src/mbgl/style/conversion/function.cpp
+++ b/src/mbgl/style/conversion/function.cpp
@@ -1,4 +1,6 @@
#include <mbgl/style/conversion/function.hpp>
+#include <mbgl/style/conversion/position.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/interpolate.hpp>
@@ -70,6 +72,72 @@ std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& so
}
}
+template <class T>
+optional<PropertyExpression<T>> convertFunctionToExpression(const Convertible& value, Error& error, bool convertTokens) {
+ auto expression = convertFunctionToExpression(expression::valueTypeToExpressionType<T>(), value, error, convertTokens);
+ if (!expression) {
+ return nullopt;
+ }
+
+ optional<T> defaultValue;
+
+ auto defaultValueValue = objectMember(value, "default");
+ if (defaultValueValue) {
+ defaultValue = convert<T>(*defaultValueValue, error);
+ if (!defaultValue) {
+ error.message = R"(wrong type for "default": )" + error.message;
+ return nullopt;
+ }
+ }
+
+ return PropertyExpression<T>(std::move(*expression), defaultValue);
+}
+
+template optional<PropertyExpression<AlignmentType>>
+ convertFunctionToExpression<AlignmentType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<bool>>
+ convertFunctionToExpression<bool>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<CirclePitchScaleType>>
+ convertFunctionToExpression<CirclePitchScaleType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<float>>
+ convertFunctionToExpression<float>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<HillshadeIlluminationAnchorType>>
+ convertFunctionToExpression<HillshadeIlluminationAnchorType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<IconTextFitType>>
+ convertFunctionToExpression<IconTextFitType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<LightAnchorType>>
+ convertFunctionToExpression<LightAnchorType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<LineCapType>>
+ convertFunctionToExpression<LineCapType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<LineJoinType>>
+ convertFunctionToExpression<LineJoinType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<Color>>
+ convertFunctionToExpression<Color>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<Position>>
+ convertFunctionToExpression<Position>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<RasterResamplingType>>
+ convertFunctionToExpression<RasterResamplingType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<std::array<float, 2>>>
+ convertFunctionToExpression<std::array<float, 2>>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<std::array<float, 4>>>
+ convertFunctionToExpression<std::array<float, 4>>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<std::string>>
+ convertFunctionToExpression<std::string>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<std::vector<float>>>
+ convertFunctionToExpression<std::vector<float>>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<std::vector<std::string>>>
+ convertFunctionToExpression<std::vector<std::string>>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<SymbolAnchorType>>
+ convertFunctionToExpression<SymbolAnchorType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<SymbolPlacementType>>
+ convertFunctionToExpression<SymbolPlacementType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<TextJustifyType>>
+ convertFunctionToExpression<TextJustifyType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<TextTransformType>>
+ convertFunctionToExpression<TextTransformType>(const Convertible&, Error&, bool);
+template optional<PropertyExpression<TranslateAnchorType>>
+ convertFunctionToExpression<TranslateAnchorType>(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
// an integer).
diff --git a/src/mbgl/style/conversion/geojson.cpp b/src/mbgl/style/conversion/geojson.cpp
index e39a1a80eb..c2d34c5491 100644
--- a/src/mbgl/style/conversion/geojson.cpp
+++ b/src/mbgl/style/conversion/geojson.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/conversion/geojson_options.cpp b/src/mbgl/style/conversion/geojson_options.cpp
index 52a5030c34..11bd7cc507 100644
--- a/src/mbgl/style/conversion/geojson_options.cpp
+++ b/src/mbgl/style/conversion/geojson_options.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/geojson_options.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
@@ -77,6 +78,16 @@ optional<GeoJSONOptions> Converter<GeoJSONOptions>::operator()(const Convertible
}
}
+ const auto lineMetricsValue = objectMember(value, "lineMetrics");
+ if (lineMetricsValue) {
+ if (toBool(*lineMetricsValue)) {
+ options.lineMetrics = *toBool(*lineMetricsValue);
+ } else {
+ error = { "GeoJSON source lineMetrics value must be a boolean" };
+ return nullopt;
+ }
+ }
+
return { options };
}
diff --git a/src/mbgl/style/conversion/get_json_type.cpp b/src/mbgl/style/conversion/get_json_type.cpp
index cd3b4608b1..2e9d35a957 100644
--- a/src/mbgl/style/conversion/get_json_type.cpp
+++ b/src/mbgl/style/conversion/get_json_type.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/get_json_type.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/feature.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/conversion/json.hpp b/src/mbgl/style/conversion/json.hpp
index 7dd2378f6b..3a7bf2b557 100644
--- a/src/mbgl/style/conversion/json.hpp
+++ b/src/mbgl/style/conversion/json.hpp
@@ -1,4 +1,6 @@
-#include <mbgl/style/conversion.hpp>
+#pragma once
+
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/rapidjson_conversion.hpp>
#include <string>
diff --git a/src/mbgl/style/conversion/layer.cpp b/src/mbgl/style/conversion/layer.cpp
index e18ad923f2..085d7ae4c6 100644
--- a/src/mbgl/style/conversion/layer.cpp
+++ b/src/mbgl/style/conversion/layer.cpp
@@ -1,7 +1,7 @@
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/filter.hpp>
-#include <mbgl/style/conversion/make_property_setters.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -16,24 +16,6 @@ namespace mbgl {
namespace style {
namespace conversion {
-optional<Error> setLayoutProperty(Layer& layer, const std::string& name, const Convertible& value) {
- static const auto setters = makeLayoutPropertySetters();
- auto it = setters.find(name);
- if (it == setters.end()) {
- return Error { "property not found" };
- }
- return it->second(layer, value);
-}
-
-optional<Error> setPaintProperty(Layer& layer, const std::string& name, const Convertible& value) {
- static const auto setters = makePaintPropertySetters();
- auto it = setters.find(name);
- if (it == setters.end()) {
- return Error { "property not found" };
- }
- return it->second(layer, value);
-}
-
optional<Error> setPaintProperties(Layer& layer, const Convertible& value) {
auto paintValue = objectMember(value, "paint");
if (!paintValue) {
@@ -43,7 +25,7 @@ optional<Error> setPaintProperties(Layer& layer, const Convertible& value) {
return { { "paint must be an object" } };
}
return eachMember(*paintValue, [&] (const std::string& k, const Convertible& v) {
- return setPaintProperty(layer, k, v);
+ return layer.setPaintProperty(k, v);
});
}
@@ -210,7 +192,7 @@ optional<std::unique_ptr<Layer>> Converter<std::unique_ptr<Layer>>::operator()(c
return nullopt;
}
optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const Convertible& v) {
- return setLayoutProperty(*layer, k, v);
+ return layer->setLayoutProperty(k, v);
});
if (error_) {
error = *error_;
diff --git a/src/mbgl/style/conversion/light.cpp b/src/mbgl/style/conversion/light.cpp
index 7b96c89a1c..e8723216ee 100644
--- a/src/mbgl/style/conversion/light.cpp
+++ b/src/mbgl/style/conversion/light.cpp
@@ -2,6 +2,7 @@
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/conversion/make_property_setters.hpp b/src/mbgl/style/conversion/make_property_setters.hpp
deleted file mode 100644
index ada0d53002..0000000000
--- a/src/mbgl/style/conversion/make_property_setters.hpp
+++ /dev/null
@@ -1,239 +0,0 @@
-#pragma once
-
-// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
-
-#include <mbgl/style/conversion/property_setter.hpp>
-
-#include <mbgl/style/layers/fill_layer.hpp>
-#include <mbgl/style/layers/line_layer.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/style/layers/circle_layer.hpp>
-#include <mbgl/style/layers/heatmap_layer.hpp>
-#include <mbgl/style/layers/fill_extrusion_layer.hpp>
-#include <mbgl/style/layers/raster_layer.hpp>
-#include <mbgl/style/layers/hillshade_layer.hpp>
-#include <mbgl/style/layers/background_layer.hpp>
-
-#include <unordered_map>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-inline auto makeLayoutPropertySetters() {
- std::unordered_map<std::string, PropertySetter> result;
-
- result["visibility"] = &setVisibility;
-
-
- result["line-cap"] = &setProperty<LineLayer, PropertyValue<LineCapType>, &LineLayer::setLineCap, false, false>;
- result["line-join"] = &setProperty<LineLayer, PropertyValue<LineJoinType>, &LineLayer::setLineJoin, true, false>;
- result["line-miter-limit"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineMiterLimit, false, false>;
- result["line-round-limit"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineRoundLimit, false, false>;
-
- result["symbol-placement"] = &setProperty<SymbolLayer, PropertyValue<SymbolPlacementType>, &SymbolLayer::setSymbolPlacement, false, false>;
- result["symbol-spacing"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setSymbolSpacing, false, false>;
- result["symbol-avoid-edges"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setSymbolAvoidEdges, false, false>;
- result["icon-allow-overlap"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconAllowOverlap, false, false>;
- result["icon-ignore-placement"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconIgnorePlacement, false, false>;
- result["icon-optional"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconOptional, false, false>;
- result["icon-rotation-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconRotationAlignment, false, false>;
- result["icon-size"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconSize, true, false>;
- result["icon-text-fit"] = &setProperty<SymbolLayer, PropertyValue<IconTextFitType>, &SymbolLayer::setIconTextFit, false, false>;
- result["icon-text-fit-padding"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 4>>, &SymbolLayer::setIconTextFitPadding, false, false>;
- result["icon-image"] = &setProperty<SymbolLayer, PropertyValue<std::string>, &SymbolLayer::setIconImage, true, true>;
- result["icon-rotate"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconRotate, true, false>;
- result["icon-padding"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconPadding, false, false>;
- result["icon-keep-upright"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setIconKeepUpright, false, false>;
- result["icon-offset"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setIconOffset, true, false>;
- result["icon-anchor"] = &setProperty<SymbolLayer, PropertyValue<SymbolAnchorType>, &SymbolLayer::setIconAnchor, true, false>;
- result["icon-pitch-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setIconPitchAlignment, false, false>;
- result["text-pitch-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextPitchAlignment, false, false>;
- result["text-rotation-alignment"] = &setProperty<SymbolLayer, PropertyValue<AlignmentType>, &SymbolLayer::setTextRotationAlignment, false, false>;
- result["text-field"] = &setProperty<SymbolLayer, PropertyValue<std::string>, &SymbolLayer::setTextField, true, true>;
- result["text-font"] = &setProperty<SymbolLayer, PropertyValue<std::vector<std::string>>, &SymbolLayer::setTextFont, true, false>;
- result["text-size"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextSize, true, false>;
- result["text-max-width"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxWidth, true, false>;
- result["text-line-height"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLineHeight, false, false>;
- result["text-letter-spacing"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextLetterSpacing, true, false>;
- result["text-justify"] = &setProperty<SymbolLayer, PropertyValue<TextJustifyType>, &SymbolLayer::setTextJustify, true, false>;
- result["text-anchor"] = &setProperty<SymbolLayer, PropertyValue<SymbolAnchorType>, &SymbolLayer::setTextAnchor, true, false>;
- result["text-max-angle"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextMaxAngle, false, false>;
- result["text-rotate"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextRotate, true, false>;
- result["text-padding"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextPadding, false, false>;
- result["text-keep-upright"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextKeepUpright, false, false>;
- result["text-transform"] = &setProperty<SymbolLayer, PropertyValue<TextTransformType>, &SymbolLayer::setTextTransform, true, false>;
- result["text-offset"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextOffset, true, false>;
- result["text-allow-overlap"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextAllowOverlap, false, false>;
- result["text-ignore-placement"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextIgnorePlacement, false, false>;
- result["text-optional"] = &setProperty<SymbolLayer, PropertyValue<bool>, &SymbolLayer::setTextOptional, false, false>;
-
-
-
-
-
-
-
- return result;
-}
-
-inline auto makePaintPropertySetters() {
- std::unordered_map<std::string, PropertySetter> result;
-
- result["fill-antialias"] = &setProperty<FillLayer, PropertyValue<bool>, &FillLayer::setFillAntialias, false, false>;
- result["fill-antialias-transition"] = &setTransition<FillLayer, &FillLayer::setFillAntialiasTransition>;
- result["fill-opacity"] = &setProperty<FillLayer, PropertyValue<float>, &FillLayer::setFillOpacity, true, false>;
- result["fill-opacity-transition"] = &setTransition<FillLayer, &FillLayer::setFillOpacityTransition>;
- result["fill-color"] = &setProperty<FillLayer, PropertyValue<Color>, &FillLayer::setFillColor, true, false>;
- result["fill-color-transition"] = &setTransition<FillLayer, &FillLayer::setFillColorTransition>;
- result["fill-outline-color"] = &setProperty<FillLayer, PropertyValue<Color>, &FillLayer::setFillOutlineColor, true, false>;
- result["fill-outline-color-transition"] = &setTransition<FillLayer, &FillLayer::setFillOutlineColorTransition>;
- result["fill-translate"] = &setProperty<FillLayer, PropertyValue<std::array<float, 2>>, &FillLayer::setFillTranslate, false, false>;
- result["fill-translate-transition"] = &setTransition<FillLayer, &FillLayer::setFillTranslateTransition>;
- result["fill-translate-anchor"] = &setProperty<FillLayer, PropertyValue<TranslateAnchorType>, &FillLayer::setFillTranslateAnchor, false, false>;
- result["fill-translate-anchor-transition"] = &setTransition<FillLayer, &FillLayer::setFillTranslateAnchorTransition>;
- result["fill-pattern"] = &setProperty<FillLayer, PropertyValue<std::string>, &FillLayer::setFillPattern, false, false>;
- result["fill-pattern-transition"] = &setTransition<FillLayer, &FillLayer::setFillPatternTransition>;
-
- result["line-opacity"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineOpacity, true, false>;
- result["line-opacity-transition"] = &setTransition<LineLayer, &LineLayer::setLineOpacityTransition>;
- result["line-color"] = &setProperty<LineLayer, PropertyValue<Color>, &LineLayer::setLineColor, true, false>;
- result["line-color-transition"] = &setTransition<LineLayer, &LineLayer::setLineColorTransition>;
- result["line-translate"] = &setProperty<LineLayer, PropertyValue<std::array<float, 2>>, &LineLayer::setLineTranslate, false, false>;
- result["line-translate-transition"] = &setTransition<LineLayer, &LineLayer::setLineTranslateTransition>;
- result["line-translate-anchor"] = &setProperty<LineLayer, PropertyValue<TranslateAnchorType>, &LineLayer::setLineTranslateAnchor, false, false>;
- result["line-translate-anchor-transition"] = &setTransition<LineLayer, &LineLayer::setLineTranslateAnchorTransition>;
- result["line-width"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineWidth, true, false>;
- result["line-width-transition"] = &setTransition<LineLayer, &LineLayer::setLineWidthTransition>;
- result["line-gap-width"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineGapWidth, true, false>;
- result["line-gap-width-transition"] = &setTransition<LineLayer, &LineLayer::setLineGapWidthTransition>;
- result["line-offset"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineOffset, true, false>;
- result["line-offset-transition"] = &setTransition<LineLayer, &LineLayer::setLineOffsetTransition>;
- result["line-blur"] = &setProperty<LineLayer, PropertyValue<float>, &LineLayer::setLineBlur, true, false>;
- result["line-blur-transition"] = &setTransition<LineLayer, &LineLayer::setLineBlurTransition>;
- result["line-dasharray"] = &setProperty<LineLayer, PropertyValue<std::vector<float>>, &LineLayer::setLineDasharray, false, false>;
- result["line-dasharray-transition"] = &setTransition<LineLayer, &LineLayer::setLineDasharrayTransition>;
- result["line-pattern"] = &setProperty<LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern, false, false>;
- result["line-pattern-transition"] = &setTransition<LineLayer, &LineLayer::setLinePatternTransition>;
-
- result["icon-opacity"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconOpacity, true, false>;
- result["icon-opacity-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconOpacityTransition>;
- result["icon-color"] = &setProperty<SymbolLayer, PropertyValue<Color>, &SymbolLayer::setIconColor, true, false>;
- result["icon-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconColorTransition>;
- result["icon-halo-color"] = &setProperty<SymbolLayer, PropertyValue<Color>, &SymbolLayer::setIconHaloColor, true, false>;
- result["icon-halo-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconHaloColorTransition>;
- result["icon-halo-width"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconHaloWidth, true, false>;
- result["icon-halo-width-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconHaloWidthTransition>;
- result["icon-halo-blur"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setIconHaloBlur, true, false>;
- result["icon-halo-blur-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconHaloBlurTransition>;
- result["icon-translate"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setIconTranslate, false, false>;
- result["icon-translate-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconTranslateTransition>;
- result["icon-translate-anchor"] = &setProperty<SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setIconTranslateAnchor, false, false>;
- result["icon-translate-anchor-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconTranslateAnchorTransition>;
- result["text-opacity"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextOpacity, true, false>;
- result["text-opacity-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextOpacityTransition>;
- result["text-color"] = &setProperty<SymbolLayer, PropertyValue<Color>, &SymbolLayer::setTextColor, true, false>;
- result["text-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextColorTransition>;
- result["text-halo-color"] = &setProperty<SymbolLayer, PropertyValue<Color>, &SymbolLayer::setTextHaloColor, true, false>;
- result["text-halo-color-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextHaloColorTransition>;
- result["text-halo-width"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextHaloWidth, true, false>;
- result["text-halo-width-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextHaloWidthTransition>;
- result["text-halo-blur"] = &setProperty<SymbolLayer, PropertyValue<float>, &SymbolLayer::setTextHaloBlur, true, false>;
- result["text-halo-blur-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextHaloBlurTransition>;
- result["text-translate"] = &setProperty<SymbolLayer, PropertyValue<std::array<float, 2>>, &SymbolLayer::setTextTranslate, false, false>;
- result["text-translate-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextTranslateTransition>;
- result["text-translate-anchor"] = &setProperty<SymbolLayer, PropertyValue<TranslateAnchorType>, &SymbolLayer::setTextTranslateAnchor, false, false>;
- result["text-translate-anchor-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setTextTranslateAnchorTransition>;
-
- result["circle-radius"] = &setProperty<CircleLayer, PropertyValue<float>, &CircleLayer::setCircleRadius, true, false>;
- result["circle-radius-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleRadiusTransition>;
- result["circle-color"] = &setProperty<CircleLayer, PropertyValue<Color>, &CircleLayer::setCircleColor, true, false>;
- result["circle-color-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleColorTransition>;
- result["circle-blur"] = &setProperty<CircleLayer, PropertyValue<float>, &CircleLayer::setCircleBlur, true, false>;
- result["circle-blur-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleBlurTransition>;
- result["circle-opacity"] = &setProperty<CircleLayer, PropertyValue<float>, &CircleLayer::setCircleOpacity, true, false>;
- result["circle-opacity-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleOpacityTransition>;
- result["circle-translate"] = &setProperty<CircleLayer, PropertyValue<std::array<float, 2>>, &CircleLayer::setCircleTranslate, false, false>;
- result["circle-translate-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleTranslateTransition>;
- result["circle-translate-anchor"] = &setProperty<CircleLayer, PropertyValue<TranslateAnchorType>, &CircleLayer::setCircleTranslateAnchor, false, false>;
- result["circle-translate-anchor-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleTranslateAnchorTransition>;
- result["circle-pitch-scale"] = &setProperty<CircleLayer, PropertyValue<CirclePitchScaleType>, &CircleLayer::setCirclePitchScale, false, false>;
- result["circle-pitch-scale-transition"] = &setTransition<CircleLayer, &CircleLayer::setCirclePitchScaleTransition>;
- result["circle-pitch-alignment"] = &setProperty<CircleLayer, PropertyValue<AlignmentType>, &CircleLayer::setCirclePitchAlignment, false, false>;
- result["circle-pitch-alignment-transition"] = &setTransition<CircleLayer, &CircleLayer::setCirclePitchAlignmentTransition>;
- result["circle-stroke-width"] = &setProperty<CircleLayer, PropertyValue<float>, &CircleLayer::setCircleStrokeWidth, true, false>;
- result["circle-stroke-width-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleStrokeWidthTransition>;
- result["circle-stroke-color"] = &setProperty<CircleLayer, PropertyValue<Color>, &CircleLayer::setCircleStrokeColor, true, false>;
- result["circle-stroke-color-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleStrokeColorTransition>;
- result["circle-stroke-opacity"] = &setProperty<CircleLayer, PropertyValue<float>, &CircleLayer::setCircleStrokeOpacity, true, false>;
- result["circle-stroke-opacity-transition"] = &setTransition<CircleLayer, &CircleLayer::setCircleStrokeOpacityTransition>;
-
- result["heatmap-radius"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapRadius, true, false>;
- result["heatmap-radius-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapRadiusTransition>;
- result["heatmap-weight"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapWeight, true, false>;
- result["heatmap-weight-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapWeightTransition>;
- result["heatmap-intensity"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapIntensity, false, false>;
- result["heatmap-intensity-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapIntensityTransition>;
- result["heatmap-color"] = &setProperty<HeatmapLayer, ColorRampPropertyValue, &HeatmapLayer::setHeatmapColor, false, false>;
- result["heatmap-color-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapColorTransition>;
- result["heatmap-opacity"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapOpacity, false, false>;
- result["heatmap-opacity-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapOpacityTransition>;
-
- result["fill-extrusion-opacity"] = &setProperty<FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionOpacity, false, false>;
- result["fill-extrusion-opacity-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionOpacityTransition>;
- result["fill-extrusion-color"] = &setProperty<FillExtrusionLayer, PropertyValue<Color>, &FillExtrusionLayer::setFillExtrusionColor, true, false>;
- result["fill-extrusion-color-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionColorTransition>;
- result["fill-extrusion-translate"] = &setProperty<FillExtrusionLayer, PropertyValue<std::array<float, 2>>, &FillExtrusionLayer::setFillExtrusionTranslate, false, false>;
- result["fill-extrusion-translate-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateTransition>;
- result["fill-extrusion-translate-anchor"] = &setProperty<FillExtrusionLayer, PropertyValue<TranslateAnchorType>, &FillExtrusionLayer::setFillExtrusionTranslateAnchor, false, false>;
- result["fill-extrusion-translate-anchor-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionTranslateAnchorTransition>;
- result["fill-extrusion-pattern"] = &setProperty<FillExtrusionLayer, PropertyValue<std::string>, &FillExtrusionLayer::setFillExtrusionPattern, false, false>;
- result["fill-extrusion-pattern-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionPatternTransition>;
- result["fill-extrusion-height"] = &setProperty<FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionHeight, true, false>;
- result["fill-extrusion-height-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionHeightTransition>;
- result["fill-extrusion-base"] = &setProperty<FillExtrusionLayer, PropertyValue<float>, &FillExtrusionLayer::setFillExtrusionBase, true, false>;
- result["fill-extrusion-base-transition"] = &setTransition<FillExtrusionLayer, &FillExtrusionLayer::setFillExtrusionBaseTransition>;
-
- result["raster-opacity"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterOpacity, false, false>;
- result["raster-opacity-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterOpacityTransition>;
- result["raster-hue-rotate"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterHueRotate, false, false>;
- result["raster-hue-rotate-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterHueRotateTransition>;
- result["raster-brightness-min"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMin, false, false>;
- result["raster-brightness-min-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterBrightnessMinTransition>;
- result["raster-brightness-max"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterBrightnessMax, false, false>;
- result["raster-brightness-max-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterBrightnessMaxTransition>;
- result["raster-saturation"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterSaturation, false, false>;
- result["raster-saturation-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterSaturationTransition>;
- result["raster-contrast"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterContrast, false, false>;
- result["raster-contrast-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterContrastTransition>;
- result["raster-resampling"] = &setProperty<RasterLayer, PropertyValue<RasterResamplingType>, &RasterLayer::setRasterResampling, false, false>;
- result["raster-resampling-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterResamplingTransition>;
- result["raster-fade-duration"] = &setProperty<RasterLayer, PropertyValue<float>, &RasterLayer::setRasterFadeDuration, false, false>;
- result["raster-fade-duration-transition"] = &setTransition<RasterLayer, &RasterLayer::setRasterFadeDurationTransition>;
-
- result["hillshade-illumination-direction"] = &setProperty<HillshadeLayer, PropertyValue<float>, &HillshadeLayer::setHillshadeIlluminationDirection, false, false>;
- result["hillshade-illumination-direction-transition"] = &setTransition<HillshadeLayer, &HillshadeLayer::setHillshadeIlluminationDirectionTransition>;
- result["hillshade-illumination-anchor"] = &setProperty<HillshadeLayer, PropertyValue<HillshadeIlluminationAnchorType>, &HillshadeLayer::setHillshadeIlluminationAnchor, false, false>;
- result["hillshade-illumination-anchor-transition"] = &setTransition<HillshadeLayer, &HillshadeLayer::setHillshadeIlluminationAnchorTransition>;
- result["hillshade-exaggeration"] = &setProperty<HillshadeLayer, PropertyValue<float>, &HillshadeLayer::setHillshadeExaggeration, false, false>;
- result["hillshade-exaggeration-transition"] = &setTransition<HillshadeLayer, &HillshadeLayer::setHillshadeExaggerationTransition>;
- result["hillshade-shadow-color"] = &setProperty<HillshadeLayer, PropertyValue<Color>, &HillshadeLayer::setHillshadeShadowColor, false, false>;
- result["hillshade-shadow-color-transition"] = &setTransition<HillshadeLayer, &HillshadeLayer::setHillshadeShadowColorTransition>;
- result["hillshade-highlight-color"] = &setProperty<HillshadeLayer, PropertyValue<Color>, &HillshadeLayer::setHillshadeHighlightColor, false, false>;
- result["hillshade-highlight-color-transition"] = &setTransition<HillshadeLayer, &HillshadeLayer::setHillshadeHighlightColorTransition>;
- result["hillshade-accent-color"] = &setProperty<HillshadeLayer, PropertyValue<Color>, &HillshadeLayer::setHillshadeAccentColor, false, false>;
- result["hillshade-accent-color-transition"] = &setTransition<HillshadeLayer, &HillshadeLayer::setHillshadeAccentColorTransition>;
-
- result["background-color"] = &setProperty<BackgroundLayer, PropertyValue<Color>, &BackgroundLayer::setBackgroundColor, false, false>;
- result["background-color-transition"] = &setTransition<BackgroundLayer, &BackgroundLayer::setBackgroundColorTransition>;
- result["background-pattern"] = &setProperty<BackgroundLayer, PropertyValue<std::string>, &BackgroundLayer::setBackgroundPattern, false, false>;
- result["background-pattern-transition"] = &setTransition<BackgroundLayer, &BackgroundLayer::setBackgroundPatternTransition>;
- result["background-opacity"] = &setProperty<BackgroundLayer, PropertyValue<float>, &BackgroundLayer::setBackgroundOpacity, false, false>;
- result["background-opacity-transition"] = &setTransition<BackgroundLayer, &BackgroundLayer::setBackgroundOpacityTransition>;
-
- return result;
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/src/mbgl/style/conversion/make_property_setters.hpp.ejs b/src/mbgl/style/conversion/make_property_setters.hpp.ejs
deleted file mode 100644
index fbf2f93fd6..0000000000
--- a/src/mbgl/style/conversion/make_property_setters.hpp.ejs
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-
-// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`.
-
-#include <mbgl/style/conversion/property_setter.hpp>
-
-<% for (const layer of locals.layers) { -%>
-#include <mbgl/style/layers/<%- layer.type.replace('-', '_') %>_layer.hpp>
-<% } -%>
-
-#include <unordered_map>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-inline auto makeLayoutPropertySetters() {
- std::unordered_map<std::string, PropertySetter> result;
-
- result["visibility"] = &setVisibility;
-
-<% for (const layer of locals.layers) { -%>
-<% for (const property of layer.layoutProperties) { -%>
- result["<%- property.name %>"] = &setProperty<<%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>, <%- property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven' %>, <%- property.name === 'icon-image' || property.name === 'text-field' %>>;
-<% } -%>
-
-<% } -%>
- return result;
-}
-
-inline auto makePaintPropertySetters() {
- std::unordered_map<std::string, PropertySetter> result;
-
-<% for (const layer of locals.layers) { -%>
-<% for (const property of layer.paintProperties) { -%>
- result["<%- property.name %>"] = &setProperty<<%- camelize(layer.type) %>Layer, <%- propertyValueType(property) %>, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>, <%- property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven' %>, <%- property.name === 'icon-image' || property.name === 'text-field' %>>;
- result["<%- property.name %>-transition"] = &setTransition<<%- camelize(layer.type) %>Layer, &<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>Transition>;
-<% } -%>
-
-<% } -%>
- return result;
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/src/mbgl/style/conversion/position.cpp b/src/mbgl/style/conversion/position.cpp
index a19f57bff3..df6c868ee8 100644
--- a/src/mbgl/style/conversion/position.cpp
+++ b/src/mbgl/style/conversion/position.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <array>
diff --git a/src/mbgl/style/conversion/property_setter.hpp b/src/mbgl/style/conversion/property_setter.hpp
deleted file mode 100644
index 3c5c65f96a..0000000000
--- a/src/mbgl/style/conversion/property_setter.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#pragma once
-
-#include <mbgl/style/layer.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/style/conversion.hpp>
-#include <mbgl/style/conversion/color_ramp_property_value.hpp>
-#include <mbgl/style/conversion/constant.hpp>
-#include <mbgl/style/conversion/property_value.hpp>
-#include <mbgl/style/conversion/transition_options.hpp>
-
-#include <string>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-using PropertySetter = optional<Error> (*) (Layer&, const Convertible&);
-
-template <class L, class PropertyValue, void (L::*setter)(PropertyValue), bool allowDataExpressions, bool convertTokens>
-optional<Error> setProperty(Layer& layer, const Convertible& value) {
- auto* typedLayer = layer.as<L>();
- if (!typedLayer) {
- return Error { "layer doesn't support this property" };
- }
-
- Error error;
- optional<PropertyValue> typedValue = convert<PropertyValue>(value, error, allowDataExpressions, convertTokens);
- if (!typedValue) {
- return error;
- }
-
- (typedLayer->*setter)(*typedValue);
- return nullopt;
-}
-
-template <class L, void (L::*setter)(const TransitionOptions&)>
-optional<Error> setTransition(Layer& layer, const Convertible& value) {
- auto* typedLayer = layer.as<L>();
- if (!typedLayer) {
- return Error { "layer doesn't support this property" };
- }
-
- Error error;
- optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
- if (!transition) {
- return error;
- }
-
- (typedLayer->*setter)(*transition);
- return nullopt;
-}
-
-inline optional<Error> setVisibility(Layer& layer, const Convertible& value) {
- if (isUndefined(value)) {
- layer.setVisibility(VisibilityType::Visible);
- return nullopt;
- }
-
- Error error;
- optional<VisibilityType> visibility = convert<VisibilityType>(value, error);
- if (!visibility) {
- return error;
- }
-
- layer.setVisibility(*visibility);
- return nullopt;
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/src/mbgl/style/conversion/property_value.cpp b/src/mbgl/style/conversion/property_value.cpp
new file mode 100644
index 0000000000..8a93c24767
--- /dev/null
+++ b/src/mbgl/style/conversion/property_value.cpp
@@ -0,0 +1,83 @@
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/position.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <class T>
+optional<PropertyValue<T>> Converter<PropertyValue<T>>::operator()(const Convertible& value, Error& error, bool allowDataExpressions, bool convertTokens) const {
+ using namespace mbgl::style::expression;
+
+ if (isUndefined(value)) {
+ return PropertyValue<T>();
+ }
+
+ optional<PropertyExpression<T>> expression;
+
+ if (isExpression(value)) {
+ ParsingContext ctx(valueTypeToExpressionType<T>());
+ ParseResult parsed = ctx.parseLayerPropertyExpression(value);
+ if (!parsed) {
+ error.message = ctx.getCombinedErrors();
+ return nullopt;
+ }
+ expression = PropertyExpression<T>(std::move(*parsed));
+ } else if (isObject(value)) {
+ expression = convertFunctionToExpression<T>(value, error, convertTokens);
+ } else {
+ optional<T> constant = convert<T>(value, error);
+ if (!constant) {
+ return nullopt;
+ }
+ return convertTokens ? maybeConvertTokens(*constant) : PropertyValue<T>(*constant);
+ }
+
+ if (!expression) {
+ return nullopt;
+ } else if (!allowDataExpressions && !(*expression).isFeatureConstant()) {
+ error.message = "data expressions not supported";
+ return nullopt;
+ } else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant()) {
+ return { std::move(*expression) };
+ } else if ((*expression).getExpression().getKind() == Kind::Literal) {
+ optional<T> constant = fromExpressionValue<T>(
+ static_cast<const Literal&>((*expression).getExpression()).getValue());
+ if (!constant) {
+ return nullopt;
+ }
+ return PropertyValue<T>(*constant);
+ } else {
+ assert(false);
+ error.message = "expected a literal expression";
+ return nullopt;
+ }
+}
+
+template optional<PropertyValue<bool>> Converter<PropertyValue<bool>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<float>> Converter<PropertyValue<float>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<std::array<float, 2>>> Converter<PropertyValue<std::array<float, 2>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<std::array<float, 4>>> Converter<PropertyValue<std::array<float, 4>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<std::vector<float>>> Converter<PropertyValue<std::vector<float>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<Color>> Converter<PropertyValue<Color>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<std::string>> Converter<PropertyValue<std::string>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<std::vector<std::string>>> Converter<PropertyValue<std::vector<std::string>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<AlignmentType>> Converter<PropertyValue<AlignmentType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<CirclePitchScaleType>> Converter<PropertyValue<CirclePitchScaleType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<HillshadeIlluminationAnchorType>> Converter<PropertyValue<HillshadeIlluminationAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<IconTextFitType>> Converter<PropertyValue<IconTextFitType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<LightAnchorType>> Converter<PropertyValue<LightAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<LineCapType>> Converter<PropertyValue<LineCapType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<LineJoinType>> Converter<PropertyValue<LineJoinType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<Position>> Converter<PropertyValue<Position>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<RasterResamplingType>> Converter<PropertyValue<RasterResamplingType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<SymbolAnchorType>> Converter<PropertyValue<SymbolAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<SymbolPlacementType>> Converter<PropertyValue<SymbolPlacementType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<TextJustifyType>> Converter<PropertyValue<TextJustifyType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<TextTransformType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+template optional<PropertyValue<TranslateAnchorType>> Converter<PropertyValue<TranslateAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/source.cpp b/src/mbgl/style/conversion/source.cpp
index ce0cb24ce0..5ecbd3b474 100644
--- a/src/mbgl/style/conversion/source.cpp
+++ b/src/mbgl/style/conversion/source.cpp
@@ -3,6 +3,7 @@
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/geojson_options.hpp>
#include <mbgl/style/conversion/tileset.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/sources/raster_source.hpp>
#include <mbgl/style/sources/raster_dem_source.hpp>
diff --git a/src/mbgl/style/conversion/tileset.cpp b/src/mbgl/style/conversion/tileset.cpp
index b566af0a18..40575838ea 100644
--- a/src/mbgl/style/conversion/tileset.cpp
+++ b/src/mbgl/style/conversion/tileset.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/tileset.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/math/clamp.hpp>
diff --git a/src/mbgl/style/conversion/transition_options.cpp b/src/mbgl/style/conversion/transition_options.cpp
index 924032a0c0..6e39dca24f 100644
--- a/src/mbgl/style/conversion/transition_options.cpp
+++ b/src/mbgl/style/conversion/transition_options.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/expression/array_assertion.cpp b/src/mbgl/style/expression/array_assertion.cpp
index 4049301b0b..9df586bdc3 100644
--- a/src/mbgl/style/expression/array_assertion.cpp
+++ b/src/mbgl/style/expression/array_assertion.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/expression/array_assertion.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/assertion.cpp b/src/mbgl/style/expression/assertion.cpp
index 2434d7a2f8..7e93003ac3 100644
--- a/src/mbgl/style/expression/assertion.cpp
+++ b/src/mbgl/style/expression/assertion.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/expression/assertion.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/expression/at.cpp b/src/mbgl/style/expression/at.cpp
index 725e5ddb51..648f247830 100644
--- a/src/mbgl/style/expression/at.cpp
+++ b/src/mbgl/style/expression/at.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/at.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
diff --git a/src/mbgl/style/expression/boolean_operator.cpp b/src/mbgl/style/expression/boolean_operator.cpp
index 68e96129aa..fa472270ce 100644
--- a/src/mbgl/style/expression/boolean_operator.cpp
+++ b/src/mbgl/style/expression/boolean_operator.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/boolean_operator.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/expression/case.cpp b/src/mbgl/style/expression/case.cpp
index e885c0ce6b..0c2ff0d7cd 100644
--- a/src/mbgl/style/expression/case.cpp
+++ b/src/mbgl/style/expression/case.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/case.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/coalesce.cpp b/src/mbgl/style/expression/coalesce.cpp
index 0090f16009..cdbf452f7f 100644
--- a/src/mbgl/style/expression/coalesce.cpp
+++ b/src/mbgl/style/expression/coalesce.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/expression/coalesce.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/expression/coercion.cpp b/src/mbgl/style/expression/coercion.cpp
index f5a4d70f66..486658ddda 100644
--- a/src/mbgl/style/expression/coercion.cpp
+++ b/src/mbgl/style/expression/coercion.cpp
@@ -1,6 +1,7 @@
#include <mbgl/style/expression/coercion.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/util.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/collator_expression.cpp b/src/mbgl/style/expression/collator_expression.cpp
index b27eedbc76..07346633a2 100644
--- a/src/mbgl/style/expression/collator_expression.cpp
+++ b/src/mbgl/style/expression/collator_expression.cpp
@@ -1,6 +1,7 @@
#include <mbgl/style/expression/collator.hpp>
#include <mbgl/style/expression/collator_expression.hpp>
#include <mbgl/style/expression/literal.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/comparison.cpp b/src/mbgl/style/expression/comparison.cpp
index 6179c3ce88..cdcdb5d59c 100644
--- a/src/mbgl/style/expression/comparison.cpp
+++ b/src/mbgl/style/expression/comparison.cpp
@@ -1,6 +1,7 @@
#include <mbgl/style/expression/collator.hpp>
#include <mbgl/style/expression/comparison.hpp>
#include <mbgl/style/expression/dsl.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
index 4c476a3749..f8c2376cb3 100644
--- a/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -3,6 +3,7 @@
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/util.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/math/log2.hpp>
#include <mbgl/util/i18n.hpp>
diff --git a/src/mbgl/style/expression/interpolate.cpp b/src/mbgl/style/expression/interpolate.cpp
index 54fbc6e1d7..8725e9e86d 100644
--- a/src/mbgl/style/expression/interpolate.cpp
+++ b/src/mbgl/style/expression/interpolate.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/is_constant.cpp b/src/mbgl/style/expression/is_constant.cpp
index 69f27f6fef..3b20f49a86 100644
--- a/src/mbgl/style/expression/is_constant.cpp
+++ b/src/mbgl/style/expression/is_constant.cpp
@@ -17,7 +17,7 @@ bool isFeatureConstant(const Expression& expression) {
return false;
} else if (name == "has" && parameterCount && *parameterCount == 1) {
return false;
- } else if (std::equal(std::begin(filter), std::end(filter) - 1, name.begin())) {
+ } else if (0 == name.rfind(filter, 0)) {
// Legacy filters begin with "filter-" and are never constant.
return false;
} else if (
@@ -28,7 +28,7 @@ bool isFeatureConstant(const Expression& expression) {
return false;
}
}
-
+
if (expression.getKind() == Kind::CollatorExpression) {
// Although the results of a Collator expression with fixed arguments
// generally shouldn't change between executions, we can't serialize them
diff --git a/src/mbgl/style/expression/is_expression.cpp b/src/mbgl/style/expression/is_expression.cpp
index 77212f6a1e..acf074c25b 100644
--- a/src/mbgl/style/expression/is_expression.cpp
+++ b/src/mbgl/style/expression/is_expression.cpp
@@ -1,8 +1,7 @@
#include <mbgl/style/expression/is_expression.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
-
-#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <unordered_set>
diff --git a/src/mbgl/style/expression/length.cpp b/src/mbgl/style/expression/length.cpp
index ad7a15675a..f1b58d7952 100644
--- a/src/mbgl/style/expression/length.cpp
+++ b/src/mbgl/style/expression/length.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/length.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/let.cpp b/src/mbgl/style/expression/let.cpp
index 242a995b0b..592ceed58a 100644
--- a/src/mbgl/style/expression/let.cpp
+++ b/src/mbgl/style/expression/let.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/expression/let.hpp>
#include <mbgl/style/conversion/get_json_type.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/literal.cpp b/src/mbgl/style/expression/literal.cpp
index 345a52de9b..c69341d298 100644
--- a/src/mbgl/style/expression/literal.cpp
+++ b/src/mbgl/style/expression/literal.cpp
@@ -1,4 +1,5 @@
#include <mbgl/style/expression/literal.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/match.cpp b/src/mbgl/style/expression/match.cpp
index 4b4984811f..0f05001a97 100644
--- a/src/mbgl/style/expression/match.cpp
+++ b/src/mbgl/style/expression/match.cpp
@@ -1,6 +1,7 @@
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index b3f6b1acee..ef17caed33 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -24,6 +24,7 @@
#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/style/conversion/get_json_type.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
diff --git a/src/mbgl/style/expression/step.cpp b/src/mbgl/style/expression/step.cpp
index a1ca0a702e..39b04c04a0 100644
--- a/src/mbgl/style/expression/step.cpp
+++ b/src/mbgl/style/expression/step.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/get_covering_stops.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
#include <cmath>
diff --git a/src/mbgl/style/layer.cpp b/src/mbgl/style/layer.cpp
index 142fe313cf..e08b71e6b3 100644
--- a/src/mbgl/style/layer.cpp
+++ b/src/mbgl/style/layer.cpp
@@ -1,6 +1,8 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
@@ -38,5 +40,23 @@ void Layer::setObserver(LayerObserver* observer_) {
observer = observer_ ? observer_ : &nullObserver;
}
+optional<conversion::Error> Layer::setVisibility(const conversion::Convertible& value) {
+ using namespace conversion;
+
+ if (isUndefined(value)) {
+ setVisibility(VisibilityType::Visible);
+ return nullopt;
+ }
+
+ Error error;
+ optional<VisibilityType> visibility = convert<VisibilityType>(value, error);
+ if (!visibility) {
+ return error;
+ }
+
+ setVisibility(*visibility);
+ return nullopt;
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
index 66ab46c078..f2e85ce7e7 100644
--- a/src/mbgl/style/layers/background_layer.cpp
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -149,5 +156,143 @@ TransitionOptions BackgroundLayer::getBackgroundOpacityTransition() const {
return impl().paint.template get<BackgroundOpacity>().options;
}
+using namespace conversion;
+
+optional<Error> BackgroundLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ BackgroundColor,
+ BackgroundPattern,
+ BackgroundOpacity,
+ BackgroundColorTransition,
+ BackgroundPatternTransition,
+ BackgroundOpacityTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("background-color"):
+ if (name == "background-color") {
+ property = Property::BackgroundColor;
+ }
+ break;
+ case util::hashFNV1a("background-color-transition"):
+ if (name == "background-color-transition") {
+ property = Property::BackgroundColorTransition;
+ }
+ break;
+ case util::hashFNV1a("background-pattern"):
+ if (name == "background-pattern") {
+ property = Property::BackgroundPattern;
+ }
+ break;
+ case util::hashFNV1a("background-pattern-transition"):
+ if (name == "background-pattern-transition") {
+ property = Property::BackgroundPatternTransition;
+ }
+ break;
+ case util::hashFNV1a("background-opacity"):
+ if (name == "background-opacity") {
+ property = Property::BackgroundOpacity;
+ }
+ break;
+ case util::hashFNV1a("background-opacity-transition"):
+ if (name == "background-opacity-transition") {
+ property = Property::BackgroundOpacityTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::BackgroundColor) {
+ Error error;
+ optional<PropertyValue<Color>> typedValue = convert<PropertyValue<Color>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setBackgroundColor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::BackgroundPattern) {
+ Error error;
+ optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setBackgroundPattern(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::BackgroundOpacity) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setBackgroundOpacity(*typedValue);
+ return nullopt;
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::BackgroundColorTransition) {
+ setBackgroundColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::BackgroundPatternTransition) {
+ setBackgroundPatternTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::BackgroundOpacityTransition) {
+ setBackgroundOpacityTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> BackgroundLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index d435ce89e1..c301a83c9e 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -393,5 +400,344 @@ TransitionOptions CircleLayer::getCircleStrokeOpacityTransition() const {
return impl().paint.template get<CircleStrokeOpacity>().options;
}
+using namespace conversion;
+
+optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ CircleRadius,
+ CircleColor,
+ CircleBlur,
+ CircleOpacity,
+ CircleTranslate,
+ CircleTranslateAnchor,
+ CirclePitchScale,
+ CirclePitchAlignment,
+ CircleStrokeWidth,
+ CircleStrokeColor,
+ CircleStrokeOpacity,
+ CircleRadiusTransition,
+ CircleColorTransition,
+ CircleBlurTransition,
+ CircleOpacityTransition,
+ CircleTranslateTransition,
+ CircleTranslateAnchorTransition,
+ CirclePitchScaleTransition,
+ CirclePitchAlignmentTransition,
+ CircleStrokeWidthTransition,
+ CircleStrokeColorTransition,
+ CircleStrokeOpacityTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("circle-radius"):
+ if (name == "circle-radius") {
+ property = Property::CircleRadius;
+ }
+ break;
+ case util::hashFNV1a("circle-radius-transition"):
+ if (name == "circle-radius-transition") {
+ property = Property::CircleRadiusTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-color"):
+ if (name == "circle-color") {
+ property = Property::CircleColor;
+ }
+ break;
+ case util::hashFNV1a("circle-color-transition"):
+ if (name == "circle-color-transition") {
+ property = Property::CircleColorTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-blur"):
+ if (name == "circle-blur") {
+ property = Property::CircleBlur;
+ }
+ break;
+ case util::hashFNV1a("circle-blur-transition"):
+ if (name == "circle-blur-transition") {
+ property = Property::CircleBlurTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-opacity"):
+ if (name == "circle-opacity") {
+ property = Property::CircleOpacity;
+ }
+ break;
+ case util::hashFNV1a("circle-opacity-transition"):
+ if (name == "circle-opacity-transition") {
+ property = Property::CircleOpacityTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-translate"):
+ if (name == "circle-translate") {
+ property = Property::CircleTranslate;
+ }
+ break;
+ case util::hashFNV1a("circle-translate-transition"):
+ if (name == "circle-translate-transition") {
+ property = Property::CircleTranslateTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-translate-anchor"):
+ if (name == "circle-translate-anchor") {
+ property = Property::CircleTranslateAnchor;
+ }
+ break;
+ case util::hashFNV1a("circle-translate-anchor-transition"):
+ if (name == "circle-translate-anchor-transition") {
+ property = Property::CircleTranslateAnchorTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-pitch-scale"):
+ if (name == "circle-pitch-scale") {
+ property = Property::CirclePitchScale;
+ }
+ break;
+ case util::hashFNV1a("circle-pitch-scale-transition"):
+ if (name == "circle-pitch-scale-transition") {
+ property = Property::CirclePitchScaleTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-pitch-alignment"):
+ if (name == "circle-pitch-alignment") {
+ property = Property::CirclePitchAlignment;
+ }
+ break;
+ case util::hashFNV1a("circle-pitch-alignment-transition"):
+ if (name == "circle-pitch-alignment-transition") {
+ property = Property::CirclePitchAlignmentTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-stroke-width"):
+ if (name == "circle-stroke-width") {
+ property = Property::CircleStrokeWidth;
+ }
+ break;
+ case util::hashFNV1a("circle-stroke-width-transition"):
+ if (name == "circle-stroke-width-transition") {
+ property = Property::CircleStrokeWidthTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-stroke-color"):
+ if (name == "circle-stroke-color") {
+ property = Property::CircleStrokeColor;
+ }
+ break;
+ case util::hashFNV1a("circle-stroke-color-transition"):
+ if (name == "circle-stroke-color-transition") {
+ property = Property::CircleStrokeColorTransition;
+ }
+ break;
+ case util::hashFNV1a("circle-stroke-opacity"):
+ if (name == "circle-stroke-opacity") {
+ property = Property::CircleStrokeOpacity;
+ }
+ break;
+ case util::hashFNV1a("circle-stroke-opacity-transition"):
+ if (name == "circle-stroke-opacity-transition") {
+ property = Property::CircleStrokeOpacityTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::CircleRadius || property == Property::CircleBlur || property == Property::CircleOpacity || property == Property::CircleStrokeWidth || property == Property::CircleStrokeOpacity) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::CircleRadius) {
+ setCircleRadius(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::CircleBlur) {
+ setCircleBlur(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::CircleOpacity) {
+ setCircleOpacity(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::CircleStrokeWidth) {
+ setCircleStrokeWidth(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::CircleStrokeOpacity) {
+ setCircleStrokeOpacity(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::CircleColor || property == Property::CircleStrokeColor) {
+ Error error;
+ optional<PropertyValue<Color>> typedValue = convert<PropertyValue<Color>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::CircleColor) {
+ setCircleColor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::CircleStrokeColor) {
+ setCircleStrokeColor(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::CircleTranslate) {
+ Error error;
+ optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setCircleTranslate(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::CircleTranslateAnchor) {
+ Error error;
+ optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setCircleTranslateAnchor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::CirclePitchScale) {
+ Error error;
+ optional<PropertyValue<CirclePitchScaleType>> typedValue = convert<PropertyValue<CirclePitchScaleType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setCirclePitchScale(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::CirclePitchAlignment) {
+ Error error;
+ optional<PropertyValue<AlignmentType>> typedValue = convert<PropertyValue<AlignmentType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setCirclePitchAlignment(*typedValue);
+ return nullopt;
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::CircleRadiusTransition) {
+ setCircleRadiusTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleColorTransition) {
+ setCircleColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleBlurTransition) {
+ setCircleBlurTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleOpacityTransition) {
+ setCircleOpacityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleTranslateTransition) {
+ setCircleTranslateTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleTranslateAnchorTransition) {
+ setCircleTranslateAnchorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CirclePitchScaleTransition) {
+ setCirclePitchScaleTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CirclePitchAlignmentTransition) {
+ setCirclePitchAlignmentTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleStrokeWidthTransition) {
+ setCircleStrokeWidthTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleStrokeColorTransition) {
+ setCircleStrokeColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::CircleStrokeOpacityTransition) {
+ setCircleStrokeOpacityTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> CircleLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp
index 69f574cd6b..358598e09c 100644
--- a/src/mbgl/style/layers/circle_layer_impl.cpp
+++ b/src/mbgl/style/layers/circle_layer_impl.cpp
@@ -4,7 +4,7 @@ namespace mbgl {
namespace style {
bool CircleLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const {
- assert(dynamic_cast<const CircleLayer::Impl*>(&other));
+ assert(other.type == LayerType::Circle);
const auto& impl = static_cast<const style::CircleLayer::Impl&>(other);
return filter != impl.filter ||
visibility != impl.visibility ||
diff --git a/src/mbgl/style/layers/custom_layer.cpp b/src/mbgl/style/layers/custom_layer.cpp
index 0e51a70e50..d1ac1a705c 100644
--- a/src/mbgl/style/layers/custom_layer.cpp
+++ b/src/mbgl/style/layers/custom_layer.cpp
@@ -50,6 +50,16 @@ void CustomLayer::setMaxZoom(float maxZoom) {
baseImpl = std::move(impl_);
}
+using namespace conversion;
+
+optional<Error> CustomLayer::setPaintProperty(const std::string&, const Convertible&) {
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> CustomLayer::setLayoutProperty(const std::string&, const Convertible&) {
+ return Error { "layer doesn't support this property" };
+}
+
template <>
bool Layer::is<CustomLayer>() const {
return getType() == LayerType::Custom;
diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp
index 829a24f354..74cdb9abe6 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer.cpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -285,5 +292,254 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionBaseTransition() const {
return impl().paint.template get<FillExtrusionBase>().options;
}
+using namespace conversion;
+
+optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ FillExtrusionOpacity,
+ FillExtrusionColor,
+ FillExtrusionTranslate,
+ FillExtrusionTranslateAnchor,
+ FillExtrusionPattern,
+ FillExtrusionHeight,
+ FillExtrusionBase,
+ FillExtrusionOpacityTransition,
+ FillExtrusionColorTransition,
+ FillExtrusionTranslateTransition,
+ FillExtrusionTranslateAnchorTransition,
+ FillExtrusionPatternTransition,
+ FillExtrusionHeightTransition,
+ FillExtrusionBaseTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("fill-extrusion-opacity"):
+ if (name == "fill-extrusion-opacity") {
+ property = Property::FillExtrusionOpacity;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-opacity-transition"):
+ if (name == "fill-extrusion-opacity-transition") {
+ property = Property::FillExtrusionOpacityTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-color"):
+ if (name == "fill-extrusion-color") {
+ property = Property::FillExtrusionColor;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-color-transition"):
+ if (name == "fill-extrusion-color-transition") {
+ property = Property::FillExtrusionColorTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-translate"):
+ if (name == "fill-extrusion-translate") {
+ property = Property::FillExtrusionTranslate;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-translate-transition"):
+ if (name == "fill-extrusion-translate-transition") {
+ property = Property::FillExtrusionTranslateTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-translate-anchor"):
+ if (name == "fill-extrusion-translate-anchor") {
+ property = Property::FillExtrusionTranslateAnchor;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-translate-anchor-transition"):
+ if (name == "fill-extrusion-translate-anchor-transition") {
+ property = Property::FillExtrusionTranslateAnchorTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-pattern"):
+ if (name == "fill-extrusion-pattern") {
+ property = Property::FillExtrusionPattern;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-pattern-transition"):
+ if (name == "fill-extrusion-pattern-transition") {
+ property = Property::FillExtrusionPatternTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-height"):
+ if (name == "fill-extrusion-height") {
+ property = Property::FillExtrusionHeight;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-height-transition"):
+ if (name == "fill-extrusion-height-transition") {
+ property = Property::FillExtrusionHeightTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-base"):
+ if (name == "fill-extrusion-base") {
+ property = Property::FillExtrusionBase;
+ }
+ break;
+ case util::hashFNV1a("fill-extrusion-base-transition"):
+ if (name == "fill-extrusion-base-transition") {
+ property = Property::FillExtrusionBaseTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::FillExtrusionOpacity) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillExtrusionOpacity(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillExtrusionColor) {
+ Error error;
+ optional<PropertyValue<Color>> typedValue = convert<PropertyValue<Color>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillExtrusionColor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillExtrusionTranslate) {
+ Error error;
+ optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillExtrusionTranslate(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillExtrusionTranslateAnchor) {
+ Error error;
+ optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillExtrusionTranslateAnchor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillExtrusionPattern) {
+ Error error;
+ optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillExtrusionPattern(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillExtrusionHeight || property == Property::FillExtrusionBase) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::FillExtrusionHeight) {
+ setFillExtrusionHeight(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::FillExtrusionBase) {
+ setFillExtrusionBase(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::FillExtrusionOpacityTransition) {
+ setFillExtrusionOpacityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillExtrusionColorTransition) {
+ setFillExtrusionColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillExtrusionTranslateTransition) {
+ setFillExtrusionTranslateTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillExtrusionTranslateAnchorTransition) {
+ setFillExtrusionTranslateAnchorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillExtrusionPatternTransition) {
+ setFillExtrusionPatternTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillExtrusionHeightTransition) {
+ setFillExtrusionHeightTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillExtrusionBaseTransition) {
+ setFillExtrusionBaseTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> FillExtrusionLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp b/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp
index d37c2ad29b..357ea3e973 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer_impl.cpp
@@ -4,7 +4,7 @@ namespace mbgl {
namespace style {
bool FillExtrusionLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const {
- assert(dynamic_cast<const FillExtrusionLayer::Impl*>(&other));
+ assert(other.type == LayerType::FillExtrusion);
const auto& impl = static_cast<const style::FillExtrusionLayer::Impl&>(other);
return filter != impl.filter ||
visibility != impl.visibility ||
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
index 8eebd54e3c..bdfc000736 100644
--- a/src/mbgl/style/layers/fill_layer.cpp
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -285,5 +292,254 @@ TransitionOptions FillLayer::getFillPatternTransition() const {
return impl().paint.template get<FillPattern>().options;
}
+using namespace conversion;
+
+optional<Error> FillLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ FillAntialias,
+ FillOpacity,
+ FillColor,
+ FillOutlineColor,
+ FillTranslate,
+ FillTranslateAnchor,
+ FillPattern,
+ FillAntialiasTransition,
+ FillOpacityTransition,
+ FillColorTransition,
+ FillOutlineColorTransition,
+ FillTranslateTransition,
+ FillTranslateAnchorTransition,
+ FillPatternTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("fill-antialias"):
+ if (name == "fill-antialias") {
+ property = Property::FillAntialias;
+ }
+ break;
+ case util::hashFNV1a("fill-antialias-transition"):
+ if (name == "fill-antialias-transition") {
+ property = Property::FillAntialiasTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-opacity"):
+ if (name == "fill-opacity") {
+ property = Property::FillOpacity;
+ }
+ break;
+ case util::hashFNV1a("fill-opacity-transition"):
+ if (name == "fill-opacity-transition") {
+ property = Property::FillOpacityTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-color"):
+ if (name == "fill-color") {
+ property = Property::FillColor;
+ }
+ break;
+ case util::hashFNV1a("fill-color-transition"):
+ if (name == "fill-color-transition") {
+ property = Property::FillColorTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-outline-color"):
+ if (name == "fill-outline-color") {
+ property = Property::FillOutlineColor;
+ }
+ break;
+ case util::hashFNV1a("fill-outline-color-transition"):
+ if (name == "fill-outline-color-transition") {
+ property = Property::FillOutlineColorTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-translate"):
+ if (name == "fill-translate") {
+ property = Property::FillTranslate;
+ }
+ break;
+ case util::hashFNV1a("fill-translate-transition"):
+ if (name == "fill-translate-transition") {
+ property = Property::FillTranslateTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-translate-anchor"):
+ if (name == "fill-translate-anchor") {
+ property = Property::FillTranslateAnchor;
+ }
+ break;
+ case util::hashFNV1a("fill-translate-anchor-transition"):
+ if (name == "fill-translate-anchor-transition") {
+ property = Property::FillTranslateAnchorTransition;
+ }
+ break;
+ case util::hashFNV1a("fill-pattern"):
+ if (name == "fill-pattern") {
+ property = Property::FillPattern;
+ }
+ break;
+ case util::hashFNV1a("fill-pattern-transition"):
+ if (name == "fill-pattern-transition") {
+ property = Property::FillPatternTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::FillAntialias) {
+ Error error;
+ optional<PropertyValue<bool>> typedValue = convert<PropertyValue<bool>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillAntialias(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillOpacity) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillOpacity(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillColor || property == Property::FillOutlineColor) {
+ Error error;
+ optional<PropertyValue<Color>> typedValue = convert<PropertyValue<Color>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::FillColor) {
+ setFillColor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::FillOutlineColor) {
+ setFillOutlineColor(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::FillTranslate) {
+ Error error;
+ optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillTranslate(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillTranslateAnchor) {
+ Error error;
+ optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillTranslateAnchor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::FillPattern) {
+ Error error;
+ optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setFillPattern(*typedValue);
+ return nullopt;
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::FillAntialiasTransition) {
+ setFillAntialiasTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillOpacityTransition) {
+ setFillOpacityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillColorTransition) {
+ setFillColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillOutlineColorTransition) {
+ setFillOutlineColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillTranslateTransition) {
+ setFillTranslateTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillTranslateAnchorTransition) {
+ setFillTranslateAnchorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::FillPatternTransition) {
+ setFillPatternTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> FillLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp
index 0dc7ed14d5..a8ba1b693b 100644
--- a/src/mbgl/style/layers/fill_layer_impl.cpp
+++ b/src/mbgl/style/layers/fill_layer_impl.cpp
@@ -4,7 +4,7 @@ namespace mbgl {
namespace style {
bool FillLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const {
- assert(dynamic_cast<const FillLayer::Impl*>(&other));
+ assert(other.type == LayerType::Fill);
const auto& impl = static_cast<const style::FillLayer::Impl&>(other);
return filter != impl.filter ||
visibility != impl.visibility ||
diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp
index 21016ee509..a90aab7009 100644
--- a/src/mbgl/style/layers/heatmap_layer.cpp
+++ b/src/mbgl/style/layers/heatmap_layer.cpp
@@ -3,10 +3,13 @@
#include <mbgl/style/layers/heatmap_layer.hpp>
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
-// for constructing default heatmap-color ramp expression from style JSON
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -237,5 +240,191 @@ TransitionOptions HeatmapLayer::getHeatmapOpacityTransition() const {
return impl().paint.template get<HeatmapOpacity>().options;
}
+using namespace conversion;
+
+optional<Error> HeatmapLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ HeatmapRadius,
+ HeatmapWeight,
+ HeatmapIntensity,
+ HeatmapColor,
+ HeatmapOpacity,
+ HeatmapRadiusTransition,
+ HeatmapWeightTransition,
+ HeatmapIntensityTransition,
+ HeatmapColorTransition,
+ HeatmapOpacityTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("heatmap-radius"):
+ if (name == "heatmap-radius") {
+ property = Property::HeatmapRadius;
+ }
+ break;
+ case util::hashFNV1a("heatmap-radius-transition"):
+ if (name == "heatmap-radius-transition") {
+ property = Property::HeatmapRadiusTransition;
+ }
+ break;
+ case util::hashFNV1a("heatmap-weight"):
+ if (name == "heatmap-weight") {
+ property = Property::HeatmapWeight;
+ }
+ break;
+ case util::hashFNV1a("heatmap-weight-transition"):
+ if (name == "heatmap-weight-transition") {
+ property = Property::HeatmapWeightTransition;
+ }
+ break;
+ case util::hashFNV1a("heatmap-intensity"):
+ if (name == "heatmap-intensity") {
+ property = Property::HeatmapIntensity;
+ }
+ break;
+ case util::hashFNV1a("heatmap-intensity-transition"):
+ if (name == "heatmap-intensity-transition") {
+ property = Property::HeatmapIntensityTransition;
+ }
+ break;
+ case util::hashFNV1a("heatmap-color"):
+ if (name == "heatmap-color") {
+ property = Property::HeatmapColor;
+ }
+ break;
+ case util::hashFNV1a("heatmap-color-transition"):
+ if (name == "heatmap-color-transition") {
+ property = Property::HeatmapColorTransition;
+ }
+ break;
+ case util::hashFNV1a("heatmap-opacity"):
+ if (name == "heatmap-opacity") {
+ property = Property::HeatmapOpacity;
+ }
+ break;
+ case util::hashFNV1a("heatmap-opacity-transition"):
+ if (name == "heatmap-opacity-transition") {
+ property = Property::HeatmapOpacityTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::HeatmapRadius || property == Property::HeatmapWeight) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::HeatmapRadius) {
+ setHeatmapRadius(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::HeatmapWeight) {
+ setHeatmapWeight(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::HeatmapIntensity || property == Property::HeatmapOpacity) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::HeatmapIntensity) {
+ setHeatmapIntensity(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::HeatmapOpacity) {
+ setHeatmapOpacity(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::HeatmapColor) {
+ Error error;
+ optional<ColorRampPropertyValue> typedValue = convert<ColorRampPropertyValue>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setHeatmapColor(*typedValue);
+ return nullopt;
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::HeatmapRadiusTransition) {
+ setHeatmapRadiusTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HeatmapWeightTransition) {
+ setHeatmapWeightTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HeatmapIntensityTransition) {
+ setHeatmapIntensityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HeatmapColorTransition) {
+ setHeatmapColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HeatmapOpacityTransition) {
+ setHeatmapOpacityTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> HeatmapLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/heatmap_layer_impl.cpp b/src/mbgl/style/layers/heatmap_layer_impl.cpp
index af20888d9d..8fd0cf72b2 100644
--- a/src/mbgl/style/layers/heatmap_layer_impl.cpp
+++ b/src/mbgl/style/layers/heatmap_layer_impl.cpp
@@ -4,7 +4,7 @@ namespace mbgl {
namespace style {
bool HeatmapLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const {
- assert(dynamic_cast<const HeatmapLayer::Impl*>(&other));
+ assert(other.type == LayerType::Heatmap);
const auto& impl = static_cast<const style::HeatmapLayer::Impl&>(other);
return filter != impl.filter ||
visibility != impl.visibility ||
diff --git a/src/mbgl/style/layers/heatmap_layer_properties.hpp b/src/mbgl/style/layers/heatmap_layer_properties.hpp
index fe7257a78a..4d49a52c72 100644
--- a/src/mbgl/style/layers/heatmap_layer_properties.hpp
+++ b/src/mbgl/style/layers/heatmap_layer_properties.hpp
@@ -24,7 +24,8 @@ struct HeatmapIntensity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
-using HeatmapColor = ColorRampProperty;
+struct HeatmapColor : ColorRampProperty {
+};
struct HeatmapOpacity : PaintProperty<float> {
static float defaultValue() { return 1; }
diff --git a/src/mbgl/style/layers/hillshade_layer.cpp b/src/mbgl/style/layers/hillshade_layer.cpp
index e352ae090c..aed49f6441 100644
--- a/src/mbgl/style/layers/hillshade_layer.cpp
+++ b/src/mbgl/style/layers/hillshade_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/hillshade_layer.hpp>
#include <mbgl/style/layers/hillshade_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -236,5 +243,213 @@ TransitionOptions HillshadeLayer::getHillshadeAccentColorTransition() const {
return impl().paint.template get<HillshadeAccentColor>().options;
}
+using namespace conversion;
+
+optional<Error> HillshadeLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ HillshadeIlluminationDirection,
+ HillshadeIlluminationAnchor,
+ HillshadeExaggeration,
+ HillshadeShadowColor,
+ HillshadeHighlightColor,
+ HillshadeAccentColor,
+ HillshadeIlluminationDirectionTransition,
+ HillshadeIlluminationAnchorTransition,
+ HillshadeExaggerationTransition,
+ HillshadeShadowColorTransition,
+ HillshadeHighlightColorTransition,
+ HillshadeAccentColorTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("hillshade-illumination-direction"):
+ if (name == "hillshade-illumination-direction") {
+ property = Property::HillshadeIlluminationDirection;
+ }
+ break;
+ case util::hashFNV1a("hillshade-illumination-direction-transition"):
+ if (name == "hillshade-illumination-direction-transition") {
+ property = Property::HillshadeIlluminationDirectionTransition;
+ }
+ break;
+ case util::hashFNV1a("hillshade-illumination-anchor"):
+ if (name == "hillshade-illumination-anchor") {
+ property = Property::HillshadeIlluminationAnchor;
+ }
+ break;
+ case util::hashFNV1a("hillshade-illumination-anchor-transition"):
+ if (name == "hillshade-illumination-anchor-transition") {
+ property = Property::HillshadeIlluminationAnchorTransition;
+ }
+ break;
+ case util::hashFNV1a("hillshade-exaggeration"):
+ if (name == "hillshade-exaggeration") {
+ property = Property::HillshadeExaggeration;
+ }
+ break;
+ case util::hashFNV1a("hillshade-exaggeration-transition"):
+ if (name == "hillshade-exaggeration-transition") {
+ property = Property::HillshadeExaggerationTransition;
+ }
+ break;
+ case util::hashFNV1a("hillshade-shadow-color"):
+ if (name == "hillshade-shadow-color") {
+ property = Property::HillshadeShadowColor;
+ }
+ break;
+ case util::hashFNV1a("hillshade-shadow-color-transition"):
+ if (name == "hillshade-shadow-color-transition") {
+ property = Property::HillshadeShadowColorTransition;
+ }
+ break;
+ case util::hashFNV1a("hillshade-highlight-color"):
+ if (name == "hillshade-highlight-color") {
+ property = Property::HillshadeHighlightColor;
+ }
+ break;
+ case util::hashFNV1a("hillshade-highlight-color-transition"):
+ if (name == "hillshade-highlight-color-transition") {
+ property = Property::HillshadeHighlightColorTransition;
+ }
+ break;
+ case util::hashFNV1a("hillshade-accent-color"):
+ if (name == "hillshade-accent-color") {
+ property = Property::HillshadeAccentColor;
+ }
+ break;
+ case util::hashFNV1a("hillshade-accent-color-transition"):
+ if (name == "hillshade-accent-color-transition") {
+ property = Property::HillshadeAccentColorTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::HillshadeIlluminationDirection || property == Property::HillshadeExaggeration) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::HillshadeIlluminationDirection) {
+ setHillshadeIlluminationDirection(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeExaggeration) {
+ setHillshadeExaggeration(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::HillshadeIlluminationAnchor) {
+ Error error;
+ optional<PropertyValue<HillshadeIlluminationAnchorType>> typedValue = convert<PropertyValue<HillshadeIlluminationAnchorType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setHillshadeIlluminationAnchor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::HillshadeShadowColor || property == Property::HillshadeHighlightColor || property == Property::HillshadeAccentColor) {
+ Error error;
+ optional<PropertyValue<Color>> typedValue = convert<PropertyValue<Color>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::HillshadeShadowColor) {
+ setHillshadeShadowColor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeHighlightColor) {
+ setHillshadeHighlightColor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeAccentColor) {
+ setHillshadeAccentColor(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::HillshadeIlluminationDirectionTransition) {
+ setHillshadeIlluminationDirectionTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeIlluminationAnchorTransition) {
+ setHillshadeIlluminationAnchorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeExaggerationTransition) {
+ setHillshadeExaggerationTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeShadowColorTransition) {
+ setHillshadeShadowColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeHighlightColorTransition) {
+ setHillshadeHighlightColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::HillshadeAccentColorTransition) {
+ setHillshadeAccentColorTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> HillshadeLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index a9b6d9d02d..b5fb1a97a4 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -8,12 +8,13 @@
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
-<% if (type === 'heatmap') { -%>
-// for constructing default heatmap-color ramp expression from style JSON
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
-<% } -%>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -175,5 +176,145 @@ TransitionOptions <%- camelize(type) %>Layer::get<%- camelize(property.name) %>T
}
<% } -%>
+using namespace conversion;
+
+optional<Error> <%- camelize(type) %>Layer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+<% for (const property of paintProperties) { -%>
+ <%- camelize(property.name) %>,
+<% } -%>
+<% for (const property of paintProperties) { -%>
+ <%- camelize(property.name) %>Transition,
+<% } -%>
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ <% for (const property of paintProperties) { -%>
+case util::hashFNV1a("<%- property.name %>"):
+ if (name == "<%- property.name %>") {
+ property = Property::<%- camelize(property.name) %>;
+ }
+ break;
+ case util::hashFNV1a("<%- property.name %>-transition"):
+ if (name == "<%- property.name %>-transition") {
+ property = Property::<%- camelize(property.name) %>Transition;
+ }
+ break;
+ <% } %>
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+ <%
+ const paintConversions = {};
+ for (const property of paintProperties) {
+ const dataDriven = property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven';
+ const convertTokens = property.name === 'icon-image' || property.name === 'text-field';
+ const conversion = `optional<${propertyValueType(property)}> typedValue = convert<${propertyValueType(property)}>(value, error, ${dataDriven}, ${convertTokens})`;
+ paintConversions[conversion] = paintConversions[conversion] || [];
+ paintConversions[conversion].push(property);
+ }
+ -%>
+ <% for (const key in paintConversions) {
+ const properties = paintConversions[key];
+ %>
+ if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) {
+ Error error;
+ <%- key %>;
+ if (!typedValue) {
+ return error;
+ }
+ <% if (properties.length == 1) { %>
+ set<%- camelize(properties[0].name) %>(*typedValue);
+ return nullopt;
+ <% } else for (const property of properties) { %>
+ if (property == Property::<%- camelize(property.name) %>) {
+ set<%- camelize(property.name) %>(*typedValue);
+ return nullopt;
+ }
+ <% } %>
+ }
+ <% } %>
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+ <% for (const property of paintProperties) { %>
+ if (property == Property::<%- camelize(property.name) %>Transition) {
+ set<%- camelize(property.name) %>Transition(*transition);
+ return nullopt;
+ }
+ <% } %>
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> <%- camelize(type) %>Layer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+<% for (const property of layoutProperties) { -%>
+ <%- camelize(property.name) %>,
+<% } -%>
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ <% for (const property of layoutProperties) { %>
+ case util::hashFNV1a("<%- property.name %>"):
+ if (name == "<%- property.name %>") {
+ property = Property::<%- camelize(property.name) %>;
+ }
+ break;
+ <% } %>
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+ <%
+ const layoutConversions = {};
+ for (const property of layoutProperties) {
+ const dataDriven = property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven';
+ const convertTokens = property.name === 'icon-image' || property.name === 'text-field';
+ const conversion = `optional<${propertyValueType(property)}> typedValue = convert<${propertyValueType(property)}>(value, error, ${dataDriven}, ${convertTokens})`;
+ layoutConversions[conversion] = layoutConversions[conversion] || [];
+ layoutConversions[conversion].push(property);
+ }
+ -%>
+ <% for (const key in layoutConversions) {
+ const properties = layoutConversions[key];
+ %>
+ if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) {
+ Error error;
+ <%- key %>;
+ if (!typedValue) {
+ return error;
+ }
+ <% if (properties.length == 1) { %>
+ set<%- camelize(properties[0].name) %>(*typedValue);
+ return nullopt;
+ <% } else for (const property of properties) { %>
+ if (property == Property::<%- camelize(property.name) %>) {
+ set<%- camelize(property.name) %>(*typedValue);
+ return nullopt;
+ }
+ <% } %>
+ }
+ <% } %>
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs
index 5b774933a6..694d9a62b7 100644
--- a/src/mbgl/style/layers/layer_properties.hpp.ejs
+++ b/src/mbgl/style/layers/layer_properties.hpp.ejs
@@ -26,7 +26,8 @@ struct <%- camelize(property.name) %> : <%- layoutPropertyType(property, type) %
<% } -%>
<% for (const property of paintProperties) { -%>
<% if (property['property-type'] === 'color-ramp') { -%>
-using <%- camelize(property.name) %> = ColorRampProperty;
+struct <%- camelize(property.name) %> : ColorRampProperty {
+};
<% } else { -%>
struct <%- camelize(property.name) %> : <%- paintPropertyType(property, type) %> {
static <%- evaluatedType(property) %> defaultValue() { return <%- defaultValue(property) %>; }
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 0cda849c0f..1b84c2d73e 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -431,5 +438,391 @@ TransitionOptions LineLayer::getLinePatternTransition() const {
return impl().paint.template get<LinePattern>().options;
}
+using namespace conversion;
+
+optional<Error> LineLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ LineOpacity,
+ LineColor,
+ LineTranslate,
+ LineTranslateAnchor,
+ LineWidth,
+ LineGapWidth,
+ LineOffset,
+ LineBlur,
+ LineDasharray,
+ LinePattern,
+ LineOpacityTransition,
+ LineColorTransition,
+ LineTranslateTransition,
+ LineTranslateAnchorTransition,
+ LineWidthTransition,
+ LineGapWidthTransition,
+ LineOffsetTransition,
+ LineBlurTransition,
+ LineDasharrayTransition,
+ LinePatternTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("line-opacity"):
+ if (name == "line-opacity") {
+ property = Property::LineOpacity;
+ }
+ break;
+ case util::hashFNV1a("line-opacity-transition"):
+ if (name == "line-opacity-transition") {
+ property = Property::LineOpacityTransition;
+ }
+ break;
+ case util::hashFNV1a("line-color"):
+ if (name == "line-color") {
+ property = Property::LineColor;
+ }
+ break;
+ case util::hashFNV1a("line-color-transition"):
+ if (name == "line-color-transition") {
+ property = Property::LineColorTransition;
+ }
+ break;
+ case util::hashFNV1a("line-translate"):
+ if (name == "line-translate") {
+ property = Property::LineTranslate;
+ }
+ break;
+ case util::hashFNV1a("line-translate-transition"):
+ if (name == "line-translate-transition") {
+ property = Property::LineTranslateTransition;
+ }
+ break;
+ case util::hashFNV1a("line-translate-anchor"):
+ if (name == "line-translate-anchor") {
+ property = Property::LineTranslateAnchor;
+ }
+ break;
+ case util::hashFNV1a("line-translate-anchor-transition"):
+ if (name == "line-translate-anchor-transition") {
+ property = Property::LineTranslateAnchorTransition;
+ }
+ break;
+ case util::hashFNV1a("line-width"):
+ if (name == "line-width") {
+ property = Property::LineWidth;
+ }
+ break;
+ case util::hashFNV1a("line-width-transition"):
+ if (name == "line-width-transition") {
+ property = Property::LineWidthTransition;
+ }
+ break;
+ case util::hashFNV1a("line-gap-width"):
+ if (name == "line-gap-width") {
+ property = Property::LineGapWidth;
+ }
+ break;
+ case util::hashFNV1a("line-gap-width-transition"):
+ if (name == "line-gap-width-transition") {
+ property = Property::LineGapWidthTransition;
+ }
+ break;
+ case util::hashFNV1a("line-offset"):
+ if (name == "line-offset") {
+ property = Property::LineOffset;
+ }
+ break;
+ case util::hashFNV1a("line-offset-transition"):
+ if (name == "line-offset-transition") {
+ property = Property::LineOffsetTransition;
+ }
+ break;
+ case util::hashFNV1a("line-blur"):
+ if (name == "line-blur") {
+ property = Property::LineBlur;
+ }
+ break;
+ case util::hashFNV1a("line-blur-transition"):
+ if (name == "line-blur-transition") {
+ property = Property::LineBlurTransition;
+ }
+ break;
+ case util::hashFNV1a("line-dasharray"):
+ if (name == "line-dasharray") {
+ property = Property::LineDasharray;
+ }
+ break;
+ case util::hashFNV1a("line-dasharray-transition"):
+ if (name == "line-dasharray-transition") {
+ property = Property::LineDasharrayTransition;
+ }
+ break;
+ case util::hashFNV1a("line-pattern"):
+ if (name == "line-pattern") {
+ property = Property::LinePattern;
+ }
+ break;
+ case util::hashFNV1a("line-pattern-transition"):
+ if (name == "line-pattern-transition") {
+ property = Property::LinePatternTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::LineOpacity || property == Property::LineWidth || property == Property::LineGapWidth || property == Property::LineOffset || property == Property::LineBlur) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::LineOpacity) {
+ setLineOpacity(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::LineWidth) {
+ setLineWidth(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::LineGapWidth) {
+ setLineGapWidth(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::LineOffset) {
+ setLineOffset(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::LineBlur) {
+ setLineBlur(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::LineColor) {
+ Error error;
+ optional<PropertyValue<Color>> typedValue = convert<PropertyValue<Color>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setLineColor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::LineTranslate) {
+ Error error;
+ optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setLineTranslate(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::LineTranslateAnchor) {
+ Error error;
+ optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setLineTranslateAnchor(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::LineDasharray) {
+ Error error;
+ optional<PropertyValue<std::vector<float>>> typedValue = convert<PropertyValue<std::vector<float>>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setLineDasharray(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::LinePattern) {
+ Error error;
+ optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setLinePattern(*typedValue);
+ return nullopt;
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::LineOpacityTransition) {
+ setLineOpacityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineColorTransition) {
+ setLineColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineTranslateTransition) {
+ setLineTranslateTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineTranslateAnchorTransition) {
+ setLineTranslateAnchorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineWidthTransition) {
+ setLineWidthTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineGapWidthTransition) {
+ setLineGapWidthTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineOffsetTransition) {
+ setLineOffsetTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineBlurTransition) {
+ setLineBlurTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LineDasharrayTransition) {
+ setLineDasharrayTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::LinePatternTransition) {
+ setLinePatternTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> LineLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ LineCap,
+ LineJoin,
+ LineMiterLimit,
+ LineRoundLimit,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ case util::hashFNV1a("line-cap"):
+ if (name == "line-cap") {
+ property = Property::LineCap;
+ }
+ break;
+
+ case util::hashFNV1a("line-join"):
+ if (name == "line-join") {
+ property = Property::LineJoin;
+ }
+ break;
+
+ case util::hashFNV1a("line-miter-limit"):
+ if (name == "line-miter-limit") {
+ property = Property::LineMiterLimit;
+ }
+ break;
+
+ case util::hashFNV1a("line-round-limit"):
+ if (name == "line-round-limit") {
+ property = Property::LineRoundLimit;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::LineCap) {
+ Error error;
+ optional<PropertyValue<LineCapType>> typedValue = convert<PropertyValue<LineCapType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setLineCap(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::LineJoin) {
+ Error error;
+ optional<PropertyValue<LineJoinType>> typedValue = convert<PropertyValue<LineJoinType>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setLineJoin(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::LineMiterLimit || property == Property::LineRoundLimit) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::LineMiterLimit) {
+ setLineMiterLimit(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::LineRoundLimit) {
+ setLineRoundLimit(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp
index bee88d6a47..68cd3a8f49 100644
--- a/src/mbgl/style/layers/line_layer_impl.cpp
+++ b/src/mbgl/style/layers/line_layer_impl.cpp
@@ -4,7 +4,7 @@ namespace mbgl {
namespace style {
bool LineLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const {
- assert(dynamic_cast<const LineLayer::Impl*>(&other));
+ assert(other.type == LayerType::Line);
const auto& impl = static_cast<const style::LineLayer::Impl&>(other);
return filter != impl.filter ||
visibility != impl.visibility ||
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
index e5b03df0f6..7bd01c92e1 100644
--- a/src/mbgl/style/layers/raster_layer.cpp
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -290,5 +297,248 @@ TransitionOptions RasterLayer::getRasterFadeDurationTransition() const {
return impl().paint.template get<RasterFadeDuration>().options;
}
+using namespace conversion;
+
+optional<Error> RasterLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ RasterOpacity,
+ RasterHueRotate,
+ RasterBrightnessMin,
+ RasterBrightnessMax,
+ RasterSaturation,
+ RasterContrast,
+ RasterResampling,
+ RasterFadeDuration,
+ RasterOpacityTransition,
+ RasterHueRotateTransition,
+ RasterBrightnessMinTransition,
+ RasterBrightnessMaxTransition,
+ RasterSaturationTransition,
+ RasterContrastTransition,
+ RasterResamplingTransition,
+ RasterFadeDurationTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("raster-opacity"):
+ if (name == "raster-opacity") {
+ property = Property::RasterOpacity;
+ }
+ break;
+ case util::hashFNV1a("raster-opacity-transition"):
+ if (name == "raster-opacity-transition") {
+ property = Property::RasterOpacityTransition;
+ }
+ break;
+ case util::hashFNV1a("raster-hue-rotate"):
+ if (name == "raster-hue-rotate") {
+ property = Property::RasterHueRotate;
+ }
+ break;
+ case util::hashFNV1a("raster-hue-rotate-transition"):
+ if (name == "raster-hue-rotate-transition") {
+ property = Property::RasterHueRotateTransition;
+ }
+ break;
+ case util::hashFNV1a("raster-brightness-min"):
+ if (name == "raster-brightness-min") {
+ property = Property::RasterBrightnessMin;
+ }
+ break;
+ case util::hashFNV1a("raster-brightness-min-transition"):
+ if (name == "raster-brightness-min-transition") {
+ property = Property::RasterBrightnessMinTransition;
+ }
+ break;
+ case util::hashFNV1a("raster-brightness-max"):
+ if (name == "raster-brightness-max") {
+ property = Property::RasterBrightnessMax;
+ }
+ break;
+ case util::hashFNV1a("raster-brightness-max-transition"):
+ if (name == "raster-brightness-max-transition") {
+ property = Property::RasterBrightnessMaxTransition;
+ }
+ break;
+ case util::hashFNV1a("raster-saturation"):
+ if (name == "raster-saturation") {
+ property = Property::RasterSaturation;
+ }
+ break;
+ case util::hashFNV1a("raster-saturation-transition"):
+ if (name == "raster-saturation-transition") {
+ property = Property::RasterSaturationTransition;
+ }
+ break;
+ case util::hashFNV1a("raster-contrast"):
+ if (name == "raster-contrast") {
+ property = Property::RasterContrast;
+ }
+ break;
+ case util::hashFNV1a("raster-contrast-transition"):
+ if (name == "raster-contrast-transition") {
+ property = Property::RasterContrastTransition;
+ }
+ break;
+ case util::hashFNV1a("raster-resampling"):
+ if (name == "raster-resampling") {
+ property = Property::RasterResampling;
+ }
+ break;
+ case util::hashFNV1a("raster-resampling-transition"):
+ if (name == "raster-resampling-transition") {
+ property = Property::RasterResamplingTransition;
+ }
+ break;
+ case util::hashFNV1a("raster-fade-duration"):
+ if (name == "raster-fade-duration") {
+ property = Property::RasterFadeDuration;
+ }
+ break;
+ case util::hashFNV1a("raster-fade-duration-transition"):
+ if (name == "raster-fade-duration-transition") {
+ property = Property::RasterFadeDurationTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::RasterOpacity || property == Property::RasterHueRotate || property == Property::RasterBrightnessMin || property == Property::RasterBrightnessMax || property == Property::RasterSaturation || property == Property::RasterContrast || property == Property::RasterFadeDuration) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::RasterOpacity) {
+ setRasterOpacity(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::RasterHueRotate) {
+ setRasterHueRotate(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::RasterBrightnessMin) {
+ setRasterBrightnessMin(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::RasterBrightnessMax) {
+ setRasterBrightnessMax(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::RasterSaturation) {
+ setRasterSaturation(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::RasterContrast) {
+ setRasterContrast(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::RasterFadeDuration) {
+ setRasterFadeDuration(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::RasterResampling) {
+ Error error;
+ optional<PropertyValue<RasterResamplingType>> typedValue = convert<PropertyValue<RasterResamplingType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setRasterResampling(*typedValue);
+ return nullopt;
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::RasterOpacityTransition) {
+ setRasterOpacityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::RasterHueRotateTransition) {
+ setRasterHueRotateTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::RasterBrightnessMinTransition) {
+ setRasterBrightnessMinTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::RasterBrightnessMaxTransition) {
+ setRasterBrightnessMaxTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::RasterSaturationTransition) {
+ setRasterSaturationTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::RasterContrastTransition) {
+ setRasterContrastTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::RasterResamplingTransition) {
+ setRasterResamplingTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::RasterFadeDurationTransition) {
+ setRasterFadeDurationTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> RasterLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index c416c6a6c5..4ea138a7f5 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -3,6 +3,13 @@
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
+#include <mbgl/style/conversion/constant.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
+#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion/json.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {
namespace style {
@@ -1051,5 +1058,937 @@ TransitionOptions SymbolLayer::getTextTranslateAnchorTransition() const {
return impl().paint.template get<TextTranslateAnchor>().options;
}
+using namespace conversion;
+
+optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Convertible& value) {
+ enum class Property {
+ Unknown,
+ IconOpacity,
+ IconColor,
+ IconHaloColor,
+ IconHaloWidth,
+ IconHaloBlur,
+ IconTranslate,
+ IconTranslateAnchor,
+ TextOpacity,
+ TextColor,
+ TextHaloColor,
+ TextHaloWidth,
+ TextHaloBlur,
+ TextTranslate,
+ TextTranslateAnchor,
+ IconOpacityTransition,
+ IconColorTransition,
+ IconHaloColorTransition,
+ IconHaloWidthTransition,
+ IconHaloBlurTransition,
+ IconTranslateTransition,
+ IconTranslateAnchorTransition,
+ TextOpacityTransition,
+ TextColorTransition,
+ TextHaloColorTransition,
+ TextHaloWidthTransition,
+ TextHaloBlurTransition,
+ TextTranslateTransition,
+ TextTranslateAnchorTransition,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+ case util::hashFNV1a("icon-opacity"):
+ if (name == "icon-opacity") {
+ property = Property::IconOpacity;
+ }
+ break;
+ case util::hashFNV1a("icon-opacity-transition"):
+ if (name == "icon-opacity-transition") {
+ property = Property::IconOpacityTransition;
+ }
+ break;
+ case util::hashFNV1a("icon-color"):
+ if (name == "icon-color") {
+ property = Property::IconColor;
+ }
+ break;
+ case util::hashFNV1a("icon-color-transition"):
+ if (name == "icon-color-transition") {
+ property = Property::IconColorTransition;
+ }
+ break;
+ case util::hashFNV1a("icon-halo-color"):
+ if (name == "icon-halo-color") {
+ property = Property::IconHaloColor;
+ }
+ break;
+ case util::hashFNV1a("icon-halo-color-transition"):
+ if (name == "icon-halo-color-transition") {
+ property = Property::IconHaloColorTransition;
+ }
+ break;
+ case util::hashFNV1a("icon-halo-width"):
+ if (name == "icon-halo-width") {
+ property = Property::IconHaloWidth;
+ }
+ break;
+ case util::hashFNV1a("icon-halo-width-transition"):
+ if (name == "icon-halo-width-transition") {
+ property = Property::IconHaloWidthTransition;
+ }
+ break;
+ case util::hashFNV1a("icon-halo-blur"):
+ if (name == "icon-halo-blur") {
+ property = Property::IconHaloBlur;
+ }
+ break;
+ case util::hashFNV1a("icon-halo-blur-transition"):
+ if (name == "icon-halo-blur-transition") {
+ property = Property::IconHaloBlurTransition;
+ }
+ break;
+ case util::hashFNV1a("icon-translate"):
+ if (name == "icon-translate") {
+ property = Property::IconTranslate;
+ }
+ break;
+ case util::hashFNV1a("icon-translate-transition"):
+ if (name == "icon-translate-transition") {
+ property = Property::IconTranslateTransition;
+ }
+ break;
+ case util::hashFNV1a("icon-translate-anchor"):
+ if (name == "icon-translate-anchor") {
+ property = Property::IconTranslateAnchor;
+ }
+ break;
+ case util::hashFNV1a("icon-translate-anchor-transition"):
+ if (name == "icon-translate-anchor-transition") {
+ property = Property::IconTranslateAnchorTransition;
+ }
+ break;
+ case util::hashFNV1a("text-opacity"):
+ if (name == "text-opacity") {
+ property = Property::TextOpacity;
+ }
+ break;
+ case util::hashFNV1a("text-opacity-transition"):
+ if (name == "text-opacity-transition") {
+ property = Property::TextOpacityTransition;
+ }
+ break;
+ case util::hashFNV1a("text-color"):
+ if (name == "text-color") {
+ property = Property::TextColor;
+ }
+ break;
+ case util::hashFNV1a("text-color-transition"):
+ if (name == "text-color-transition") {
+ property = Property::TextColorTransition;
+ }
+ break;
+ case util::hashFNV1a("text-halo-color"):
+ if (name == "text-halo-color") {
+ property = Property::TextHaloColor;
+ }
+ break;
+ case util::hashFNV1a("text-halo-color-transition"):
+ if (name == "text-halo-color-transition") {
+ property = Property::TextHaloColorTransition;
+ }
+ break;
+ case util::hashFNV1a("text-halo-width"):
+ if (name == "text-halo-width") {
+ property = Property::TextHaloWidth;
+ }
+ break;
+ case util::hashFNV1a("text-halo-width-transition"):
+ if (name == "text-halo-width-transition") {
+ property = Property::TextHaloWidthTransition;
+ }
+ break;
+ case util::hashFNV1a("text-halo-blur"):
+ if (name == "text-halo-blur") {
+ property = Property::TextHaloBlur;
+ }
+ break;
+ case util::hashFNV1a("text-halo-blur-transition"):
+ if (name == "text-halo-blur-transition") {
+ property = Property::TextHaloBlurTransition;
+ }
+ break;
+ case util::hashFNV1a("text-translate"):
+ if (name == "text-translate") {
+ property = Property::TextTranslate;
+ }
+ break;
+ case util::hashFNV1a("text-translate-transition"):
+ if (name == "text-translate-transition") {
+ property = Property::TextTranslateTransition;
+ }
+ break;
+ case util::hashFNV1a("text-translate-anchor"):
+ if (name == "text-translate-anchor") {
+ property = Property::TextTranslateAnchor;
+ }
+ break;
+ case util::hashFNV1a("text-translate-anchor-transition"):
+ if (name == "text-translate-anchor-transition") {
+ property = Property::TextTranslateAnchorTransition;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::IconOpacity || property == Property::IconHaloWidth || property == Property::IconHaloBlur || property == Property::TextOpacity || property == Property::TextHaloWidth || property == Property::TextHaloBlur) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconOpacity) {
+ setIconOpacity(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconHaloWidth) {
+ setIconHaloWidth(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconHaloBlur) {
+ setIconHaloBlur(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextOpacity) {
+ setTextOpacity(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextHaloWidth) {
+ setTextHaloWidth(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextHaloBlur) {
+ setTextHaloBlur(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::IconColor || property == Property::IconHaloColor || property == Property::TextColor || property == Property::TextHaloColor) {
+ Error error;
+ optional<PropertyValue<Color>> typedValue = convert<PropertyValue<Color>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconColor) {
+ setIconColor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconHaloColor) {
+ setIconHaloColor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextColor) {
+ setTextColor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextHaloColor) {
+ setTextHaloColor(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ 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);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconTranslate) {
+ setIconTranslate(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextTranslate) {
+ setTextTranslate(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::IconTranslateAnchor || property == Property::TextTranslateAnchor) {
+ Error error;
+ optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconTranslateAnchor) {
+ setIconTranslateAnchor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextTranslateAnchor) {
+ setTextTranslateAnchor(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+
+ Error error;
+ optional<TransitionOptions> transition = convert<TransitionOptions>(value, error);
+ if (!transition) {
+ return error;
+ }
+
+ if (property == Property::IconOpacityTransition) {
+ setIconOpacityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::IconColorTransition) {
+ setIconColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::IconHaloColorTransition) {
+ setIconHaloColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::IconHaloWidthTransition) {
+ setIconHaloWidthTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::IconHaloBlurTransition) {
+ setIconHaloBlurTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::IconTranslateTransition) {
+ setIconTranslateTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::IconTranslateAnchorTransition) {
+ setIconTranslateAnchorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::TextOpacityTransition) {
+ setTextOpacityTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::TextColorTransition) {
+ setTextColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::TextHaloColorTransition) {
+ setTextHaloColorTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::TextHaloWidthTransition) {
+ setTextHaloWidthTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::TextHaloBlurTransition) {
+ setTextHaloBlurTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::TextTranslateTransition) {
+ setTextTranslateTransition(*transition);
+ return nullopt;
+ }
+
+ if (property == Property::TextTranslateAnchorTransition) {
+ setTextTranslateAnchorTransition(*transition);
+ return nullopt;
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
+optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Convertible& value) {
+ if (name == "visibility") {
+ return Layer::setVisibility(value);
+ }
+
+ enum class Property {
+ Unknown,
+ SymbolPlacement,
+ SymbolSpacing,
+ SymbolAvoidEdges,
+ IconAllowOverlap,
+ IconIgnorePlacement,
+ IconOptional,
+ IconRotationAlignment,
+ IconSize,
+ IconTextFit,
+ IconTextFitPadding,
+ IconImage,
+ IconRotate,
+ IconPadding,
+ IconKeepUpright,
+ IconOffset,
+ IconAnchor,
+ IconPitchAlignment,
+ TextPitchAlignment,
+ TextRotationAlignment,
+ TextField,
+ TextFont,
+ TextSize,
+ TextMaxWidth,
+ TextLineHeight,
+ TextLetterSpacing,
+ TextJustify,
+ TextAnchor,
+ TextMaxAngle,
+ TextRotate,
+ TextPadding,
+ TextKeepUpright,
+ TextTransform,
+ TextOffset,
+ TextAllowOverlap,
+ TextIgnorePlacement,
+ TextOptional,
+ };
+
+ Property property = Property::Unknown;
+ switch (util::hashFNV1a(name.c_str())) {
+
+ case util::hashFNV1a("symbol-placement"):
+ if (name == "symbol-placement") {
+ property = Property::SymbolPlacement;
+ }
+ break;
+
+ case util::hashFNV1a("symbol-spacing"):
+ if (name == "symbol-spacing") {
+ property = Property::SymbolSpacing;
+ }
+ break;
+
+ case util::hashFNV1a("symbol-avoid-edges"):
+ if (name == "symbol-avoid-edges") {
+ property = Property::SymbolAvoidEdges;
+ }
+ break;
+
+ case util::hashFNV1a("icon-allow-overlap"):
+ if (name == "icon-allow-overlap") {
+ property = Property::IconAllowOverlap;
+ }
+ break;
+
+ case util::hashFNV1a("icon-ignore-placement"):
+ if (name == "icon-ignore-placement") {
+ property = Property::IconIgnorePlacement;
+ }
+ break;
+
+ case util::hashFNV1a("icon-optional"):
+ if (name == "icon-optional") {
+ property = Property::IconOptional;
+ }
+ break;
+
+ case util::hashFNV1a("icon-rotation-alignment"):
+ if (name == "icon-rotation-alignment") {
+ property = Property::IconRotationAlignment;
+ }
+ break;
+
+ case util::hashFNV1a("icon-size"):
+ if (name == "icon-size") {
+ property = Property::IconSize;
+ }
+ break;
+
+ case util::hashFNV1a("icon-text-fit"):
+ if (name == "icon-text-fit") {
+ property = Property::IconTextFit;
+ }
+ break;
+
+ case util::hashFNV1a("icon-text-fit-padding"):
+ if (name == "icon-text-fit-padding") {
+ property = Property::IconTextFitPadding;
+ }
+ break;
+
+ case util::hashFNV1a("icon-image"):
+ if (name == "icon-image") {
+ property = Property::IconImage;
+ }
+ break;
+
+ case util::hashFNV1a("icon-rotate"):
+ if (name == "icon-rotate") {
+ property = Property::IconRotate;
+ }
+ break;
+
+ case util::hashFNV1a("icon-padding"):
+ if (name == "icon-padding") {
+ property = Property::IconPadding;
+ }
+ break;
+
+ case util::hashFNV1a("icon-keep-upright"):
+ if (name == "icon-keep-upright") {
+ property = Property::IconKeepUpright;
+ }
+ break;
+
+ case util::hashFNV1a("icon-offset"):
+ if (name == "icon-offset") {
+ property = Property::IconOffset;
+ }
+ break;
+
+ case util::hashFNV1a("icon-anchor"):
+ if (name == "icon-anchor") {
+ property = Property::IconAnchor;
+ }
+ break;
+
+ case util::hashFNV1a("icon-pitch-alignment"):
+ if (name == "icon-pitch-alignment") {
+ property = Property::IconPitchAlignment;
+ }
+ break;
+
+ case util::hashFNV1a("text-pitch-alignment"):
+ if (name == "text-pitch-alignment") {
+ property = Property::TextPitchAlignment;
+ }
+ break;
+
+ case util::hashFNV1a("text-rotation-alignment"):
+ if (name == "text-rotation-alignment") {
+ property = Property::TextRotationAlignment;
+ }
+ break;
+
+ case util::hashFNV1a("text-field"):
+ if (name == "text-field") {
+ property = Property::TextField;
+ }
+ break;
+
+ case util::hashFNV1a("text-font"):
+ if (name == "text-font") {
+ property = Property::TextFont;
+ }
+ break;
+
+ case util::hashFNV1a("text-size"):
+ if (name == "text-size") {
+ property = Property::TextSize;
+ }
+ break;
+
+ case util::hashFNV1a("text-max-width"):
+ if (name == "text-max-width") {
+ property = Property::TextMaxWidth;
+ }
+ break;
+
+ case util::hashFNV1a("text-line-height"):
+ if (name == "text-line-height") {
+ property = Property::TextLineHeight;
+ }
+ break;
+
+ case util::hashFNV1a("text-letter-spacing"):
+ if (name == "text-letter-spacing") {
+ property = Property::TextLetterSpacing;
+ }
+ break;
+
+ case util::hashFNV1a("text-justify"):
+ if (name == "text-justify") {
+ property = Property::TextJustify;
+ }
+ break;
+
+ case util::hashFNV1a("text-anchor"):
+ if (name == "text-anchor") {
+ property = Property::TextAnchor;
+ }
+ break;
+
+ case util::hashFNV1a("text-max-angle"):
+ if (name == "text-max-angle") {
+ property = Property::TextMaxAngle;
+ }
+ break;
+
+ case util::hashFNV1a("text-rotate"):
+ if (name == "text-rotate") {
+ property = Property::TextRotate;
+ }
+ break;
+
+ case util::hashFNV1a("text-padding"):
+ if (name == "text-padding") {
+ property = Property::TextPadding;
+ }
+ break;
+
+ case util::hashFNV1a("text-keep-upright"):
+ if (name == "text-keep-upright") {
+ property = Property::TextKeepUpright;
+ }
+ break;
+
+ case util::hashFNV1a("text-transform"):
+ if (name == "text-transform") {
+ property = Property::TextTransform;
+ }
+ break;
+
+ case util::hashFNV1a("text-offset"):
+ if (name == "text-offset") {
+ property = Property::TextOffset;
+ }
+ break;
+
+ case util::hashFNV1a("text-allow-overlap"):
+ if (name == "text-allow-overlap") {
+ property = Property::TextAllowOverlap;
+ }
+ break;
+
+ case util::hashFNV1a("text-ignore-placement"):
+ if (name == "text-ignore-placement") {
+ property = Property::TextIgnorePlacement;
+ }
+ break;
+
+ case util::hashFNV1a("text-optional"):
+ if (name == "text-optional") {
+ property = Property::TextOptional;
+ }
+ break;
+
+ }
+
+ if (property == Property::Unknown) {
+ return Error { "layer doesn't support this property" };
+ }
+
+
+ if (property == Property::SymbolPlacement) {
+ Error error;
+ optional<PropertyValue<SymbolPlacementType>> typedValue = convert<PropertyValue<SymbolPlacementType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setSymbolPlacement(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::SymbolSpacing || property == Property::IconPadding || property == Property::TextLineHeight || property == Property::TextMaxAngle || property == Property::TextPadding) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::SymbolSpacing) {
+ setSymbolSpacing(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconPadding) {
+ setIconPadding(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextLineHeight) {
+ setTextLineHeight(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextMaxAngle) {
+ setTextMaxAngle(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextPadding) {
+ setTextPadding(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::SymbolAvoidEdges || property == Property::IconAllowOverlap || property == Property::IconIgnorePlacement || property == Property::IconOptional || property == Property::IconKeepUpright || property == Property::TextKeepUpright || property == Property::TextAllowOverlap || property == Property::TextIgnorePlacement || property == Property::TextOptional) {
+ Error error;
+ optional<PropertyValue<bool>> typedValue = convert<PropertyValue<bool>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::SymbolAvoidEdges) {
+ setSymbolAvoidEdges(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconAllowOverlap) {
+ setIconAllowOverlap(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconIgnorePlacement) {
+ setIconIgnorePlacement(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconOptional) {
+ setIconOptional(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconKeepUpright) {
+ setIconKeepUpright(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextKeepUpright) {
+ setTextKeepUpright(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextAllowOverlap) {
+ setTextAllowOverlap(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextIgnorePlacement) {
+ setTextIgnorePlacement(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextOptional) {
+ setTextOptional(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::IconRotationAlignment || property == Property::IconPitchAlignment || property == Property::TextPitchAlignment || property == Property::TextRotationAlignment) {
+ Error error;
+ optional<PropertyValue<AlignmentType>> typedValue = convert<PropertyValue<AlignmentType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconRotationAlignment) {
+ setIconRotationAlignment(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconPitchAlignment) {
+ setIconPitchAlignment(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextPitchAlignment) {
+ setTextPitchAlignment(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextRotationAlignment) {
+ setTextRotationAlignment(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::IconSize || property == Property::IconRotate || property == Property::TextSize || property == Property::TextMaxWidth || property == Property::TextLetterSpacing || property == Property::TextRotate) {
+ Error error;
+ optional<PropertyValue<float>> typedValue = convert<PropertyValue<float>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconSize) {
+ setIconSize(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::IconRotate) {
+ setIconRotate(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextSize) {
+ setTextSize(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextMaxWidth) {
+ setTextMaxWidth(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextLetterSpacing) {
+ setTextLetterSpacing(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextRotate) {
+ setTextRotate(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::IconTextFit) {
+ Error error;
+ optional<PropertyValue<IconTextFitType>> typedValue = convert<PropertyValue<IconTextFitType>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setIconTextFit(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::IconTextFitPadding) {
+ Error error;
+ optional<PropertyValue<std::array<float, 4>>> typedValue = convert<PropertyValue<std::array<float, 4>>>(value, error, false, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setIconTextFitPadding(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::IconImage || property == Property::TextField) {
+ Error error;
+ optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, true);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconImage) {
+ setIconImage(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextField) {
+ setTextField(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ 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);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconOffset) {
+ setIconOffset(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextOffset) {
+ setTextOffset(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::IconAnchor || property == Property::TextAnchor) {
+ Error error;
+ optional<PropertyValue<SymbolAnchorType>> typedValue = convert<PropertyValue<SymbolAnchorType>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ if (property == Property::IconAnchor) {
+ setIconAnchor(*typedValue);
+ return nullopt;
+ }
+
+ if (property == Property::TextAnchor) {
+ setTextAnchor(*typedValue);
+ return nullopt;
+ }
+
+ }
+
+ if (property == Property::TextFont) {
+ Error error;
+ optional<PropertyValue<std::vector<std::string>>> typedValue = convert<PropertyValue<std::vector<std::string>>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setTextFont(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::TextJustify) {
+ Error error;
+ optional<PropertyValue<TextJustifyType>> typedValue = convert<PropertyValue<TextJustifyType>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setTextJustify(*typedValue);
+ return nullopt;
+
+ }
+
+ if (property == Property::TextTransform) {
+ Error error;
+ optional<PropertyValue<TextTransformType>> typedValue = convert<PropertyValue<TextTransformType>>(value, error, true, false);
+ if (!typedValue) {
+ return error;
+ }
+
+ setTextTransform(*typedValue);
+ return nullopt;
+
+ }
+
+
+ return Error { "layer doesn't support this property" };
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp
index b59768725d..753b2fa184 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.cpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.cpp
@@ -4,7 +4,7 @@ namespace mbgl {
namespace style {
bool SymbolLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const {
- assert(dynamic_cast<const SymbolLayer::Impl*>(&other));
+ assert(other.type == LayerType::Symbol);
const auto& impl = static_cast<const style::SymbolLayer::Impl&>(other);
return filter != impl.filter ||
visibility != impl.visibility ||
diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp
index 8d14d7972c..114a666f08 100644
--- a/src/mbgl/style/parser.cpp
+++ b/src/mbgl/style/parser.cpp
@@ -1,13 +1,12 @@
#include <mbgl/style/parser.hpp>
#include <mbgl/style/layer_impl.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/rapidjson_conversion.hpp>
-#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/coordinate.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/light.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/string.hpp>
@@ -274,31 +273,12 @@ void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique
}
std::vector<FontStack> Parser::fontStacks() const {
- std::set<FontStack> result;
-
+ std::vector<Immutable<Layer::Impl>> impls;
+ impls.reserve(layers.size());
for (const auto& layer : layers) {
- if (layer->is<SymbolLayer>() && !layer->as<SymbolLayer>()->getTextField().isUndefined()) {
- layer->as<SymbolLayer>()->getTextFont().match(
- [&] (Undefined) {
- result.insert({"Open Sans Regular", "Arial Unicode MS Regular"});
- },
- [&] (const FontStack& constant) {
- result.insert(constant);
- },
- [&] (const auto& function) {
- for (const auto& value : function.possibleOutputs()) {
- if (value) {
- result.insert(*value);
- } else {
- Log::Warning(Event::ParseStyle, "Layer '%s' has an invalid value for text-font and will not work offline. Output values must be contained as literals within the expression.", layer->getID().c_str());
- break;
- }
- }
- }
- );
- }
+ impls.emplace_back(layer->baseImpl);
}
-
+ std::set<FontStack> result = mbgl::fontStacks(impls);
return std::vector<FontStack>(result.begin(), result.end());
}
diff --git a/src/mbgl/style/rapidjson_conversion.hpp b/src/mbgl/style/rapidjson_conversion.hpp
index 79bd9c928b..be335101e9 100644
--- a/src/mbgl/style/rapidjson_conversion.hpp
+++ b/src/mbgl/style/rapidjson_conversion.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/util/rapidjson.hpp>
-#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion_impl.hpp>
#include <mapbox/geojson.hpp>
#include <mapbox/geojson/rapidjson.hpp>
diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp
index fd6d7d3013..5ec3909d3e 100644
--- a/src/mbgl/style/sources/geojson_source_impl.cpp
+++ b/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -64,6 +64,7 @@ GeoJSONSource::Impl::Impl(const Impl& other, const GeoJSON& geoJSON)
vtOptions.extent = util::EXTENT;
vtOptions.buffer = ::round(scale * options.buffer);
vtOptions.tolerance = scale * options.tolerance;
+ vtOptions.lineMetrics = options.lineMetrics;
data = std::make_unique<GeoJSONVTData>(geoJSON, vtOptions);
}
}
diff --git a/src/mbgl/text/collision_index.cpp b/src/mbgl/text/collision_index.cpp
index 091840a371..dae789a196 100644
--- a/src/mbgl/text/collision_index.cpp
+++ b/src/mbgl/text/collision_index.cpp
@@ -62,6 +62,21 @@ bool CollisionIndex::isOffscreen(const CollisionBox& box) const {
bool CollisionIndex::isInsideGrid(const CollisionBox& box) const {
return box.px2 >= 0 && box.px1 < gridRightBoundary && box.py2 >= 0 && box.py1 < gridBottomBoundary;
}
+
+CollisionTileBoundaries CollisionIndex::projectTileBoundaries(const mat4& posMatrix) const {
+ Point<float> topLeft = projectPoint(posMatrix, { 0, 0 });
+ Point<float> bottomRight = projectPoint(posMatrix, { util::EXTENT, util::EXTENT });
+
+ return {{ topLeft.x, topLeft.y, bottomRight.x, bottomRight.y }};
+
+}
+
+bool CollisionIndex::isInsideTile(const CollisionBox& box, const CollisionTileBoundaries& tileBoundaries) const {
+ // This check is only well defined when the tile boundaries are axis-aligned
+ // We are relying on it only being used in MapMode::Tile, where that is always the case
+
+ return box.px1 >= tileBoundaries[0] && box.py1 >= tileBoundaries[1] && box.px2 < tileBoundaries[2] && box.py2 < tileBoundaries[3];
+}
std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
@@ -73,7 +88,8 @@ std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
const float fontSize,
const bool allowOverlap,
const bool pitchWithMap,
- const bool collisionDebug) {
+ const bool collisionDebug,
+ const optional<CollisionTileBoundaries>& avoidEdges) {
if (!feature.alongLine) {
CollisionBox& box = feature.boxes.front();
const auto projectedPoint = projectAndGetPerspectiveRatio(posMatrix, box.anchor);
@@ -82,15 +98,17 @@ std::pair<bool,bool> CollisionIndex::placeFeature(CollisionFeature& feature,
box.py1 = box.y1 * tileToViewport + projectedPoint.first.y;
box.px2 = box.x2 * tileToViewport + projectedPoint.first.x;
box.py2 = box.y2 * tileToViewport + projectedPoint.first.y;
+
- if (!isInsideGrid(box) ||
+ if ((avoidEdges && !isInsideTile(box, *avoidEdges)) ||
+ !isInsideGrid(box) ||
(!allowOverlap && collisionGrid.hitTest({{ box.px1, box.py1 }, { box.px2, box.py2 }}))) {
return { false, false };
}
return {true, isOffscreen(box)};
} else {
- return placeLineFeature(feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug);
+ return placeLineFeature(feature, posMatrix, labelPlaneMatrix, textPixelRatio, symbol, scale, fontSize, allowOverlap, pitchWithMap, collisionDebug, avoidEdges);
}
}
@@ -103,7 +121,8 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
const float fontSize,
const bool allowOverlap,
const bool pitchWithMap,
- const bool collisionDebug) {
+ const bool collisionDebug,
+ const optional<CollisionTileBoundaries>& avoidEdges) {
const auto tileUnitAnchorPoint = symbol.anchorPoint;
const auto projectedAnchor = projectAnchor(posMatrix, tileUnitAnchorPoint);
@@ -202,15 +221,14 @@ std::pair<bool,bool> CollisionIndex::placeLineFeature(CollisionFeature& feature,
entirelyOffscreen &= isOffscreen(circle);
inGrid |= isInsideGrid(circle);
- if (!allowOverlap) {
- if (collisionGrid.hitTest({{circle.px, circle.py}, circle.radius})) {
- if (!collisionDebug) {
- return {false, false};
- } else {
- // Don't early exit if we're showing the debug circles because we still want to calculate
- // which circles are in use
- collisionDetected = true;
- }
+ if ((avoidEdges && !isInsideTile(circle, *avoidEdges)) ||
+ (!allowOverlap && collisionGrid.hitTest({{circle.px, circle.py}, circle.radius}))) {
+ if (!collisionDebug) {
+ return {false, false};
+ } else {
+ // Don't early exit if we're showing the debug circles because we still want to calculate
+ // which circles are in use
+ collisionDetected = true;
}
}
}
diff --git a/src/mbgl/text/collision_index.hpp b/src/mbgl/text/collision_index.hpp
index b2be4c6ade..78782fe61c 100644
--- a/src/mbgl/text/collision_index.hpp
+++ b/src/mbgl/text/collision_index.hpp
@@ -3,13 +3,18 @@
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/text/collision_feature.hpp>
#include <mbgl/util/grid_index.hpp>
+#include <mbgl/util/optional.hpp>
#include <mbgl/map/transform_state.hpp>
+#include <array>
+
namespace mbgl {
class PlacedSymbol;
struct TileDistance;
+
+using CollisionTileBoundaries = std::array<float,4>;
class CollisionIndex {
public:
@@ -26,15 +31,19 @@ public:
const float fontSize,
const bool allowOverlap,
const bool pitchWithMap,
- const bool collisionDebug);
+ const bool collisionDebug,
+ const optional<CollisionTileBoundaries>& avoidEdges);
void insertFeature(CollisionFeature& feature, bool ignorePlacement, uint32_t bucketInstanceId);
std::unordered_map<uint32_t, std::vector<IndexedSubfeature>> queryRenderedSymbols(const ScreenLineString&) const;
+
+ CollisionTileBoundaries projectTileBoundaries(const mat4& posMatrix) const;
private:
bool isOffscreen(const CollisionBox&) const;
bool isInsideGrid(const CollisionBox&) const;
+ bool isInsideTile(const CollisionBox&, const CollisionTileBoundaries& tileBoundaries) const;
std::pair<bool,bool> placeLineFeature(CollisionFeature& feature,
const mat4& posMatrix,
@@ -45,7 +54,8 @@ private:
const float fontSize,
const bool allowOverlap,
const bool pitchWithMap,
- const bool collisionDebug);
+ const bool collisionDebug,
+ const optional<CollisionTileBoundaries>& avoidEdges);
float approximateTileDistance(const TileDistance& tileDistance, const float lastSegmentAngle, const float pixelsToTileUnits, const float cameraToAnchorDistance, const bool pitchWithMap);
diff --git a/src/mbgl/text/glyph_manager.cpp b/src/mbgl/text/glyph_manager.cpp
index 3130418908..8e7cfe5ba7 100644
--- a/src/mbgl/text/glyph_manager.cpp
+++ b/src/mbgl/text/glyph_manager.cpp
@@ -5,6 +5,7 @@
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/tiny_sdf.hpp>
+#include <mbgl/util/std.hpp>
namespace mbgl {
@@ -153,4 +154,10 @@ void GlyphManager::removeRequestor(GlyphRequestor& requestor) {
}
}
+void GlyphManager::evict(const std::set<FontStack>& keep) {
+ util::erase_if(entries, [&] (const auto& entry) {
+ return keep.count(entry.first) == 0;
+ });
+}
+
} // namespace mbgl
diff --git a/src/mbgl/text/glyph_manager.hpp b/src/mbgl/text/glyph_manager.hpp
index 84db2c4be5..642471bbf2 100644
--- a/src/mbgl/text/glyph_manager.hpp
+++ b/src/mbgl/text/glyph_manager.hpp
@@ -42,6 +42,9 @@ public:
void setObserver(GlyphManagerObserver*);
+ // Remove glyphs for all but the supplied font stacks.
+ void evict(const std::set<FontStack>&);
+
private:
Glyph generateLocalSDF(const FontStack& fontStack, GlyphID glyphID);
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 16dd94b374..0747133bd2 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -48,7 +48,7 @@ void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatri
if (!renderTile.tile.isRenderable()) {
continue;
}
- assert(dynamic_cast<GeometryTile*>(&renderTile.tile));
+ assert(renderTile.tile.kind == Tile::Kind::Geometry);
GeometryTile& geometryTile = static_cast<GeometryTile&>(renderTile.tile);
auto bucket = renderTile.tile.getBucket<SymbolBucket>(*symbolLayer.baseImpl);
@@ -110,6 +110,13 @@ void Placement::placeLayerBucket(
auto partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(state.getZoom());
auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom());
+ optional<CollisionTileBoundaries> avoidEdges;
+ if (mapMode == MapMode::Tile &&
+ (bucket.layout.get<style::SymbolAvoidEdges>() ||
+ bucket.layout.get<style::SymbolPlacement>() == style::SymbolPlacementType::Line)) {
+ avoidEdges = collisionIndex.projectTileBoundaries(posMatrix);
+ }
+
for (auto& symbolInstance : bucket.symbolInstances) {
if (seenCrossTileIDs.count(symbolInstance.crossTileID) == 0) {
@@ -133,7 +140,7 @@ void Placement::placeLayerBucket(
placedSymbol, scale, fontSize,
bucket.layout.get<style::TextAllowOverlap>(),
bucket.layout.get<style::TextPitchAlignment>() == style::AlignmentType::Map,
- showCollisionBoxes);
+ showCollisionBoxes, avoidEdges);
placeText = placed.first;
offscreen &= placed.second;
}
@@ -147,7 +154,7 @@ void Placement::placeLayerBucket(
placedSymbol, scale, fontSize,
bucket.layout.get<style::IconAllowOverlap>(),
bucket.layout.get<style::IconPitchAlignment>() == style::AlignmentType::Map,
- showCollisionBoxes);
+ showCollisionBoxes, avoidEdges);
placeIcon = placed.first;
offscreen &= placed.second;
}
@@ -254,9 +261,16 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::set<uint32_t>&
JointOpacityState duplicateOpacityState(false, false, true);
+ const bool textAllowOverlap = bucket.layout.get<style::TextAllowOverlap>();
+ const bool iconAllowOverlap = bucket.layout.get<style::IconAllowOverlap>();
+
+ // If allow-overlap is true, we can show symbols before placement runs on them
+ // But we have to wait for placement if we potentially depend on a paired icon/text
+ // with allow-overlap: false.
+ // See https://github.com/mapbox/mapbox-gl-native/issues/12483
JointOpacityState defaultOpacityState(
- bucket.layout.get<style::TextAllowOverlap>(),
- bucket.layout.get<style::IconAllowOverlap>(),
+ textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || bucket.layout.get<style::IconOptional>()),
+ iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || bucket.layout.get<style::TextOptional>()),
true);
for (SymbolInstance& symbolInstance : bucket.symbolInstances) {
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index d686d8440b..90d4d07895 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -44,7 +44,7 @@ using namespace style;
GeometryTile::GeometryTile(const OverscaledTileID& id_,
std::string sourceID_,
const TileParameters& parameters)
- : Tile(id_),
+ : Tile(Kind::Geometry, id_),
sourceID(std::move(sourceID_)),
mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
worker(parameters.workerScheduler,
diff --git a/src/mbgl/tile/raster_dem_tile.cpp b/src/mbgl/tile/raster_dem_tile.cpp
index f29861ee71..751f69bad9 100644
--- a/src/mbgl/tile/raster_dem_tile.cpp
+++ b/src/mbgl/tile/raster_dem_tile.cpp
@@ -15,7 +15,7 @@ namespace mbgl {
RasterDEMTile::RasterDEMTile(const OverscaledTileID& id_,
const TileParameters& parameters,
const Tileset& tileset)
- : Tile(id_),
+ : Tile(Kind::RasterDEM, id_),
loader(*this, id_, parameters, tileset),
mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
worker(parameters.workerScheduler,
diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp
index cc71c04ba1..1346f87ae5 100644
--- a/src/mbgl/tile/raster_tile.cpp
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -15,7 +15,7 @@ namespace mbgl {
RasterTile::RasterTile(const OverscaledTileID& id_,
const TileParameters& parameters,
const Tileset& tileset)
- : Tile(id_),
+ : Tile(Kind::Raster, id_),
loader(*this, id_, parameters, tileset),
mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
worker(parameters.workerScheduler,
diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp
index b95944f10e..5a69df5b43 100644
--- a/src/mbgl/tile/tile.cpp
+++ b/src/mbgl/tile/tile.cpp
@@ -9,7 +9,7 @@ namespace mbgl {
static TileObserver nullObserver;
-Tile::Tile(OverscaledTileID id_) : id(std::move(id_)), observer(&nullObserver) {
+Tile::Tile(Kind kind_, OverscaledTileID id_) : kind(kind_), id(std::move(id_)), observer(&nullObserver) {
}
Tile::~Tile() = default;
@@ -27,6 +27,14 @@ void Tile::setTriedCache() {
}
void Tile::dumpDebugLogs() const {
+ std::string kindString;
+ switch (kind) {
+ case Kind::Geometry: kindString = "Geometry"; break;
+ case Kind::Raster: kindString = "Raster"; break;
+ case Kind::RasterDEM: kindString = "RasterDEM"; break;
+ default: kindString = "Unknown"; break;
+ }
+ Log::Info(Event::General, "Tile::Kind: %s", kindString.c_str());
Log::Info(Event::General, "Tile::id: %s", util::toString(id).c_str());
Log::Info(Event::General, "Tile::renderable: %s", isRenderable() ? "yes" : "no");
Log::Info(Event::General, "Tile::complete: %s", isComplete() ? "yes" : "no");
diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp
index 5cf74abff5..70b2aa0371 100644
--- a/src/mbgl/tile/tile.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -35,7 +35,13 @@ class Context;
class Tile : private util::noncopyable {
public:
- Tile(OverscaledTileID);
+ enum class Kind : uint8_t {
+ Geometry,
+ Raster,
+ RasterDEM
+ };
+
+ Tile(Kind, OverscaledTileID);
virtual ~Tile();
void setObserver(TileObserver* observer);
@@ -119,6 +125,7 @@ public:
void dumpDebugLogs() const;
+ const Kind kind;
OverscaledTileID id;
optional<Timestamp> modified;
optional<Timestamp> expires;
diff --git a/src/mbgl/util/fnv_hash.hpp b/src/mbgl/util/fnv_hash.hpp
new file mode 100644
index 0000000000..87d4661c56
--- /dev/null
+++ b/src/mbgl/util/fnv_hash.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace mbgl {
+namespace util {
+
+inline constexpr uint64_t hashFNV1a(const char * str, uint64_t value = 0xcbf29ce484222325) {
+ return str[0] ? hashFNV1a(str + 1, (value ^ uint64_t(str[0])) * 0x100000001b3) : value;
+}
+
+} // end namespace util
+} // end namespace mbgl
diff --git a/src/mbgl/util/font_stack.cpp b/src/mbgl/util/font_stack.cpp
index fb3b1b60a2..177d5e6f31 100644
--- a/src/mbgl/util/font_stack.cpp
+++ b/src/mbgl/util/font_stack.cpp
@@ -1,10 +1,14 @@
#include <mbgl/util/font_stack.hpp>
+#include <mbgl/util/logging.hpp>
+#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <boost/functional/hash.hpp>
#include <boost/algorithm/string/join.hpp>
namespace mbgl {
+using namespace style;
+
std::string fontStackToString(const FontStack& fontStack) {
return boost::algorithm::join(fontStack, ",");
}
@@ -13,4 +17,40 @@ std::size_t FontStackHash::operator()(const FontStack& fontStack) const {
return boost::hash_range(fontStack.begin(), fontStack.end());
}
+std::set<FontStack> fontStacks(const std::vector<Immutable<style::Layer::Impl>>& layers) {
+ std::set<FontStack> result;
+
+ for (const auto& layer : layers) {
+ if (layer->type != LayerType::Symbol) {
+ continue;
+ }
+
+ const SymbolLayer::Impl& impl = dynamic_cast<const SymbolLayer::Impl&>(*layer);
+ if (impl.layout.get<TextField>().isUndefined()) {
+ continue;
+ }
+
+ impl.layout.get<TextFont>().match(
+ [&] (Undefined) {
+ result.insert({"Open Sans Regular", "Arial Unicode MS Regular"});
+ },
+ [&] (const FontStack& constant) {
+ result.insert(constant);
+ },
+ [&] (const auto& function) {
+ for (const auto& value : function.possibleOutputs()) {
+ if (value) {
+ result.insert(*value);
+ } else {
+ Log::Warning(Event::ParseStyle, "Layer '%s' has an invalid value for text-font and will not render text. Output values must be contained as literals within the expression.", impl.id.c_str());
+ break;
+ }
+ }
+ }
+ );
+ }
+
+ return result;
+}
+
} // namespace mbgl
diff --git a/src/mbgl/util/logging.cpp b/src/mbgl/util/logging.cpp
index d322bd3670..fd3f14825d 100644
--- a/src/mbgl/util/logging.cpp
+++ b/src/mbgl/util/logging.cpp
@@ -35,7 +35,7 @@ void Log::record(EventSeverity severity, Event event, const char* format, ...) {
vsnprintf(msg, sizeof(msg), format, args);
va_end(args);
- record(severity, event, -1, msg);
+ record(severity, event, -1, std::string{ msg });
}
void Log::record(EventSeverity severity, Event event, int64_t code, const char* format, ...) {
diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp
index 3f39e53d40..f58d1270bd 100644
--- a/src/mbgl/util/tile_cover.cpp
+++ b/src/mbgl/util/tile_cover.cpp
@@ -4,6 +4,7 @@
#include <mbgl/map/transform_state.hpp>
#include <mbgl/util/tile_cover_impl.hpp>
#include <mbgl/util/tile_coordinate.hpp>
+#include <mbgl/math/log2.hpp>
#include <functional>
#include <list>