diff options
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"], |