summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/cpp/jni.cpp10
-rw-r--r--include/mbgl/annotation/shape_annotation.hpp8
-rw-r--r--include/mbgl/style/style_properties.hpp18
-rw-r--r--platform/default/glfw_view.cpp7
-rw-r--r--platform/ios/MGLMapView.mm2
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp25
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.cpp63
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.hpp1
-rw-r--r--src/mbgl/layer/background_layer.cpp12
-rw-r--r--src/mbgl/layer/background_layer.hpp18
-rw-r--r--src/mbgl/layer/circle_layer.cpp15
-rw-r--r--src/mbgl/layer/circle_layer.hpp18
-rw-r--r--src/mbgl/layer/fill_layer.cpp29
-rw-r--r--src/mbgl/layer/fill_layer.hpp18
-rw-r--r--src/mbgl/layer/line_layer.cpp22
-rw-r--r--src/mbgl/layer/line_layer.hpp18
-rw-r--r--src/mbgl/layer/raster_layer.cpp16
-rw-r--r--src/mbgl/layer/raster_layer.hpp18
-rw-r--r--src/mbgl/layer/symbol_layer.cpp39
-rw-r--r--src/mbgl/layer/symbol_layer.hpp18
-rw-r--r--src/mbgl/map/tile_worker.cpp24
-rw-r--r--src/mbgl/renderer/circle_bucket.cpp5
-rw-r--r--src/mbgl/renderer/fill_bucket.cpp5
-rw-r--r--src/mbgl/renderer/line_bucket.cpp6
-rw-r--r--src/mbgl/renderer/painter.cpp34
-rw-r--r--src/mbgl/renderer/painter.hpp20
-rw-r--r--src/mbgl/renderer/painter_circle.cpp8
-rw-r--r--src/mbgl/renderer/painter_fill.cpp8
-rw-r--r--src/mbgl/renderer/painter_line.cpp8
-rw-r--r--src/mbgl/renderer/painter_raster.cpp6
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp7
-rw-r--r--src/mbgl/renderer/raster_bucket.cpp5
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp5
-rw-r--r--src/mbgl/style/property_evaluator.hpp45
-rw-r--r--src/mbgl/style/style_layer.cpp241
-rw-r--r--src/mbgl/style/style_layer.hpp93
-rw-r--r--src/mbgl/style/style_parser.cpp238
-rw-r--r--src/mbgl/style/style_parser.hpp8
-rw-r--r--test/api/annotations.cpp40
-rw-r--r--test/fixtures/style_parser/text-size.style.json2
40 files changed, 648 insertions, 535 deletions
diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp
index ae1066f38f..e4f1cd26ab 100644
--- a/android/cpp/jni.cpp
+++ b/android/cpp/jni.cpp
@@ -340,7 +340,7 @@ mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jobjec
return segment;
}
-std::pair<mbgl::AnnotationSegment, mbgl::StyleProperties> annotation_std_pair_from_polygon_jobject(JNIEnv *env, jobject polygon) {
+std::pair<mbgl::AnnotationSegment, mbgl::ShapeAnnotation::Properties> annotation_std_pair_from_polygon_jobject(JNIEnv *env, jobject polygon) {
jfloat alpha = env->GetFloatField(polygon, polygonAlphaId);
jint fillColor = env->GetIntField(polygon, polygonFillColorId);
jint strokeColor = env->GetIntField(polygon, polygonStrokeColorId);
@@ -355,7 +355,7 @@ std::pair<mbgl::AnnotationSegment, mbgl::StyleProperties> annotation_std_pair_fr
int bS = (strokeColor) & 0xFF;
int aS = (strokeColor >> 24) & 0xFF;
- mbgl::StyleProperties shapeProperties;
+ mbgl::ShapeAnnotation::Properties shapeProperties;
mbgl::FillPaintProperties fillProperties;
fillProperties.opacity = alpha;
fillProperties.stroke_color = {{ static_cast<float>(rS) / 255.0f, static_cast<float>(gS) / 255.0f, static_cast<float>(bS) / 255.0f, static_cast<float>(aS) / 255.0f }};
@@ -939,7 +939,7 @@ jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr
return -1;
}
- mbgl::StyleProperties shapeProperties;
+ mbgl::ShapeAnnotation::Properties shapeProperties;
mbgl::LinePaintProperties lineProperties;
lineProperties.opacity = alpha;
lineProperties.color = {{ static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f, static_cast<float>(a) / 255.0f }};
@@ -964,7 +964,7 @@ jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr,
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
std::vector<mbgl::ShapeAnnotation> shapes;
- std::pair<mbgl::AnnotationSegment, mbgl::StyleProperties> segment = annotation_std_pair_from_polygon_jobject(env, polygon);
+ std::pair<mbgl::AnnotationSegment, mbgl::ShapeAnnotation::Properties> segment = annotation_std_pair_from_polygon_jobject(env, polygon);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
@@ -1011,7 +1011,7 @@ jlongArray JNICALL nativeAddPolygons(JNIEnv *env, jobject obj, jlong nativeMapVi
for (jsize i = 0; i < len; i++) {
jobject polygon = reinterpret_cast<jobject>(env->GetObjectArrayElement(jarray, i));
- std::pair<mbgl::AnnotationSegment, mbgl::StyleProperties> segment = annotation_std_pair_from_polygon_jobject(env, polygon);
+ std::pair<mbgl::AnnotationSegment, mbgl::ShapeAnnotation::Properties> segment = annotation_std_pair_from_polygon_jobject(env, polygon);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
return nullptr;
diff --git a/include/mbgl/annotation/shape_annotation.hpp b/include/mbgl/annotation/shape_annotation.hpp
index dd8bf5e4d5..5e6a13149a 100644
--- a/include/mbgl/annotation/shape_annotation.hpp
+++ b/include/mbgl/annotation/shape_annotation.hpp
@@ -6,6 +6,8 @@
#include <mbgl/util/geo.hpp>
+#include <mapbox/variant.hpp>
+
namespace mbgl {
using AnnotationSegment = std::vector<LatLng>;
@@ -13,12 +15,14 @@ using AnnotationSegments = std::vector<AnnotationSegment>;
class ShapeAnnotation {
public:
- inline ShapeAnnotation(const AnnotationSegments& segments_, const StyleProperties& styleProperties_)
+ using Properties = mapbox::util::variant<FillPaintProperties, LinePaintProperties>;
+
+ inline ShapeAnnotation(const AnnotationSegments& segments_, const Properties& styleProperties_)
: segments(segments_), styleProperties(styleProperties_) {
}
const AnnotationSegments segments;
- const StyleProperties styleProperties;
+ const Properties styleProperties;
};
}
diff --git a/include/mbgl/style/style_properties.hpp b/include/mbgl/style/style_properties.hpp
index aacac3387b..2216491135 100644
--- a/include/mbgl/style/style_properties.hpp
+++ b/include/mbgl/style/style_properties.hpp
@@ -1,14 +1,10 @@
#ifndef MBGL_STYLE_STYLE_PROPERTIES
#define MBGL_STYLE_STYLE_PROPERTIES
-#include <mapbox/variant.hpp>
-
#include <mbgl/style/types.hpp>
#include <array>
#include <string>
-#include <type_traits>
-#include <memory>
#include <vector>
namespace mbgl {
@@ -169,22 +165,16 @@ public:
float opacity = 1.0f;
Color color = {{ 0, 0, 0, 1 }};
Faded<std::string> image;
+
+ inline bool isVisible() const {
+ return opacity > 0;
+ }
};
class BackgroundLayoutProperties {
public:
};
-typedef mapbox::util::variant<
- FillPaintProperties,
- LinePaintProperties,
- CirclePaintProperties,
- SymbolPaintProperties,
- RasterPaintProperties,
- BackgroundPaintProperties,
- std::false_type
-> StyleProperties;
-
}
#endif
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
index 78461462d1..cbc872313e 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/default/glfw_view.cpp
@@ -223,11 +223,8 @@ void GLFWView::addRandomPointAnnotations(int count) {
void GLFWView::addRandomShapeAnnotations(int count) {
std::vector<mbgl::ShapeAnnotation> shapes;
- mbgl::FillPaintProperties fillProperties;
- fillProperties.opacity = .1;
-
- mbgl::StyleProperties properties;
- properties.set<mbgl::FillPaintProperties>(fillProperties);
+ mbgl::FillPaintProperties properties;
+ properties.opacity = .1;
for (int i = 0; i < count; i++) {
mbgl::AnnotationSegment triangle;
diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm
index 4165cd3974..ffe91f15fe 100644
--- a/platform/ios/MGLMapView.mm
+++ b/platform/ios/MGLMapView.mm
@@ -2167,7 +2167,7 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng)
[strokeColor getRed:&r green:&g blue:&b alpha:&a];
mbgl::Color strokeNativeColor({{ (float)r, (float)g, (float)b, (float)a }});
- mbgl::StyleProperties shapeProperties;
+ mbgl::ShapeAnnotation::Properties shapeProperties;
if ([annotation isKindOfClass:[MGLPolyline class]])
{
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp
index 45fb1218f1..b8e9f973f2 100644
--- a/src/mbgl/annotation/annotation_manager.cpp
+++ b/src/mbgl/annotation/annotation_manager.cpp
@@ -2,7 +2,7 @@
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_bucket.hpp>
-#include <mbgl/style/style_layer.hpp>
+#include <mbgl/layer/symbol_layer.hpp>
#include <boost/function_output_iterator.hpp>
@@ -112,20 +112,19 @@ void AnnotationManager::updateStyle(Style& style) {
source->enabled = true;
style.addSource(std::move(source));
- std::map<ClassID, ClassProperties> pointPaints;
- pointPaints.emplace(ClassID::Default, ClassProperties());
- std::unique_ptr<StyleLayer> pointLayer = std::make_unique<StyleLayer>(PointLayerID, std::move(pointPaints));
- pointLayer->type = StyleLayerType::Symbol;
+ std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>();
+ layer->id = PointLayerID;
+ layer->type = StyleLayerType::Symbol;
+ layer->styles.emplace(ClassID::Default, ClassProperties());
- util::ptr<StyleBucket> pointBucket = std::make_shared<StyleBucket>(pointLayer->type);
- pointBucket->name = pointLayer->id;
- pointBucket->source = SourceID;
- pointBucket->source_layer = PointLayerID;
- pointBucket->layout.set(PropertyKey::IconImage, ConstantFunction<std::string>("{sprite}"));
- pointBucket->layout.set(PropertyKey::IconAllowOverlap, ConstantFunction<bool>(true));
+ layer->bucket = std::make_shared<StyleBucket>(layer->type);
+ layer->bucket->name = layer->id;
+ layer->bucket->source = SourceID;
+ layer->bucket->source_layer = PointLayerID;
+ layer->bucket->layout.set(PropertyKey::IconImage, ConstantFunction<std::string>("{sprite}"));
+ layer->bucket->layout.set(PropertyKey::IconAllowOverlap, ConstantFunction<bool>(true));
- pointLayer->bucket = pointBucket;
- style.addLayer(std::move(pointLayer));
+ style.addLayer(std::move(layer));
}
for (const auto& shape : shapeAnnotations) {
diff --git a/src/mbgl/annotation/shape_annotation_impl.cpp b/src/mbgl/annotation/shape_annotation_impl.cpp
index 74daf849ec..5b3c07fbc9 100644
--- a/src/mbgl/annotation/shape_annotation_impl.cpp
+++ b/src/mbgl/annotation/shape_annotation_impl.cpp
@@ -6,7 +6,8 @@
#include <mbgl/util/string.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_bucket.hpp>
-#include <mbgl/style/style_layer.hpp>
+#include <mbgl/layer/line_layer.hpp>
+#include <mbgl/layer/fill_layer.hpp>
namespace mbgl {
@@ -55,35 +56,47 @@ void ShapeAnnotationImpl::updateStyle(Style& style) {
if (style.getLayer(layerID))
return;
- ClassProperties paintProperties;
-
if (shape.styleProperties.is<LinePaintProperties>()) {
- const LinePaintProperties& lineProperties = shape.styleProperties.get<LinePaintProperties>();
- paintProperties.set(PropertyKey::LineOpacity, ConstantFunction<float>(lineProperties.opacity));
- paintProperties.set(PropertyKey::LineWidth, ConstantFunction<float>(lineProperties.width));
- paintProperties.set(PropertyKey::LineColor, ConstantFunction<Color>(lineProperties.color));
+ const LinePaintProperties& properties = shape.styleProperties.get<LinePaintProperties>();
+
+ std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>();
+ layer->id = layerID;
+ layer->type = StyleLayerType::Line;
+
+ ClassProperties paintProperties;
+ paintProperties.set(PropertyKey::LineOpacity, ConstantFunction<float>(properties.opacity));
+ paintProperties.set(PropertyKey::LineWidth, ConstantFunction<float>(properties.width));
+ paintProperties.set(PropertyKey::LineColor, ConstantFunction<Color>(properties.color));
+ layer->styles.emplace(ClassID::Default, std::move(paintProperties));
+
+ layer->bucket = std::make_shared<StyleBucket>(layer->type);
+ layer->bucket->name = layer->id;
+ layer->bucket->source = AnnotationManager::SourceID;
+ layer->bucket->source_layer = layer->id;
+ layer->bucket->layout.set(PropertyKey::LineJoin, ConstantFunction<JoinType>(JoinType::Round));
+
+ style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
+
} else if (shape.styleProperties.is<FillPaintProperties>()) {
- const FillPaintProperties& fillProperties = shape.styleProperties.get<FillPaintProperties>();
- paintProperties.set(PropertyKey::FillOpacity, ConstantFunction<float>(fillProperties.opacity));
- paintProperties.set(PropertyKey::FillColor, ConstantFunction<Color>(fillProperties.fill_color));
- paintProperties.set(PropertyKey::FillOutlineColor, ConstantFunction<Color>(fillProperties.stroke_color));
- }
+ const FillPaintProperties& properties = shape.styleProperties.get<FillPaintProperties>();
- std::map<ClassID, ClassProperties> shapePaints;
- shapePaints.emplace(ClassID::Default, std::move(paintProperties));
- std::unique_ptr<StyleLayer> shapeLayer = std::make_unique<StyleLayer>(layerID, std::move(shapePaints));
- shapeLayer->type = (shape.styleProperties.is<LinePaintProperties>() ? StyleLayerType::Line : StyleLayerType::Fill);
+ std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>();
+ layer->id = layerID;
+ layer->type = StyleLayerType::Fill;
- util::ptr<StyleBucket> shapeBucket = std::make_shared<StyleBucket>(shapeLayer->type);
- shapeBucket->name = shapeLayer->id;
- shapeBucket->source = AnnotationManager::SourceID;
- shapeBucket->source_layer = shapeLayer->id;
- if (shape.styleProperties.is<LinePaintProperties>()) {
- shapeBucket->layout.set(PropertyKey::LineJoin, ConstantFunction<JoinType>(JoinType::Round));
- }
+ ClassProperties paintProperties;
+ paintProperties.set(PropertyKey::FillOpacity, ConstantFunction<float>(properties.opacity));
+ paintProperties.set(PropertyKey::FillColor, ConstantFunction<Color>(properties.fill_color));
+ paintProperties.set(PropertyKey::FillOutlineColor, ConstantFunction<Color>(properties.stroke_color));
+ layer->styles.emplace(ClassID::Default, std::move(paintProperties));
- shapeLayer->bucket = shapeBucket;
- style.addLayer(std::move(shapeLayer), AnnotationManager::PointLayerID);
+ layer->bucket = std::make_shared<StyleBucket>(layer->type);
+ layer->bucket->name = layer->id;
+ layer->bucket->source = AnnotationManager::SourceID;
+ layer->bucket->source_layer = layer->id;
+
+ style.addLayer(std::move(layer), AnnotationManager::PointLayerID);
+ }
}
void ShapeAnnotationImpl::updateTile(const TileID& tileID, AnnotationTile& tile) {
diff --git a/src/mbgl/annotation/shape_annotation_impl.hpp b/src/mbgl/annotation/shape_annotation_impl.hpp
index 19eb05f89c..4cf6c23f61 100644
--- a/src/mbgl/annotation/shape_annotation_impl.hpp
+++ b/src/mbgl/annotation/shape_annotation_impl.hpp
@@ -6,6 +6,7 @@
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geojsonvt/geojsonvt.hpp>
+#include <memory>
#include <string>
#include <map>
diff --git a/src/mbgl/layer/background_layer.cpp b/src/mbgl/layer/background_layer.cpp
new file mode 100644
index 0000000000..c97124feb6
--- /dev/null
+++ b/src/mbgl/layer/background_layer.cpp
@@ -0,0 +1,12 @@
+#include <mbgl/layer/background_layer.hpp>
+
+namespace mbgl {
+
+RenderPass BackgroundLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, properties.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::BackgroundColor, properties.color, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::BackgroundImage, properties.image, z, now, zoomHistory);
+ return properties.isVisible() ? RenderPass::Translucent : RenderPass::None;
+}
+
+}
diff --git a/src/mbgl/layer/background_layer.hpp b/src/mbgl/layer/background_layer.hpp
new file mode 100644
index 0000000000..817c234239
--- /dev/null
+++ b/src/mbgl/layer/background_layer.hpp
@@ -0,0 +1,18 @@
+#ifndef MBGL_BACKGROUND_LAYER
+#define MBGL_BACKGROUND_LAYER
+
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/style_properties.hpp>
+
+namespace mbgl {
+
+class BackgroundLayer : public StyleLayer {
+public:
+ RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) override;
+
+ BackgroundPaintProperties properties;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/layer/circle_layer.cpp b/src/mbgl/layer/circle_layer.cpp
new file mode 100644
index 0000000000..384d56dfb8
--- /dev/null
+++ b/src/mbgl/layer/circle_layer.cpp
@@ -0,0 +1,15 @@
+#include <mbgl/layer/circle_layer.hpp>
+
+namespace mbgl {
+
+RenderPass CircleLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ applyTransitionedStyleProperty(PropertyKey::CircleRadius, properties.radius, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::CircleColor, properties.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::CircleOpacity, properties.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::CircleTranslate, properties.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::CircleTranslateAnchor, properties.translateAnchor, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::CircleBlur, properties.blur, z, now, zoomHistory);
+ return properties.isVisible() ? RenderPass::Translucent : RenderPass::None;
+}
+
+}
diff --git a/src/mbgl/layer/circle_layer.hpp b/src/mbgl/layer/circle_layer.hpp
new file mode 100644
index 0000000000..f3a1cf9733
--- /dev/null
+++ b/src/mbgl/layer/circle_layer.hpp
@@ -0,0 +1,18 @@
+#ifndef MBGL_CIRCLE_LAYER
+#define MBGL_CIRCLE_LAYER
+
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/style_properties.hpp>
+
+namespace mbgl {
+
+class CircleLayer : public StyleLayer {
+public:
+ RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) override;
+
+ CirclePaintProperties properties;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/layer/fill_layer.cpp b/src/mbgl/layer/fill_layer.cpp
new file mode 100644
index 0000000000..7a45774c2d
--- /dev/null
+++ b/src/mbgl/layer/fill_layer.cpp
@@ -0,0 +1,29 @@
+#include <mbgl/layer/fill_layer.hpp>
+
+namespace mbgl {
+
+RenderPass FillLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ applyStyleProperty(PropertyKey::FillAntialias, properties.antialias, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillOpacity, properties.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillColor, properties.fill_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillOutlineColor, properties.stroke_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillTranslate, properties.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::FillTranslateAnchor, properties.translateAnchor, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::FillImage, properties.image, z, now, zoomHistory);
+
+ RenderPass result = RenderPass::None;
+
+ if (properties.antialias) {
+ result |= RenderPass::Translucent;
+ }
+
+ if (!properties.image.from.empty() || (properties.fill_color[3] * properties.opacity) < 1.0f) {
+ result |= RenderPass::Translucent;
+ } else {
+ result |= RenderPass::Opaque;
+ }
+
+ return result;
+}
+
+}
diff --git a/src/mbgl/layer/fill_layer.hpp b/src/mbgl/layer/fill_layer.hpp
new file mode 100644
index 0000000000..d8e8e6d37a
--- /dev/null
+++ b/src/mbgl/layer/fill_layer.hpp
@@ -0,0 +1,18 @@
+#ifndef MBGL_FILL_LAYER
+#define MBGL_FILL_LAYER
+
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/style_properties.hpp>
+
+namespace mbgl {
+
+class FillLayer : public StyleLayer {
+public:
+ RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) override;
+
+ FillPaintProperties properties;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/layer/line_layer.cpp b/src/mbgl/layer/line_layer.cpp
new file mode 100644
index 0000000000..340f8fe7f4
--- /dev/null
+++ b/src/mbgl/layer/line_layer.cpp
@@ -0,0 +1,22 @@
+#include <mbgl/layer/line_layer.hpp>
+
+namespace mbgl {
+
+RenderPass LineLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ applyTransitionedStyleProperty(PropertyKey::LineOpacity, properties.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineColor, properties.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineTranslate, properties.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::LineTranslateAnchor, properties.translateAnchor, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineWidth, properties.width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineGapWidth, properties.gap_width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineBlur, properties.blur, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::LineDashArray, properties.dash_array, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::LineImage, properties.image, z, now, zoomHistory);
+
+ // for scaling dasharrays
+ applyStyleProperty(PropertyKey::LineWidth, properties.dash_line_width, std::floor(z), now, zoomHistory);
+
+ return properties.isVisible() ? RenderPass::Translucent : RenderPass::None;
+}
+
+}
diff --git a/src/mbgl/layer/line_layer.hpp b/src/mbgl/layer/line_layer.hpp
new file mode 100644
index 0000000000..9f59768c1f
--- /dev/null
+++ b/src/mbgl/layer/line_layer.hpp
@@ -0,0 +1,18 @@
+#ifndef MBGL_LINE_LAYER
+#define MBGL_LINE_LAYER
+
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/style_properties.hpp>
+
+namespace mbgl {
+
+class LineLayer : public StyleLayer {
+public:
+ RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) override;
+
+ LinePaintProperties properties;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/layer/raster_layer.cpp b/src/mbgl/layer/raster_layer.cpp
new file mode 100644
index 0000000000..2831483b82
--- /dev/null
+++ b/src/mbgl/layer/raster_layer.cpp
@@ -0,0 +1,16 @@
+#include <mbgl/layer/raster_layer.hpp>
+
+namespace mbgl {
+
+RenderPass RasterLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ applyTransitionedStyleProperty(PropertyKey::RasterOpacity, properties.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterHueRotate, properties.hue_rotate, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterBrightnessLow, properties.brightness[0], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterBrightnessHigh, properties.brightness[1], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterSaturation, properties.saturation, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterContrast, properties.contrast, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::RasterFade, properties.fade, z, now, zoomHistory);
+ return properties.isVisible() ? RenderPass::Translucent : RenderPass::None;
+}
+
+}
diff --git a/src/mbgl/layer/raster_layer.hpp b/src/mbgl/layer/raster_layer.hpp
new file mode 100644
index 0000000000..fc57a91717
--- /dev/null
+++ b/src/mbgl/layer/raster_layer.hpp
@@ -0,0 +1,18 @@
+#ifndef MBGL_RASTER_LAYER
+#define MBGL_RASTER_LAYER
+
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/style_properties.hpp>
+
+namespace mbgl {
+
+class RasterLayer : public StyleLayer {
+public:
+ RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) override;
+
+ RasterPaintProperties properties;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/layer/symbol_layer.cpp b/src/mbgl/layer/symbol_layer.cpp
new file mode 100644
index 0000000000..bdfa577ce7
--- /dev/null
+++ b/src/mbgl/layer/symbol_layer.cpp
@@ -0,0 +1,39 @@
+#include <mbgl/layer/symbol_layer.hpp>
+#include <mbgl/style/style_bucket.hpp>
+#include <mbgl/style/property_evaluator.hpp>
+
+namespace mbgl {
+
+RenderPass SymbolLayer::applyStyleProperties(const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ applyTransitionedStyleProperty(PropertyKey::IconOpacity, properties.icon.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconColor, properties.icon.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconHaloColor, properties.icon.halo_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconHaloWidth, properties.icon.halo_width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconHaloBlur, properties.icon.halo_blur, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconTranslate, properties.icon.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::IconTranslateAnchor, properties.icon.translate_anchor, z, now, zoomHistory);
+
+ applyTransitionedStyleProperty(PropertyKey::TextOpacity, properties.text.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextColor, properties.text.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextHaloColor, properties.text.halo_color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextHaloWidth, properties.text.halo_width, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextHaloBlur, properties.text.halo_blur, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextTranslate, properties.text.translate, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::TextTranslateAnchor, properties.text.translate_anchor, z, now, zoomHistory);
+
+ // text-size and icon-size are layout properties but they also need to be evaluated as paint properties:
+ auto it = bucket->layout.properties.find(PropertyKey::IconSize);
+ if (it != bucket->layout.properties.end()) {
+ const PropertyEvaluator<float> evaluator(z, zoomHistory);
+ properties.icon.size = mapbox::util::apply_visitor(evaluator, it->second);
+ }
+ it = bucket->layout.properties.find(PropertyKey::TextSize);
+ if (it != bucket->layout.properties.end()) {
+ const PropertyEvaluator<float> evaluator(z, zoomHistory);
+ properties.text.size = mapbox::util::apply_visitor(evaluator, it->second);
+ }
+
+ return properties.isVisible() ? RenderPass::Translucent : RenderPass::None;
+}
+
+}
diff --git a/src/mbgl/layer/symbol_layer.hpp b/src/mbgl/layer/symbol_layer.hpp
new file mode 100644
index 0000000000..ee25b00be7
--- /dev/null
+++ b/src/mbgl/layer/symbol_layer.hpp
@@ -0,0 +1,18 @@
+#ifndef MBGL_SYMBOL_LAYER
+#define MBGL_SYMBOL_LAYER
+
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/style_properties.hpp>
+
+namespace mbgl {
+
+class SymbolLayer : public StyleLayer {
+public:
+ RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) override;
+
+ SymbolPaintProperties properties;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/map/tile_worker.cpp
index acf8320093..c4a38c923d 100644
--- a/src/mbgl/map/tile_worker.cpp
+++ b/src/mbgl/map/tile_worker.cpp
@@ -2,6 +2,7 @@
#include <mbgl/map/tile_worker.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/property_evaluator.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/renderer/line_bucket.hpp>
@@ -64,29 +65,6 @@ void TileWorker::redoPlacement(float angle, float pitch, bool collisionDebug) {
}
template <typename T>
-struct PropertyEvaluator {
- typedef T result_type;
- explicit PropertyEvaluator(float z_) : z(z_) {}
-
- template <typename P, typename std::enable_if<std::is_convertible<P, T>::value, int>::type = 0>
- T operator()(const P &value) const {
- return value;
- }
-
- T operator()(const Function<T> &value) const {
- return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value);
- }
-
- template <typename P, typename std::enable_if<!std::is_convertible<P, T>::value, int>::type = 0>
- T operator()(const P &) const {
- return T();
- }
-
-private:
- const float z;
-};
-
-template <typename T>
void applyLayoutProperty(PropertyKey key, const ClassProperties &classProperties, T &target, const float z) {
auto it = classProperties.properties.find(key);
if (it != classProperties.properties.end()) {
diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp
index a9433eecbc..6187907a63 100644
--- a/src/mbgl/renderer/circle_bucket.cpp
+++ b/src/mbgl/renderer/circle_bucket.cpp
@@ -2,6 +2,7 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/shader/circle_shader.hpp>
+#include <mbgl/layer/circle_layer.hpp>
using namespace mbgl;
@@ -19,10 +20,10 @@ void CircleBucket::upload() {
}
void CircleBucket::render(Painter& painter,
- const StyleLayer& layer_desc,
+ const StyleLayer& layer,
const TileID& id,
const mat4& matrix) {
- painter.renderCircle(*this, layer_desc, id, matrix);
+ painter.renderCircle(*this, dynamic_cast<const CircleLayer&>(layer), id, matrix);
}
bool CircleBucket::hasData() const {
diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp
index 38582c0123..5b60be3c7c 100644
--- a/src/mbgl/renderer/fill_bucket.cpp
+++ b/src/mbgl/renderer/fill_bucket.cpp
@@ -1,5 +1,6 @@
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/geometry/fill_buffer.hpp>
+#include <mbgl/layer/fill_layer.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/renderer/painter.hpp>
#include <mbgl/style/style.hpp>
@@ -197,10 +198,10 @@ void FillBucket::upload() {
}
void FillBucket::render(Painter& painter,
- const StyleLayer& layer_desc,
+ const StyleLayer& layer,
const TileID& id,
const mat4& matrix) {
- painter.renderFill(*this, layer_desc, id, matrix);
+ painter.renderFill(*this, dynamic_cast<const FillLayer&>(layer), id, matrix);
}
bool FillBucket::hasData() const {
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index d2d7650d70..a7c3f00676 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -1,5 +1,5 @@
#include <mbgl/renderer/line_bucket.hpp>
-
+#include <mbgl/layer/line_layer.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/renderer/painter.hpp>
#include <mbgl/style/style.hpp>
@@ -388,10 +388,10 @@ void LineBucket::upload() {
}
void LineBucket::render(Painter& painter,
- const StyleLayer& layer_desc,
+ const StyleLayer& layer,
const TileID& id,
const mat4& matrix) {
- painter.renderLine(*this, layer_desc, id, matrix);
+ painter.renderLine(*this, dynamic_cast<const LineLayer&>(layer), id, matrix);
}
bool LineBucket::hasData() const {
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index d5dfed4421..a7ffd82698 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -12,6 +12,8 @@
#include <mbgl/style/style_layer.hpp>
#include <mbgl/style/style_bucket.hpp>
+#include <mbgl/layer/background_layer.hpp>
+
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
@@ -286,7 +288,7 @@ void Painter::renderPass(RenderPass pass_,
}
} else {
MBGL_DEBUG_GROUP("background");
- renderBackground(item.layer);
+ renderBackground(dynamic_cast<const BackgroundLayer&>(item.layer));
}
}
@@ -303,20 +305,18 @@ std::vector<RenderItem> Painter::determineRenderOrder(const Style& style) {
if (layer.bucket->visibility == VisibilityType::None) continue;
if (layer.type == StyleLayerType::Background) {
// This layer defines a background color/image.
- if (layer.properties.is<BackgroundPaintProperties>()) {
- auto& props = layer.properties.get<BackgroundPaintProperties>();
- if (props.image.from.empty()) {
- // This is a solid background. We can use glClear().
- background = props.color;
- background[0] *= props.opacity;
- background[1] *= props.opacity;
- background[2] *= props.opacity;
- background[3] *= props.opacity;
- } else {
- // This is a textured background. We need to render it with a quad.
- background = {{ 0, 0, 0, 0 }};
- order.emplace_back(layer);
- }
+ auto& props = dynamic_cast<const BackgroundLayer&>(layer).properties;
+ if (props.image.from.empty()) {
+ // This is a solid background. We can use glClear().
+ background = props.color;
+ background[0] *= props.opacity;
+ background[1] *= props.opacity;
+ background[2] *= props.opacity;
+ background[3] *= props.opacity;
+ } else {
+ // This is a textured background. We need to render it with a quad.
+ background = {{ 0, 0, 0, 0 }};
+ order.emplace_back(layer);
}
continue;
}
@@ -378,10 +378,10 @@ std::vector<RenderItem> Painter::determineRenderOrder(const Style& style) {
return order;
}
-void Painter::renderBackground(const StyleLayer &layer_desc) {
+void Painter::renderBackground(const BackgroundLayer& layer) {
// Note: This function is only called for textured background. Otherwise, the background color
// is created with glClear.
- const BackgroundPaintProperties& properties = layer_desc.getProperties<BackgroundPaintProperties>();
+ const BackgroundPaintProperties& properties = layer.properties;
if (!properties.image.to.empty()) {
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index dbe575985f..b7402d69b6 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -37,10 +37,16 @@ struct FrameData;
class DebugBucket;
class FillBucket;
+class FillLayer;
class LineBucket;
+class LineLayer;
class CircleBucket;
+class CircleLayer;
class SymbolBucket;
+class SymbolLayer;
class RasterBucket;
+class RasterLayer;
+class BackgroundLayer;
struct RasterProperties;
@@ -96,13 +102,13 @@ public:
// Renders the red debug frame around a tile, visualizing its perimeter.
void renderDebugFrame(const mat4 &matrix);
- void renderDebugText(DebugBucket& bucket, const mat4 &matrix);
- void renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
- void renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
- void renderCircle(CircleBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
- void renderSymbol(SymbolBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
- void renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
- void renderBackground(const StyleLayer &layer_desc);
+ void renderDebugText(DebugBucket&, const mat4&);
+ void renderFill(FillBucket&, const FillLayer&, const TileID&, const mat4&);
+ void renderLine(LineBucket&, const LineLayer&, const TileID&, const mat4&);
+ void renderCircle(CircleBucket&, const CircleLayer&, const TileID&, const mat4&);
+ void renderSymbol(SymbolBucket&, const SymbolLayer&, const TileID&, const mat4&);
+ void renderRaster(RasterBucket&, const RasterLayer&, const TileID&, const mat4&);
+ void renderBackground(const BackgroundLayer&);
float saturationFactor(float saturation);
float contrastFactor(float contrast);
diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp
index a7aa6ac455..cb0fe0baad 100644
--- a/src/mbgl/renderer/painter_circle.cpp
+++ b/src/mbgl/renderer/painter_circle.cpp
@@ -1,9 +1,7 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/circle_bucket.hpp>
-#include <mbgl/style/style.hpp>
-#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_properties.hpp>
+#include <mbgl/layer/circle_layer.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/map/tile_id.hpp>
@@ -14,7 +12,7 @@
using namespace mbgl;
void Painter::renderCircle(CircleBucket& bucket,
- const StyleLayer& layer_desc,
+ const CircleLayer& layer,
const TileID& id,
const mat4& matrix) {
// Abort early.
@@ -22,7 +20,7 @@ void Painter::renderCircle(CircleBucket& bucket,
config.stencilTest = false;
- const CirclePaintProperties& properties = layer_desc.getProperties<CirclePaintProperties>();
+ const CirclePaintProperties& properties = layer.properties;
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
Color color = properties.color;
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index 33fc14a0dc..b4247d6d91 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -1,8 +1,6 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/fill_bucket.hpp>
-#include <mbgl/style/style.hpp>
-#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_properties.hpp>
+#include <mbgl/layer/fill_layer.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/map/tile_id.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
@@ -13,8 +11,8 @@
using namespace mbgl;
-void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix) {
- const FillPaintProperties& properties = layer_desc.getProperties<FillPaintProperties>();
+void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileID& id, const mat4& matrix) {
+ const FillPaintProperties& properties = layer.properties;
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
Color fill_color = properties.fill_color;
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index fdbe690f72..945022280a 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -1,8 +1,6 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/line_bucket.hpp>
-#include <mbgl/style/style.hpp>
-#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_properties.hpp>
+#include <mbgl/layer/line_layer.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/map/tile_id.hpp>
#include <mbgl/map/map_data.hpp>
@@ -15,7 +13,7 @@
using namespace mbgl;
-void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix) {
+void Painter::renderLine(LineBucket& bucket, const LineLayer& layer, const TileID& id, const mat4& matrix) {
// Abort early.
if (pass == RenderPass::Opaque) return;
@@ -23,7 +21,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
config.depthTest = true;
config.depthMask = GL_FALSE;
- const auto& properties = layer_desc.getProperties<LinePaintProperties>();
+ const auto& properties = layer.properties;
const auto& layout = bucket.layout;
// the distance over which the line edge fades out.
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index f052563187..80730113a1 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -1,15 +1,15 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/platform/gl.hpp>
#include <mbgl/renderer/raster_bucket.hpp>
-#include <mbgl/style/style_layer.hpp>
+#include <mbgl/layer/raster_layer.hpp>
#include <mbgl/shader/raster_shader.hpp>
using namespace mbgl;
-void Painter::renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, const TileID&, const mat4 &matrix) {
+void Painter::renderRaster(RasterBucket& bucket, const RasterLayer& layer, const TileID&, const mat4& matrix) {
if (pass != RenderPass::Translucent) return;
- const RasterPaintProperties& properties = layer_desc.getProperties<RasterPaintProperties>();
+ const RasterPaintProperties& properties = layer.properties;
if (bucket.hasData()) {
useProgram(rasterShader->program);
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index f1ebef3989..1ad8c64e8d 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -1,7 +1,6 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/symbol_bucket.hpp>
-#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_properties.hpp>
+#include <mbgl/layer/symbol_layer.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
#include <mbgl/shader/sdf_shader.hpp>
@@ -126,13 +125,13 @@ void Painter::renderSDF(SymbolBucket &bucket,
}
}
-void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, const TileID &id, const mat4 &matrix) {
+void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const TileID& id, const mat4& matrix) {
// Abort early.
if (pass == RenderPass::Opaque) {
return;
}
- const auto& properties = layer_desc.getProperties<SymbolPaintProperties>();
+ const auto& properties = layer.properties;
const auto& layout = bucket.layout;
config.depthMask = GL_FALSE;
diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp
index 9f28dfd324..d9146f0e88 100644
--- a/src/mbgl/renderer/raster_bucket.cpp
+++ b/src/mbgl/renderer/raster_bucket.cpp
@@ -1,4 +1,5 @@
#include <mbgl/renderer/raster_bucket.hpp>
+#include <mbgl/layer/raster_layer.hpp>
#include <mbgl/shader/raster_shader.hpp>
#include <mbgl/renderer/painter.hpp>
@@ -17,10 +18,10 @@ void RasterBucket::upload() {
}
void RasterBucket::render(Painter& painter,
- const StyleLayer& layer_desc,
+ const StyleLayer& layer,
const TileID& id,
const mat4& matrix) {
- painter.renderRaster(*this, layer_desc, id, matrix);
+ painter.renderRaster(*this, dynamic_cast<const RasterLayer&>(layer), id, matrix);
}
bool RasterBucket::setImage(std::unique_ptr<util::Image> image) {
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index a56a926b77..d769060c6e 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -1,4 +1,5 @@
#include <mbgl/renderer/symbol_bucket.hpp>
+#include <mbgl/layer/symbol_layer.hpp>
#include <mbgl/map/geometry_tile.hpp>
#include <mbgl/style/style_properties.hpp>
#include <mbgl/annotation/sprite_image.hpp>
@@ -75,10 +76,10 @@ void SymbolBucket::upload() {
}
void SymbolBucket::render(Painter& painter,
- const StyleLayer& layer_desc,
+ const StyleLayer& layer,
const TileID& id,
const mat4& matrix) {
- painter.renderSymbol(*this, layer_desc, id, matrix);
+ painter.renderSymbol(*this, dynamic_cast<const SymbolLayer&>(layer), id, matrix);
}
bool SymbolBucket::hasData() const { return hasTextData() || hasIconData() || !symbolInstances.empty(); }
diff --git a/src/mbgl/style/property_evaluator.hpp b/src/mbgl/style/property_evaluator.hpp
new file mode 100644
index 0000000000..7856c90f49
--- /dev/null
+++ b/src/mbgl/style/property_evaluator.hpp
@@ -0,0 +1,45 @@
+#ifndef MBGL_PROPERTY_EVALUATOR
+#define MBGL_PROPERTY_EVALUATOR
+
+#include <mbgl/style/zoom_history.hpp>
+#include <mbgl/style/function_properties.hpp>
+#include <mbgl/style/piecewisefunction_properties.hpp>
+
+namespace mbgl {
+
+struct ZoomHistory;
+
+template <typename T>
+class PropertyEvaluator {
+public:
+ typedef T result_type;
+
+ PropertyEvaluator(float z_) : z(z_), zoomHistory() {}
+ PropertyEvaluator(float z_, const ZoomHistory& zoomHistory_) : z(z_), zoomHistory(zoomHistory_) {}
+
+ template <typename P, typename std::enable_if<std::is_convertible<P, T>::value, int>::type = 0>
+ T operator()(const P &value) const {
+ return value;
+ }
+
+ T operator()(const Function<T>& value) const {
+ return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value);
+ }
+
+ T operator()(const PiecewiseConstantFunction<T>& value) const {
+ return value.evaluate(z, zoomHistory);
+ }
+
+ template <typename P, typename std::enable_if<!std::is_convertible<P, T>::value, int>::type = 0>
+ T operator()(const P &) const {
+ return T();
+ }
+
+private:
+ const float z;
+ ZoomHistory zoomHistory;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp
index 17c6fa9386..e6b3ee5bd9 100644
--- a/src/mbgl/style/style_layer.cpp
+++ b/src/mbgl/style/style_layer.cpp
@@ -1,35 +1,38 @@
#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_bucket.hpp>
#include <mbgl/style/property_fallback.hpp>
-#include <mbgl/util/interpolate.hpp>
+#include <mbgl/layer/fill_layer.hpp>
+#include <mbgl/layer/line_layer.hpp>
+#include <mbgl/layer/circle_layer.hpp>
+#include <mbgl/layer/symbol_layer.hpp>
+#include <mbgl/layer/raster_layer.hpp>
+#include <mbgl/layer/background_layer.hpp>
namespace mbgl {
-StyleLayer::StyleLayer(const std::string &id_, std::map<ClassID, ClassProperties> &&styles_)
- : id(id_), styles(std::move(styles_)) {}
+std::unique_ptr<StyleLayer> StyleLayer::create(StyleLayerType type) {
+ switch (type) {
+ case StyleLayerType::Fill:
+ return std::make_unique<FillLayer>();
+ case StyleLayerType::Line:
+ return std::make_unique<LineLayer>();
+ case StyleLayerType::Circle:
+ return std::make_unique<CircleLayer>();
+ case StyleLayerType::Symbol:
+ return std::make_unique<SymbolLayer>();
+ case StyleLayerType::Raster:
+ return std::make_unique<RasterLayer>();
+ case StyleLayerType::Background:
+ return std::make_unique<BackgroundLayer>();
+ default:
+ return nullptr;
+ }
+}
bool StyleLayer::isBackground() const {
return type == StyleLayerType::Background;
}
-bool StyleLayer::isVisible() const {
- switch (type) {
- case StyleLayerType::Fill:
- return getProperties<FillPaintProperties>().isVisible();
- case StyleLayerType::Line:
- return getProperties<LinePaintProperties>().isVisible();
- case StyleLayerType::Circle:
- return getProperties<CirclePaintProperties>().isVisible();
- case StyleLayerType::Symbol:
- return getProperties<SymbolPaintProperties>().isVisible();
- case StyleLayerType::Raster:
- return getProperties<RasterPaintProperties>().isVisible();
- default:
- return false;
- }
-}
-
bool StyleLayer::hasRenderPass(RenderPass pass) const {
return bool(passes & pass);
}
@@ -119,208 +122,14 @@ void StyleLayer::applyClassProperties(const ClassID class_id,
}
}
-template <typename T>
-struct PropertyEvaluator {
- typedef T result_type;
- PropertyEvaluator(float z_, const ZoomHistory &zoomHistory_) : z(z_), zoomHistory(zoomHistory_) {}
-
- template <typename P, typename std::enable_if<std::is_convertible<P, T>::value, int>::type = 0>
- T operator()(const P &value) const {
- return value;
- }
-
- T operator()(const Function<T> &value) const {
- return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value);
- }
-
- T operator()(const PiecewiseConstantFunction<T> &value) const {
- return value.evaluate(z, zoomHistory);
- }
-
- template <typename P, typename std::enable_if<!std::is_convertible<P, T>::value, int>::type = 0>
- T operator()(const P &) const {
- return T();
- }
-
-private:
- const float z;
- const ZoomHistory &zoomHistory;
-};
-
-template <typename T>
-void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- auto it = appliedStyle.find(key);
- if (it != appliedStyle.end()) {
- AppliedClassPropertyValues &applied = it->second;
- // Iterate through all properties that we need to apply in order.
- const PropertyEvaluator<T> evaluator(z, zoomHistory);
- for (auto& property : applied.propertyValues) {
- if (now >= property.begin) {
- // We overwrite the current property with the new value.
- target = mapbox::util::apply_visitor(evaluator, property.value);
- } else {
- // Do not apply this property because its transition hasn't begun yet.
- }
- }
- }
-}
-
-template <typename T>
-void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- auto it = appliedStyle.find(key);
- if (it != appliedStyle.end()) {
- AppliedClassPropertyValues &applied = it->second;
- // Iterate through all properties that we need to apply in order.
- const PropertyEvaluator<T> evaluator(z, zoomHistory);
- for (auto& property : applied.propertyValues) {
- if (now >= property.end) {
- // We overwrite the current property with the new value.
- target = mapbox::util::apply_visitor(evaluator, property.value);
- } else if (now >= property.begin) {
- // We overwrite the current property partially with the new value.
- float progress = std::chrono::duration<float>(now - property.begin) / (property.end - property.begin);
- target = util::interpolate(target, mapbox::util::apply_visitor(evaluator, property.value), progress);
- hasPendingTransitions = true;
- } else {
- // Do not apply this property because its transition hasn't begun yet.
- }
- }
- }
-}
-
-template <>
-void StyleLayer::applyStyleProperties<FillPaintProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- properties.set<FillPaintProperties>();
- FillPaintProperties& fill = properties.get<FillPaintProperties>();
- applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::FillOutlineColor, fill.stroke_color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::FillTranslate, fill.translate, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::FillTranslateAnchor, fill.translateAnchor, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::FillImage, fill.image, z, now, zoomHistory);
-}
-
-template <>
-void StyleLayer::applyStyleProperties<LinePaintProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- properties.set<LinePaintProperties>();
- LinePaintProperties& line = properties.get<LinePaintProperties>();
- applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::LineColor, line.color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::LineTranslate, line.translate, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::LineTranslateAnchor, line.translateAnchor, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::LineImage, line.image, z, now, zoomHistory);
-
- // for scaling dasharrays
- applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), now, zoomHistory);
-}
-
-template <>
-void StyleLayer::applyStyleProperties<CirclePaintProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- properties.set<CirclePaintProperties>();
- CirclePaintProperties& circle = properties.get<CirclePaintProperties>();
- applyTransitionedStyleProperty(PropertyKey::CircleRadius, circle.radius, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::CircleColor, circle.color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::CircleOpacity, circle.opacity, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::CircleTranslate, circle.translate, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::CircleTranslateAnchor, circle.translateAnchor, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::CircleBlur, circle.blur, z, now, zoomHistory);
-}
-
-template <>
-void StyleLayer::applyStyleProperties<SymbolPaintProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- properties.set<SymbolPaintProperties>();
- SymbolPaintProperties& symbol = properties.get<SymbolPaintProperties>();
- applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::IconColor, symbol.icon.color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::IconHaloColor, symbol.icon.halo_color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::IconHaloWidth, symbol.icon.halo_width, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::IconHaloBlur, symbol.icon.halo_blur, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::IconTranslate, symbol.icon.translate, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now, zoomHistory);
-
- applyTransitionedStyleProperty(PropertyKey::TextOpacity, symbol.text.opacity, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::TextColor, symbol.text.color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::TextHaloColor, symbol.text.halo_color, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::TextHaloWidth, symbol.text.halo_width, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::TextHaloBlur, symbol.text.halo_blur, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::TextTranslate, symbol.text.translate, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::TextTranslateAnchor, symbol.text.translate_anchor, z, now, zoomHistory);
-
- // text-size and icon-size are layout properties but they also need to be evaluated as paint properties:
- auto it = bucket->layout.properties.find(PropertyKey::IconSize);
- if (it != bucket->layout.properties.end()) {
- const PropertyEvaluator<float> evaluator(z, zoomHistory);
- symbol.icon.size = mapbox::util::apply_visitor(evaluator, it->second);
- }
- it = bucket->layout.properties.find(PropertyKey::TextSize);
- if (it != bucket->layout.properties.end()) {
- const PropertyEvaluator<float> evaluator(z, zoomHistory);
- symbol.text.size = mapbox::util::apply_visitor(evaluator, it->second);
- }
-}
-
-template <>
-void StyleLayer::applyStyleProperties<RasterPaintProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- properties.set<RasterPaintProperties>();
- RasterPaintProperties& raster = properties.get<RasterPaintProperties>();
- applyTransitionedStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::RasterHueRotate, raster.hue_rotate, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::RasterBrightnessHigh, raster.brightness[1], z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::RasterSaturation, raster.saturation, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::RasterContrast, raster.contrast, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::RasterFade, raster.fade, z, now, zoomHistory);
-}
-
-template <>
-void StyleLayer::applyStyleProperties<BackgroundPaintProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
- properties.set<BackgroundPaintProperties>();
- BackgroundPaintProperties& background = properties.get<BackgroundPaintProperties>();
- applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now, zoomHistory);
- applyTransitionedStyleProperty(PropertyKey::BackgroundColor, background.color, z, now, zoomHistory);
- applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now, zoomHistory);
-}
-
void StyleLayer::updateProperties(float z, const TimePoint& now, ZoomHistory &zoomHistory) {
cleanupAppliedStyleProperties(now);
// Clear the pending transitions flag upon each update.
hasPendingTransitions = false;
- switch (type) {
- case StyleLayerType::Fill: applyStyleProperties<FillPaintProperties>(z, now, zoomHistory); break;
- case StyleLayerType::Line: applyStyleProperties<LinePaintProperties>(z, now, zoomHistory); break;
- case StyleLayerType::Circle: applyStyleProperties<CirclePaintProperties>(z, now, zoomHistory); break;
- case StyleLayerType::Symbol: applyStyleProperties<SymbolPaintProperties>(z, now, zoomHistory); break;
- case StyleLayerType::Raster: applyStyleProperties<RasterPaintProperties>(z, now, zoomHistory); break;
- case StyleLayerType::Background: applyStyleProperties<BackgroundPaintProperties>(z, now, zoomHistory); break;
- default: properties.set<std::false_type>(); break;
- }
-
// Update the render passes when this layer is visible.
- passes = RenderPass::None;
- if (isVisible()) {
- if (properties.is<FillPaintProperties>()) {
- const FillPaintProperties &fillProperties = properties.get<FillPaintProperties>();
- const float alpha = fillProperties.fill_color[3] * fillProperties.opacity;
-
- if (fillProperties.antialias) {
- passes |= RenderPass::Translucent;
- }
- if (!fillProperties.image.from.empty() || alpha < 1.0f) {
- passes |= RenderPass::Translucent;
- } else {
- passes |= RenderPass::Opaque;
- }
- } else {
- passes |= RenderPass::Translucent;
- }
- }
+ passes = applyStyleProperties(z, now, zoomHistory);
}
bool StyleLayer::hasTransitions() const {
diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp
index fdba827645..d44b2ce7cc 100644
--- a/src/mbgl/style/style_layer.hpp
+++ b/src/mbgl/style/style_layer.hpp
@@ -3,15 +3,16 @@
#include <mbgl/style/class_dictionary.hpp>
#include <mbgl/style/class_properties.hpp>
-#include <mbgl/style/style_properties.hpp>
#include <mbgl/style/applied_class_properties.hpp>
#include <mbgl/style/zoom_history.hpp>
+#include <mbgl/style/property_evaluator.hpp>
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/util/ptr.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/interpolate.hpp>
#include <vector>
#include <string>
@@ -24,16 +25,13 @@ class StyleBucket;
class StyleLayer : public util::noncopyable {
public:
- StyleLayer(const std::string &id, std::map<ClassID, ClassProperties> &&styles);
+ static std::unique_ptr<StyleLayer> create(StyleLayerType);
- template <typename T> const T& getProperties() const {
- return properties.get<T>();
- }
+ virtual ~StyleLayer() = default;
// Determines whether this layer is the background layer.
bool isBackground() const;
-public:
// Checks whether this layer needs to be rendered in the given render pass.
bool hasRenderPass(RenderPass) const;
@@ -47,37 +45,74 @@ public:
bool hasTransitions() const;
-private:
- // Applies all properties from a class, if they haven't been applied already.
- void applyClassProperties(ClassID class_id, std::set<PropertyKey> &already_applied,
- const TimePoint& now, const PropertyTransition &defaultTransition);
-
- // Sets the properties of this object by evaluating all pending transitions and
- // aplied classes in order.
- template <typename T> void applyStyleProperties(float z, const TimePoint& now, const ZoomHistory &zoomHistory);
- template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, const TimePoint& now, const ZoomHistory &zoomHistory);
- template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, const TimePoint& now, const ZoomHistory &zoomHistory);
-
- // Removes all expired style transitions.
- void cleanupAppliedStyleProperties(const TimePoint& now);
-
- // Checks whether the layer is currently visible at all.
- bool isVisible() const;
-
public:
// The name of this layer.
- const std::string id;
+ std::string id;
StyleLayerType type = StyleLayerType::Unknown;
// Bucket information, telling the renderer how to generate the geometries
// for this layer (feature property filters, tessellation instructions, ...).
- util::ptr<const StyleBucket> bucket;
+ util::ptr<StyleBucket> bucket;
// Contains all style classes that can be applied to this layer.
- const std::map<ClassID, ClassProperties> styles;
+ std::map<ClassID, ClassProperties> styles;
+
+protected:
+ // TODO: extract
+ template <typename T>
+ void applyStyleProperty(PropertyKey key, T& target, const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ auto it = appliedStyle.find(key);
+ if (it != appliedStyle.end()) {
+ AppliedClassPropertyValues &applied = it->second;
+ // Iterate through all properties that we need to apply in order.
+ const PropertyEvaluator<T> evaluator(z, zoomHistory);
+ for (auto& property : applied.propertyValues) {
+ if (now >= property.begin) {
+ // We overwrite the current property with the new value.
+ target = mapbox::util::apply_visitor(evaluator, property.value);
+ } else {
+ // Do not apply this property because its transition hasn't begun yet.
+ }
+ }
+ }
+ }
+
+ template <typename T>
+ void applyTransitionedStyleProperty(PropertyKey key, T& target, const float z, const TimePoint& now, const ZoomHistory& zoomHistory) {
+ auto it = appliedStyle.find(key);
+ if (it != appliedStyle.end()) {
+ AppliedClassPropertyValues &applied = it->second;
+ // Iterate through all properties that we need to apply in order.
+ const PropertyEvaluator<T> evaluator(z, zoomHistory);
+ for (auto& property : applied.propertyValues) {
+ if (now >= property.end) {
+ // We overwrite the current property with the new value.
+ target = mapbox::util::apply_visitor(evaluator, property.value);
+ } else if (now >= property.begin) {
+ // We overwrite the current property partially with the new value.
+ float progress = std::chrono::duration<float>(now - property.begin) / (property.end - property.begin);
+ target = util::interpolate(target, mapbox::util::apply_visitor(evaluator, property.value), progress);
+ hasPendingTransitions = true;
+ } else {
+ // Do not apply this property because its transition hasn't begun yet.
+ }
+ }
+ }
+ }
private:
+ // Applies all properties from a class, if they haven't been applied already.
+ void applyClassProperties(ClassID class_id, std::set<PropertyKey> &already_applied,
+ const TimePoint& now, const PropertyTransition &defaultTransition);
+
+ // Sets the properties of this object by evaluating all pending transitions and
+ // aplied classes in order.
+ virtual RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) = 0;
+
+ // Removes all expired style transitions.
+ void cleanupAppliedStyleProperties(const TimePoint& now);
+
// For every property, stores a list of applied property values, with
// optional transition times.
std::map<PropertyKey, AppliedClassPropertyValues> appliedStyle;
@@ -86,12 +121,6 @@ private:
// evaluated StyleProperties object and is updated accordingly.
RenderPass passes = RenderPass::None;
-public:
- // Stores the evaluated, and cascaded styling information, specific to this
- // layer's type.
- StyleProperties properties;
-
-private:
// Stores whether there are pending transitions to be done on each update.
bool hasPendingTransitions = false;
};
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp
index fac5306601..538015ead4 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/style_parser.cpp
@@ -632,6 +632,8 @@ template<> StyleParser::Result<PiecewiseConstantFunction<Faded<std::string>>> St
#pragma mark - Parse Layers
void StyleParser::parseLayers(JSVal value) {
+ std::vector<std::string> ids;
+
if (!value.IsArray()) {
Log::Warning(Event::ParseStyle, "layers must be an array");
return;
@@ -662,53 +664,151 @@ void StyleParser::parseLayers(JSVal value) {
continue;
}
- // Parse paints already, as they can't be inherited anyway.
- std::map<ClassID, ClassProperties> paints;
- parsePaints(layerValue, paints);
-
- util::ptr<StyleLayer> layer = std::make_shared<StyleLayer>(layerID, std::move(paints));
-
- layers.emplace_back(layer);
- layersMap.emplace(layerID, std::pair<JSVal, util::ptr<StyleLayer>> { layerValue, layer });
+ layersMap.emplace(layerID, std::pair<JSVal, util::ptr<StyleLayer>> { layerValue, nullptr });
+ ids.push_back(layerID);
}
- for (auto& pair : layersMap) {
- parseLayer(pair.second);
- }
-}
+ for (const auto& id : ids) {
+ auto it = layersMap.find(id);
-void StyleParser::parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair) {
- JSVal value = pair.first;
- util::ptr<StyleLayer> &layer = pair.second;
+ parseLayer(it->first,
+ it->second.first,
+ it->second.second);
- if (value.HasMember("type")) {
- JSVal type = value["type"];
- if (!type.IsString()) {
- Log::Warning(Event::ParseStyle, "layer type of '%s' must be a string", layer->id.c_str());
- } else {
- layer->type = StyleLayerTypeClass(std::string { type.GetString(), type.GetStringLength() });
+ if (it->second.second) {
+ layers.emplace_back(it->second.second);
}
}
+}
- if (layer->bucket) {
+void StyleParser::parseLayer(const std::string& id, JSVal value, util::ptr<StyleLayer>& layer) {
+ if (layer) {
// Skip parsing this again. We already have a valid layer definition.
return;
}
// Make sure we have not previously attempted to parse this layer.
- if (std::find(stack.begin(), stack.end(), layer.get()) != stack.end()) {
- Log::Warning(Event::ParseStyle, "layer reference of '%s' is circular", layer->id.c_str());
+ if (std::find(stack.begin(), stack.end(), id) != stack.end()) {
+ Log::Warning(Event::ParseStyle, "layer reference of '%s' is circular", id.c_str());
return;
}
if (value.HasMember("ref")) {
- // This layer is referencing another layer. Inherit the bucket from that layer, if we
- // already parsed it.
- parseReference(value["ref"], layer);
+ // This layer is referencing another layer. Recursively parse that layer.
+ JSVal refVal = value["ref"];
+ if (!refVal.IsString()) {
+ Log::Warning(Event::ParseStyle, "layer ref of '%s' must be a string", id.c_str());
+ return;
+ }
+
+ const std::string ref { refVal.GetString(), refVal.GetStringLength() };
+ auto it = layersMap.find(ref);
+ if (it == layersMap.end()) {
+ Log::Warning(Event::ParseStyle, "layer '%s' references unknown layer %s", id.c_str(), ref.c_str());
+ return;
+ }
+
+ // Recursively parse the referenced layer.
+ stack.push_front(id);
+ parseLayer(it->first,
+ it->second.first,
+ it->second.second);
+ stack.pop_front();
+
+ util::ptr<StyleLayer> reference = it->second.second;
+ if (!reference) {
+ return;
+ }
+
+ layer = StyleLayer::create(reference->type);
+ layer->id = id;
+ layer->type = reference->type;
+ layer->bucket = reference->bucket;
+
} else {
// Otherwise, parse the source/source-layer/filter/render keys to form the bucket.
- parseBucket(value, layer);
+ if (!value.HasMember("type")) {
+ Log::Warning(Event::ParseStyle, "layer '%s' is missing a type", id.c_str());
+ return;
+ }
+
+ JSVal typeVal = value["type"];
+ if (!typeVal.IsString()) {
+ Log::Warning(Event::ParseStyle, "layer '%s' has an invalid type", id.c_str());
+ return;
+ }
+
+ std::string type { typeVal.GetString(), typeVal.GetStringLength() };
+ StyleLayerType typeClass = StyleLayerTypeClass(type);
+ layer = StyleLayer::create(typeClass);
+
+ if (!layer) {
+ Log::Warning(Event::ParseStyle, "unknown type '%s' for layer '%s'", type.c_str(), id.c_str());
+ return;
+ }
+
+ layer->id = id;
+ layer->type = typeClass;
+
+ util::ptr<StyleBucket> bucket = std::make_shared<StyleBucket>(layer->type);
+
+ // We name the buckets according to the layer that defined it.
+ bucket->name = layer->id;
+
+ if (value.HasMember("source")) {
+ JSVal value_source = value["source"];
+ if (value_source.IsString()) {
+ bucket->source = { value_source.GetString(), value_source.GetStringLength() };
+ auto source_it = sourcesMap.find(bucket->source);
+ if (source_it == sourcesMap.end()) {
+ Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", bucket->source.c_str(), layer->id.c_str());
+ }
+ } else {
+ Log::Warning(Event::ParseStyle, "source of layer '%s' must be a string", layer->id.c_str());
+ }
+ }
+
+ if (value.HasMember("source-layer")) {
+ JSVal value_source_layer = value["source-layer"];
+ if (value_source_layer.IsString()) {
+ bucket->source_layer = { value_source_layer.GetString(), value_source_layer.GetStringLength() };
+ } else {
+ Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", layer->id.c_str());
+ }
+ }
+
+ if (value.HasMember("filter")) {
+ bucket->filter = parseFilterExpression(value["filter"]);
+ }
+
+ if (value.HasMember("layout")) {
+ parseLayout(value["layout"], bucket);
+ }
+
+ if (value.HasMember("minzoom")) {
+ JSVal min_zoom = value["minzoom"];
+ if (min_zoom.IsNumber()) {
+ bucket->min_zoom = min_zoom.GetDouble();
+ } else {
+ Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", layer->id.c_str());
+ }
+ }
+
+ if (value.HasMember("maxzoom")) {
+ JSVal max_zoom = value["maxzoom"];
+ if (max_zoom.IsNumber()) {
+ bucket->max_zoom = max_zoom.GetDouble();
+ } else {
+ Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", layer->id.c_str());
+ }
+ }
+
+ layer->bucket = bucket;
}
+
+ std::map<ClassID, ClassProperties> paints;
+ parsePaints(value, paints);
+ layer->styles = std::move(paints);
}
#pragma mark - Parse Styles
@@ -860,88 +960,6 @@ void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
}
-void StyleParser::parseReference(JSVal value, util::ptr<StyleLayer> &layer) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "layer ref of '%s' must be a string", layer->id.c_str());
- return;
- }
- const std::string ref { value.GetString(), value.GetStringLength() };
- auto it = layersMap.find(ref);
- if (it == layersMap.end()) {
- Log::Warning(Event::ParseStyle, "layer '%s' references unknown layer %s", layer->id.c_str(), ref.c_str());
- // We cannot parse this layer further.
- return;
- }
-
- // Recursively parse the referenced layer.
- stack.push_front(layer.get());
- parseLayer(it->second);
- stack.pop_front();
-
- util::ptr<StyleLayer> reference = it->second.second;
- layer->type = reference->type;
- layer->bucket = reference->bucket;
-}
-
-#pragma mark - Parse Bucket
-
-void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
- util::ptr<StyleBucket> bucket = std::make_shared<StyleBucket>(layer->type);
-
- // We name the buckets according to the layer that defined it.
- bucket->name = layer->id;
-
- if (value.HasMember("source")) {
- JSVal value_source = value["source"];
- if (value_source.IsString()) {
- bucket->source = { value_source.GetString(), value_source.GetStringLength() };
- auto source_it = sourcesMap.find(bucket->source);
- if (source_it == sourcesMap.end()) {
- Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", bucket->source.c_str(), layer->id.c_str());
- }
- } else {
- Log::Warning(Event::ParseStyle, "source of layer '%s' must be a string", layer->id.c_str());
- }
- }
-
- if (value.HasMember("source-layer")) {
- JSVal value_source_layer = value["source-layer"];
- if (value_source_layer.IsString()) {
- bucket->source_layer = { value_source_layer.GetString(), value_source_layer.GetStringLength() };
- } else {
- Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", layer->id.c_str());
- }
- }
-
- if (value.HasMember("filter")) {
- bucket->filter = parseFilterExpression(value["filter"]);
- }
-
- if (value.HasMember("layout")) {
- parseLayout(value["layout"], bucket);
- }
-
- if (value.HasMember("minzoom")) {
- JSVal min_zoom = value["minzoom"];
- if (min_zoom.IsNumber()) {
- bucket->min_zoom = min_zoom.GetDouble();
- } else {
- Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", layer->id.c_str());
- }
- }
-
- if (value.HasMember("maxzoom")) {
- JSVal max_zoom = value["maxzoom"];
- if (max_zoom.IsNumber()) {
- bucket->max_zoom = max_zoom.GetDouble();
- } else {
- Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", layer->id.c_str());
- }
- }
-
- layer->bucket = bucket;
-}
-
void StyleParser::parseSprite(JSVal value) {
if (value.IsString()) {
sprite = { value.GetString(), value.GetStringLength() };
diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp
index 22dc4f6275..2f6063e1f5 100644
--- a/src/mbgl/style/style_parser.hpp
+++ b/src/mbgl/style/style_parser.hpp
@@ -54,11 +54,9 @@ public:
private:
void parseSources(JSVal value);
void parseLayers(JSVal value);
- void parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair);
+ void parseLayer(const std::string& id, JSVal value, util::ptr<StyleLayer>&);
void parsePaints(JSVal value, std::map<ClassID, ClassProperties> &paints);
void parsePaint(JSVal, ClassProperties &properties);
- void parseReference(JSVal value, util::ptr<StyleLayer> &layer);
- void parseBucket(JSVal value, util::ptr<StyleLayer> &layer);
void parseLayout(JSVal value, util::ptr<StyleBucket> &bucket);
void parseSprite(JSVal value);
void parseGlyphURL(JSVal value);
@@ -106,8 +104,8 @@ private:
std::unordered_map<std::string, const Source*> sourcesMap;
std::unordered_map<std::string, std::pair<JSVal, util::ptr<StyleLayer>>> layersMap;
- // Store a stack of layers we're parsing right now. This is to prevent reference cycles.
- std::forward_list<StyleLayer *> stack;
+ // Store a stack of layer IDs we're parsing right now. This is to prevent reference cycles.
+ std::forward_list<std::string> stack;
// Base URL of the sprite image.
std::string sprite;
diff --git a/test/api/annotations.cpp b/test/api/annotations.cpp
index 907f0446b6..415b2ddb69 100644
--- a/test/api/annotations.cpp
+++ b/test/api/annotations.cpp
@@ -48,14 +48,11 @@ TEST(Annotations, LineAnnotation) {
AnnotationSegments segments = {{ {{ { 0, 0 }, { 45, 45 } }} }};
- LinePaintProperties lineProperties;
- lineProperties.color = {{ 255, 0, 0, 1 }};
- lineProperties.width = 5;
+ LinePaintProperties properties;
+ properties.color = {{ 255, 0, 0, 1 }};
+ properties.width = 5;
- StyleProperties styleProperties;
- styleProperties.set<LinePaintProperties>(lineProperties);
-
- map.addShapeAnnotation(ShapeAnnotation(segments, styleProperties));
+ map.addShapeAnnotation(ShapeAnnotation(segments, properties));
util::write_file("test/output/line_annotation.png", renderPNG(map));
}
@@ -70,13 +67,10 @@ TEST(Annotations, FillAnnotation) {
AnnotationSegments segments = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
- FillPaintProperties fillProperties;
- fillProperties.fill_color = {{ 255, 0, 0, 1 }};
-
- StyleProperties styleProperties;
- styleProperties.set<FillPaintProperties>(fillProperties);
+ FillPaintProperties properties;
+ properties.fill_color = {{ 255, 0, 0, 1 }};
- map.addShapeAnnotation(ShapeAnnotation(segments, styleProperties));
+ map.addShapeAnnotation(ShapeAnnotation(segments, properties));
util::write_file("test/output/fill_annotation.png", renderPNG(map));
}
@@ -109,13 +103,10 @@ TEST(Annotations, NonImmediateAdd) {
AnnotationSegments segments = {{ {{ { 0, 0 }, { 0, 45 }, { 45, 45 }, { 45, 0 } }} }};
- FillPaintProperties fillProperties;
- fillProperties.fill_color = {{ 255, 0, 0, 1 }};
+ FillPaintProperties properties;
+ properties.fill_color = {{ 255, 0, 0, 1 }};
- StyleProperties styleProperties;
- styleProperties.set<FillPaintProperties>(fillProperties);
-
- map.addShapeAnnotation(ShapeAnnotation(segments, styleProperties));
+ map.addShapeAnnotation(ShapeAnnotation(segments, properties));
util::write_file("test/output/non_immediate_add.png", renderPNG(map));
}
@@ -143,16 +134,13 @@ TEST(Annotations, RemoveShape) {
AnnotationSegments segments = {{ {{ { 0, 0 }, { 45, 45 } }} }};
- LinePaintProperties lineProperties;
- lineProperties.color = {{ 255, 0, 0, 1 }};
- lineProperties.width = 5;
-
- StyleProperties styleProperties;
- styleProperties.set<LinePaintProperties>(lineProperties);
+ LinePaintProperties properties;
+ properties.color = {{ 255, 0, 0, 1 }};
+ properties.width = 5;
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
- uint32_t shape = map.addShapeAnnotation(ShapeAnnotation(segments, styleProperties));
+ uint32_t shape = map.addShapeAnnotation(ShapeAnnotation(segments, properties));
renderPNG(map);
diff --git a/test/fixtures/style_parser/text-size.style.json b/test/fixtures/style_parser/text-size.style.json
index 46dd33e3c4..8c0076197a 100644
--- a/test/fixtures/style_parser/text-size.style.json
+++ b/test/fixtures/style_parser/text-size.style.json
@@ -9,7 +9,7 @@
},
"layers": [{
"id": "country_label",
- "type": "text",
+ "type": "symbol",
"source": "mapbox",
"source-layer": "country_label",
"filter": ["==", "$type", "Point"],