[core] Introduce StyleLayer subclasses
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]])
|
||||
{
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>();
|
||||
layer->id = layerID;
|
||||
layer->type = StyleLayerType::Fill;
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
shapeLayer->bucket = shapeBucket;
|
||||
style.addLayer(std::move(shapeLayer), AnnotationManager::PointLayerID);
|
||||
}
|
||||
|
||||
void ShapeAnnotationImpl::updateTile(const TileID& tileID, AnnotationTile& tile) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/geojsonvt/geojsonvt.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
||||
12
src/mbgl/layer/background_layer.cpp
Normal file
12
src/mbgl/layer/background_layer.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/mbgl/layer/background_layer.hpp
Normal file
18
src/mbgl/layer/background_layer.hpp
Normal file
@@ -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
|
||||
15
src/mbgl/layer/circle_layer.cpp
Normal file
15
src/mbgl/layer/circle_layer.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/mbgl/layer/circle_layer.hpp
Normal file
18
src/mbgl/layer/circle_layer.hpp
Normal file
@@ -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
|
||||
29
src/mbgl/layer/fill_layer.cpp
Normal file
29
src/mbgl/layer/fill_layer.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/mbgl/layer/fill_layer.hpp
Normal file
18
src/mbgl/layer/fill_layer.hpp
Normal file
@@ -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
|
||||
22
src/mbgl/layer/line_layer.cpp
Normal file
22
src/mbgl/layer/line_layer.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/mbgl/layer/line_layer.hpp
Normal file
18
src/mbgl/layer/line_layer.hpp
Normal file
@@ -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
|
||||
16
src/mbgl/layer/raster_layer.cpp
Normal file
16
src/mbgl/layer/raster_layer.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/mbgl/layer/raster_layer.hpp
Normal file
18
src/mbgl/layer/raster_layer.hpp
Normal file
@@ -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
|
||||
39
src/mbgl/layer/symbol_layer.cpp
Normal file
39
src/mbgl/layer/symbol_layer.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/mbgl/layer/symbol_layer.hpp
Normal file
18
src/mbgl/layer/symbol_layer.hpp
Normal file
@@ -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
|
||||
@@ -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>
|
||||
@@ -63,29 +64,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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
45
src/mbgl/style/property_evaluator.hpp
Normal file
45
src/mbgl/style/property_evaluator.hpp
Normal file
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,6 +45,62 @@ public:
|
||||
|
||||
bool hasTransitions() const;
|
||||
|
||||
public:
|
||||
// The name of this layer.
|
||||
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<StyleBucket> bucket;
|
||||
|
||||
// Contains all style classes that can be applied to this layer.
|
||||
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,
|
||||
@@ -54,30 +108,11 @@ private:
|
||||
|
||||
// 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);
|
||||
virtual RenderPass applyStyleProperties(float z, const TimePoint& now, const ZoomHistory&) = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
|
||||
// Contains all style classes that can be applied to this layer.
|
||||
const std::map<ClassID, ClassProperties> styles;
|
||||
|
||||
private:
|
||||
// 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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
parseLayer(it->first,
|
||||
it->second.first,
|
||||
it->second.second);
|
||||
|
||||
if (it->second.second) {
|
||||
layers.emplace_back(it->second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StyleParser::parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair) {
|
||||
JSVal value = pair.first;
|
||||
util::ptr<StyleLayer> &layer = pair.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 (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() };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }};
|
||||
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/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);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"layers": [{
|
||||
"id": "country_label",
|
||||
"type": "text",
|
||||
"type": "symbol",
|
||||
"source": "mapbox",
|
||||
"source-layer": "country_label",
|
||||
"filter": ["==", "$type", "Point"],
|
||||
|
||||
Reference in New Issue
Block a user