summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/programs/line_program.cpp14
-rw-r--r--src/mbgl/programs/line_program.hpp21
-rw-r--r--src/mbgl/programs/programs.hpp2
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.cpp93
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.hpp11
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp43
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.hpp6
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp4
-rw-r--r--src/mbgl/shaders/collision_circle.cpp8
-rw-r--r--src/mbgl/shaders/line.cpp3
-rw-r--r--src/mbgl/shaders/line_gradient.cpp249
-rw-r--r--src/mbgl/shaders/line_gradient.hpp16
-rw-r--r--src/mbgl/style/conversion/make_property_setters.hpp4
-rw-r--r--src/mbgl/style/conversion/property_setter.hpp2
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp13
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp3
-rw-r--r--src/mbgl/style/function/expression.cpp4
-rw-r--r--src/mbgl/style/layers/heatmap_layer.cpp10
-rw-r--r--src/mbgl/style/layers/heatmap_layer_properties.hpp2
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs10
-rw-r--r--src/mbgl/style/layers/layer_properties.hpp.ejs5
-rw-r--r--src/mbgl/style/layers/line_layer.cpp23
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp5
-rw-r--r--src/mbgl/style/paint_property.hpp16
24 files changed, 506 insertions, 61 deletions
diff --git a/src/mbgl/programs/line_program.cpp b/src/mbgl/programs/line_program.cpp
index faf57ef19b..3c4124e9f4 100644
--- a/src/mbgl/programs/line_program.cpp
+++ b/src/mbgl/programs/line_program.cpp
@@ -44,6 +44,20 @@ LineProgram::uniformValues(const RenderLinePaintProperties::PossiblyEvaluated& p
);
}
+LineGradientProgram::UniformValues
+LineGradientProgram::uniformValues(const RenderLinePaintProperties::PossiblyEvaluated& properties,
+ const RenderTile& tile,
+ const TransformState& state,
+ const std::array<float, 2>& pixelsToGLUnits) {
+ return makeValues<LineGradientProgram::UniformValues>(
+ properties,
+ tile,
+ state,
+ pixelsToGLUnits,
+ uniforms::u_image::Value{ 0 }
+ );
+}
+
LineSDFProgram::UniformValues
LineSDFProgram::uniformValues(const RenderLinePaintProperties::PossiblyEvaluated& properties,
float pixelRatio,
diff --git a/src/mbgl/programs/line_program.hpp b/src/mbgl/programs/line_program.hpp
index da9964e623..c07176fa44 100644
--- a/src/mbgl/programs/line_program.hpp
+++ b/src/mbgl/programs/line_program.hpp
@@ -4,6 +4,7 @@
#include <mbgl/programs/attributes.hpp>
#include <mbgl/programs/uniforms.hpp>
#include <mbgl/shaders/line.hpp>
+#include <mbgl/shaders/line_gradient.hpp>
#include <mbgl/shaders/line_pattern.hpp>
#include <mbgl/shaders/line_sdf.hpp>
#include <mbgl/util/geometry.hpp>
@@ -98,6 +99,26 @@ public:
const std::array<float, 2>& pixelsToGLUnits);
};
+class LineGradientProgram : public Program<
+ shaders::line_gradient,
+ gl::Triangle,
+ LineLayoutAttributes,
+ gl::Uniforms<
+ uniforms::u_matrix,
+ uniforms::u_ratio,
+ uniforms::u_gl_units_to_pixels,
+ uniforms::u_image>,
+ RenderLinePaintProperties>
+{
+public:
+ using Program::Program;
+
+ static UniformValues uniformValues(const RenderLinePaintProperties::PossiblyEvaluated&,
+ const RenderTile&,
+ const TransformState&,
+ const std::array<float, 2>& pixelsToGLUnits);
+};
+
class LinePatternProgram : public Program<
shaders::line_pattern,
gl::Triangle,
diff --git a/src/mbgl/programs/programs.hpp b/src/mbgl/programs/programs.hpp
index 4bb23455e8..6c9802ab4b 100644
--- a/src/mbgl/programs/programs.hpp
+++ b/src/mbgl/programs/programs.hpp
@@ -37,6 +37,7 @@ public:
hillshade(context, programParameters),
hillshadePrepare(context, programParameters),
line(context, programParameters),
+ lineGradient(context, programParameters),
lineSDF(context, programParameters),
linePattern(context, programParameters),
raster(context, programParameters),
@@ -64,6 +65,7 @@ public:
HillshadeProgram hillshade;
HillshadePrepareProgram hillshadePrepare;
ProgramMap<LineProgram> line;
+ ProgramMap<LineGradientProgram> lineGradient;
ProgramMap<LineSDFProgram> lineSDF;
ProgramMap<LinePatternProgram> linePattern;
RasterProgram raster;
diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp
index a96518df38..248e0a235d 100644
--- a/src/mbgl/renderer/buckets/line_bucket.cpp
+++ b/src/mbgl/renderer/buckets/line_bucket.cpp
@@ -88,6 +88,16 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
return;
}
+ const auto &props = feature.getProperties();
+ optional<double> totalDistance;
+ optional<double> startDistance;
+ auto total_it = props.find("$distance_total");
+ auto start_it = props.find("$distance_start");
+ if (total_it != props.end() && start_it != props.end()) {
+ totalDistance = numericValue<double>(total_it->second);
+ startDistance = numericValue<double>(start_it->second);
+ }
+
const LineJoinType joinType = layout.evaluate<LineJoin>(zoom, feature);
const float miterLimit = joinType == LineJoinType::Bevel ? 1.05f : float(layout.get<LineMiterLimit>());
@@ -190,7 +200,8 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
if (prevSegmentLength > 2.0 * sharpCornerOffset) {
GeometryCoordinate newPrevVertex = *currentCoordinate - convertPoint<int16_t>(util::round(convertPoint<double>(*currentCoordinate - *prevCoordinate) * (sharpCornerOffset / prevSegmentLength)));
distance += util::dist<double>(newPrevVertex, *prevCoordinate);
- addCurrentVertex(newPrevVertex, distance, *prevNormal, 0, 0, false, startVertex, triangleStore);
+ addCurrentVertex(newPrevVertex, distance, *prevNormal, 0, 0, false, startVertex,
+ triangleStore, totalDistance, startDistance);
prevCoordinate = newPrevVertex;
}
}
@@ -235,7 +246,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
if (middleVertex && currentJoin == LineJoinType::Miter) {
joinNormal = joinNormal * miterLength;
addCurrentVertex(*currentCoordinate, distance, joinNormal, 0, 0, false, startVertex,
- triangleStore);
+ triangleStore, totalDistance, startDistance);
} else if (middleVertex && currentJoin == LineJoinType::FlipBevel) {
// miter is too big, flip the direction to make a beveled join
@@ -251,10 +262,10 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
}
addCurrentVertex(*currentCoordinate, distance, joinNormal, 0, 0, false, startVertex,
- triangleStore);
+ triangleStore, totalDistance, startDistance);
addCurrentVertex(*currentCoordinate, distance, joinNormal * -1.0, 0, 0, false, startVertex,
- triangleStore);
+ triangleStore, totalDistance, startDistance);
} else if (middleVertex && (currentJoin == LineJoinType::Bevel || currentJoin == LineJoinType::FakeRound)) {
const bool lineTurnsLeft = (prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x) > 0;
const float offset = -std::sqrt(miterLength * miterLength - 1);
@@ -272,7 +283,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
// Close previous segement with bevel
if (!startOfLine) {
addCurrentVertex(*currentCoordinate, distance, *prevNormal, offsetA, offsetB, false,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
}
if (currentJoin == LineJoinType::FakeRound) {
@@ -287,41 +298,44 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
for (int m = 0; m < n; m++) {
auto approxFractionalJoinNormal = util::unit(*nextNormal * ((m + 1.0) / (n + 1.0)) + *prevNormal);
- addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft, startVertex, triangleStore);
+ addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft,
+ startVertex, triangleStore, totalDistance, startDistance);
}
- addPieSliceVertex(*currentCoordinate, distance, joinNormal, lineTurnsLeft, startVertex, triangleStore);
+ addPieSliceVertex(*currentCoordinate, distance, joinNormal, lineTurnsLeft, startVertex,
+ triangleStore, totalDistance, startDistance);
for (int k = n - 1; k >= 0; k--) {
auto approxFractionalJoinNormal = util::unit(*prevNormal * ((k + 1.0) / (n + 1.0)) + *nextNormal);
- addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft, startVertex, triangleStore);
+ addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft,
+ startVertex, triangleStore, totalDistance, startDistance);
}
}
// Start next segment
if (nextCoordinate) {
addCurrentVertex(*currentCoordinate, distance, *nextNormal, -offsetA, -offsetB,
- false, startVertex, triangleStore);
+ false, startVertex, triangleStore, totalDistance, startDistance);
}
} else if (!middleVertex && currentCap == LineCapType::Butt) {
if (!startOfLine) {
// Close previous segment with a butt
addCurrentVertex(*currentCoordinate, distance, *prevNormal, 0, 0, false,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
}
// Start next segment with a butt
if (nextCoordinate) {
addCurrentVertex(*currentCoordinate, distance, *nextNormal, 0, 0, false,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
}
} else if (!middleVertex && currentCap == LineCapType::Square) {
if (!startOfLine) {
// Close previous segment with a square cap
addCurrentVertex(*currentCoordinate, distance, *prevNormal, 1, 1, false,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
// The segment is done. Unset vertices to disconnect segments.
e1 = e2 = -1;
@@ -330,18 +344,18 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
// Start next segment
if (nextCoordinate) {
addCurrentVertex(*currentCoordinate, distance, *nextNormal, -1, -1, false,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
}
} else if (middleVertex ? currentJoin == LineJoinType::Round : currentCap == LineCapType::Round) {
if (!startOfLine) {
// Close previous segment with a butt
addCurrentVertex(*currentCoordinate, distance, *prevNormal, 0, 0, false,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
// Add round cap or linejoin at end of segment
addCurrentVertex(*currentCoordinate, distance, *prevNormal, 1, 1, true, startVertex,
- triangleStore);
+ triangleStore, totalDistance, startDistance);
// The segment is done. Unset vertices to disconnect segments.
e1 = e2 = -1;
@@ -351,10 +365,10 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
if (nextCoordinate) {
// Add round cap before first segment
addCurrentVertex(*currentCoordinate, distance, *nextNormal, -1, -1, true,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
addCurrentVertex(*currentCoordinate, distance, *nextNormal, 0, 0, false,
- startVertex, triangleStore);
+ startVertex, triangleStore, totalDistance, startDistance);
}
}
@@ -363,7 +377,8 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
if (nextSegmentLength > 2 * sharpCornerOffset) {
GeometryCoordinate newCurrentVertex = *currentCoordinate + convertPoint<int16_t>(util::round(convertPoint<double>(*nextCoordinate - *currentCoordinate) * (sharpCornerOffset / nextSegmentLength)));
distance += util::dist<double>(newCurrentVertex, *currentCoordinate);
- addCurrentVertex(newCurrentVertex, distance, *nextNormal, 0, 0, false, startVertex, triangleStore);
+ addCurrentVertex(newCurrentVertex, distance, *nextNormal, 0, 0, false, startVertex,
+ triangleStore, totalDistance, startDistance);
currentCoordinate = newCurrentVertex;
}
}
@@ -391,14 +406,27 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
}
void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
- double &distance,
+ double distance,
const Point<double>& normal,
double endLeft,
double endRight,
bool round,
std::size_t startVertex,
- std::vector<TriangleElement>& triangleStore) {
+ std::vector<TriangleElement>& triangleStore,
+ optional<double> totalDistance,
+ optional<double> startDistance) {
Point<double> extrude = normal;
+ if (totalDistance && startDistance) {
+ // First scale line from tile units to [0, 2^15)
+ distance = scaleDistance(distance, *totalDistance, *startDistance);
+ // Check to see if this vertex is going to be drawn across an edge,
+ // and if so, don't add square/round caps:
+ if (shouldClipAtEdge(currentCoordinate, distance)) {
+ endLeft = 0.;
+ endRight = 0.;
+ round = false;
+ }
+ }
if (endLeft)
extrude = extrude - (util::perp(normal) * endLeft);
vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, round, false, endLeft, distance * LINE_DISTANCE_SCALE));
@@ -424,9 +452,10 @@ void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate,
// When we get close to the distance, reset it to zero and add the vertex again with
// a distance of zero. The max distance is determined by the number of bits we allocate
// to `linesofar`.
- if (distance > MAX_LINE_DISTANCE / 2.0f) {
+ if (distance > MAX_LINE_DISTANCE / 2.0f && !totalDistance && !startDistance) {
distance = 0;
- addCurrentVertex(currentCoordinate, distance, normal, endLeft, endRight, round, startVertex, triangleStore);
+ addCurrentVertex(currentCoordinate, distance, normal, endLeft, endRight, round, startVertex,
+ triangleStore, totalDistance, startDistance);
}
}
@@ -435,8 +464,13 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex,
const Point<double>& extrude,
bool lineTurnsLeft,
std::size_t startVertex,
- std::vector<TriangleElement>& triangleStore) {
+ std::vector<TriangleElement>& triangleStore,
+ optional<double> totalDistance,
+ optional<double> startDistance) {
Point<double> flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0);
+ if (totalDistance && startDistance) {
+ distance = scaleDistance(distance, *totalDistance, *startDistance);
+ }
vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, false, lineTurnsLeft, 0, distance * LINE_DISTANCE_SCALE));
e3 = vertices.vertexSize() - 1 - startVertex;
if (e1 >= 0 && e2 >= 0) {
@@ -465,6 +499,19 @@ bool LineBucket::hasData() const {
return !segments.empty();
}
+double LineBucket::scaleDistance(double tileDistance, double totalDistance, double startDistance) const {
+ return (startDistance + tileDistance) * ((MAX_LINE_DISTANCE - 1) / totalDistance);
+}
+
+bool LineBucket::shouldClipAtEdge(const GeometryCoordinate& vertex, double vertexDistance) const {
+ // We detect non-start/end tile edge vertices for gradient lines because
+ // we turn clipping off when there's no tile buffer (which we do in
+ // order to calcuate line distances correctly), and turn these into butt
+ // ends so they won't overlap with semitransparent neighbors.
+ if (vertexDistance == 0 || vertexDistance == MAX_LINE_DISTANCE - 1) return false;
+ return vertex.x == 0 || vertex.x == util::EXTENT || vertex.y == 0 || vertex.y == util::EXTENT;
+}
+
template <class Property>
static float get(const RenderLineLayer& layer, const std::map<std::string, LineProgram::PaintPropertyBinders>& paintPropertyBinders) {
auto it = paintPropertyBinders.find(layer.getID());
diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp
index 4fb77c377e..6f1b3b20c4 100644
--- a/src/mbgl/renderer/buckets/line_bucket.hpp
+++ b/src/mbgl/renderer/buckets/line_bucket.hpp
@@ -47,12 +47,17 @@ private:
TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {}
uint16_t a, b, c;
};
- void addCurrentVertex(const GeometryCoordinate& currentVertex, double& distance,
+ void addCurrentVertex(const GeometryCoordinate& currentVertex, double distance,
const Point<double>& normal, double endLeft, double endRight, bool round,
- std::size_t startVertex, std::vector<LineBucket::TriangleElement>& triangleStore);
+ std::size_t startVertex, std::vector<LineBucket::TriangleElement>& triangleStore,
+ optional<double> totalDistance, optional<double> startDistance);
void addPieSliceVertex(const GeometryCoordinate& currentVertex, double distance,
const Point<double>& extrude, bool lineTurnsLeft, std::size_t startVertex,
- std::vector<TriangleElement>& triangleStore);
+ std::vector<TriangleElement>& triangleStore,
+ optional<double> totalDistance, optional<double> startDistance);
+
+ double scaleDistance(double, double, double) const;
+ bool shouldClipAtEdge(const GeometryCoordinate&, double) const;
std::ptrdiff_t e1;
std::ptrdiff_t e2;
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index 1b4a1c0ff7..04d300dd1f 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -18,7 +18,7 @@ using namespace style;
RenderLineLayer::RenderLineLayer(Immutable<style::LineLayer::Impl> _impl)
: RenderLayer(style::LayerType::Line, _impl),
- unevaluated(impl().paint.untransitioned()) {
+ unevaluated(impl().paint.untransitioned()), colorRamp({256, 1}) {
}
const style::LineLayer::Impl& RenderLineLayer::impl() const {
@@ -61,12 +61,12 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
assert(dynamic_cast<LineBucket*>(tile.tile.getBucket(*baseImpl)));
LineBucket& bucket = *reinterpret_cast<LineBucket*>(tile.tile.getBucket(*baseImpl));
- auto draw = [&] (auto& program, auto&& uniformValues) {
+ auto draw = [&] (auto& program, const auto& stencilMode, auto&& uniformValues) {
program.get(evaluated).draw(
parameters.context,
gl::Triangles(),
parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
- parameters.stencilModeForClipping(tile.clip),
+ stencilMode,
parameters.colorModeForRenderPass(),
std::move(uniformValues),
*bucket.vertexBuffer,
@@ -88,6 +88,7 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.lineAtlas.bind(parameters.context, 0);
draw(parameters.programs.lineSDF,
+ parameters.stencilModeForClipping(tile.clip),
LineSDFProgram::uniformValues(
evaluated,
parameters.pixelRatio,
@@ -108,6 +109,7 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
parameters.imageManager.bind(parameters.context, 0);
draw(parameters.programs.linePattern,
+ parameters.stencilModeForClipping(tile.clip),
LinePatternProgram::uniformValues(
evaluated,
tile,
@@ -117,8 +119,22 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) {
*posA,
*posB));
+ } else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) {
+ if (!colorRampTexture) {
+ colorRampTexture = parameters.context.createTexture(colorRamp);
+ }
+
+ draw(parameters.programs.lineGradient,
+ gl::StencilMode::disabled(),
+ LineGradientProgram::uniformValues(
+ evaluated,
+ tile,
+ parameters.state,
+ parameters.pixelsToGLUnits));
+
} else {
draw(parameters.programs.line,
+ parameters.stencilModeForClipping(tile.clip),
LineProgram::uniformValues(
evaluated,
tile,
@@ -158,6 +174,27 @@ optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const d
return newRings;
}
+void RenderLineLayer::updateColorRamp() {
+ auto colorValue = unevaluated.get<LineGradient>().getValue();
+ if (colorValue.isUndefined()) {
+ return;
+ }
+
+ const auto length = colorRamp.bytes();
+
+ for (uint32_t i = 0; i < length; i += 4) {
+ const auto color = colorValue.evaluate(static_cast<double>(i) / length);
+ colorRamp.data[i + 0] = std::floor(color.r * 255);
+ colorRamp.data[i + 1] = std::floor(color.g * 255);
+ colorRamp.data[i + 2] = std::floor(color.b * 255);
+ colorRamp.data[i + 3] = std::floor(color.a * 255);
+ }
+
+ if (colorRampTexture) {
+ colorRampTexture = nullopt;
+ }
+}
+
bool RenderLineLayer::queryIntersectsFeature(
const GeometryCoordinates& queryGeometry,
const GeometryTileFeature& feature,
diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp
index 8bf7e2329d..59333f0404 100644
--- a/src/mbgl/renderer/layers/render_line_layer.hpp
+++ b/src/mbgl/renderer/layers/render_line_layer.hpp
@@ -4,6 +4,7 @@
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/style/layers/line_layer_properties.hpp>
#include <mbgl/programs/uniforms.hpp>
+#include <mbgl/util/image.hpp>
namespace mbgl {
@@ -32,6 +33,8 @@ public:
const float,
const float) const override;
+ void updateColorRamp();
+
std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
// Paint properties
@@ -40,6 +43,9 @@ public:
const style::LineLayer::Impl& impl() const;
+ PremultipliedImage colorRamp;
+ optional<gl::Texture> colorRampTexture;
+
private:
float getLineWidth(const GeometryTileFeature&, const float) const;
};
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index 627a592d81..8f74e43f42 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -190,6 +190,10 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
if (layer.is<RenderHeatmapLayer>()) {
layer.as<RenderHeatmapLayer>()->updateColorRamp();
}
+
+ if (layer.is<RenderLineLayer>()) {
+ layer.as<RenderLineLayer>()->updateColorRamp();
+ }
}
if (layerAdded || layerChanged || zoomChanged || layer.hasTransition()) {
diff --git a/src/mbgl/shaders/collision_circle.cpp b/src/mbgl/shaders/collision_circle.cpp
index 82ebbf05a0..f220586245 100644
--- a/src/mbgl/shaders/collision_circle.cpp
+++ b/src/mbgl/shaders/collision_circle.cpp
@@ -26,10 +26,7 @@ varying vec2 v_extrude_scale;
void main() {
vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);
highp float camera_to_anchor_distance = projectedPoint.w;
- highp float collision_perspective_ratio = clamp(
- 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance),
- 0.0, // Prevents oversized near-field circles in pitched/overzoomed tiles
- 4.0);
+ highp float collision_perspective_ratio = 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance);
gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
@@ -46,7 +43,6 @@ void main() {
)MBGL_SHADER";
const char* collision_circle::fragmentSource = R"MBGL_SHADER(
-uniform float u_overscale_factor;
varying float v_placed;
varying float v_notUsed;
@@ -72,7 +68,7 @@ void main() {
float extrude_scale_length = length(v_extrude_scale);
float extrude_length = length(v_extrude) * extrude_scale_length;
- float stroke_width = 15.0 * extrude_scale_length / u_overscale_factor;
+ float stroke_width = 15.0 * extrude_scale_length;
float radius = v_radius * extrude_scale_length;
float distance_to_edge = abs(extrude_length - radius);
diff --git a/src/mbgl/shaders/line.cpp b/src/mbgl/shaders/line.cpp
index c700295a15..98ca2f4f1b 100644
--- a/src/mbgl/shaders/line.cpp
+++ b/src/mbgl/shaders/line.cpp
@@ -31,6 +31,7 @@ uniform vec2 u_gl_units_to_pixels;
varying vec2 v_normal;
varying vec2 v_width2;
varying float v_gamma_scale;
+varying float v_linesofar;
#ifndef HAS_UNIFORM_u_color
@@ -131,6 +132,8 @@ void main() {
vec2 a_extrude = a_data.xy - 128.0;
float a_direction = mod(a_data.z, 4.0) - 1.0;
+ v_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * 2.0;
+
vec2 pos = a_pos_normal.xy;
// x is 1 if it's a round cap, 0 otherwise
diff --git a/src/mbgl/shaders/line_gradient.cpp b/src/mbgl/shaders/line_gradient.cpp
new file mode 100644
index 0000000000..08e59a0d96
--- /dev/null
+++ b/src/mbgl/shaders/line_gradient.cpp
@@ -0,0 +1,249 @@
+// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
+
+#include <mbgl/shaders/line_gradient.hpp>
+
+namespace mbgl {
+namespace shaders {
+
+const char* line_gradient::name = "line_gradient";
+const char* line_gradient::vertexSource = R"MBGL_SHADER(
+
+
+// the distance over which the line edge fades out.
+// Retina devices need a smaller distance to avoid aliasing.
+#define ANTIALIASING 1.0 / DEVICE_PIXEL_RATIO / 2.0
+
+// floor(127 / 2) == 63.0
+// the maximum allowed miter limit is 2.0 at the moment. the extrude normal is
+// stored in a byte (-128..127). we scale regular normals up to length 63, but
+// there are also "special" normals that have a bigger length (of up to 126 in
+// this case).
+// #define scale 63.0
+#define scale 0.015873016
+
+attribute vec4 a_pos_normal;
+attribute vec4 a_data;
+
+uniform mat4 u_matrix;
+uniform mediump float u_ratio;
+uniform vec2 u_gl_units_to_pixels;
+
+varying vec2 v_normal;
+varying vec2 v_width2;
+varying float v_gamma_scale;
+varying float v_linesofar;
+
+
+#ifndef HAS_UNIFORM_u_color
+uniform lowp float a_color_t;
+attribute highp vec4 a_color;
+varying highp vec4 color;
+#else
+uniform highp vec4 u_color;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_blur
+uniform lowp float a_blur_t;
+attribute lowp vec2 a_blur;
+varying lowp float blur;
+#else
+uniform lowp float u_blur;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_opacity
+uniform lowp float a_opacity_t;
+attribute lowp vec2 a_opacity;
+varying lowp float opacity;
+#else
+uniform lowp float u_opacity;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_gapwidth
+uniform lowp float a_gapwidth_t;
+attribute mediump vec2 a_gapwidth;
+#else
+uniform mediump float u_gapwidth;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_offset
+uniform lowp float a_offset_t;
+attribute lowp vec2 a_offset;
+#else
+uniform lowp float u_offset;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_width
+uniform lowp float a_width_t;
+attribute mediump vec2 a_width;
+#else
+uniform mediump float u_width;
+#endif
+
+
+void main() {
+
+#ifndef HAS_UNIFORM_u_color
+ color = unpack_mix_vec4(a_color, a_color_t);
+#else
+ highp vec4 color = u_color;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_blur
+ blur = unpack_mix_vec2(a_blur, a_blur_t);
+#else
+ lowp float blur = u_blur;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_opacity
+ opacity = unpack_mix_vec2(a_opacity, a_opacity_t);
+#else
+ lowp float opacity = u_opacity;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_gapwidth
+ mediump float gapwidth = unpack_mix_vec2(a_gapwidth, a_gapwidth_t);
+#else
+ mediump float gapwidth = u_gapwidth;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_offset
+ lowp float offset = unpack_mix_vec2(a_offset, a_offset_t);
+#else
+ lowp float offset = u_offset;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_width
+ mediump float width = unpack_mix_vec2(a_width, a_width_t);
+#else
+ mediump float width = u_width;
+#endif
+
+
+ vec2 a_extrude = a_data.xy - 128.0;
+ float a_direction = mod(a_data.z, 4.0) - 1.0;
+
+ v_linesofar = (floor(a_data.z / 4.0) + a_data.w * 64.0) * 2.0;
+
+ vec2 pos = a_pos_normal.xy;
+
+ // x is 1 if it's a round cap, 0 otherwise
+ // y is 1 if the normal points up, and -1 if it points down
+ mediump vec2 normal = a_pos_normal.zw;
+ v_normal = normal;
+
+ // these transformations used to be applied in the JS and native code bases.
+ // moved them into the shader for clarity and simplicity.
+ gapwidth = gapwidth / 2.0;
+ float halfwidth = width / 2.0;
+ offset = -1.0 * offset;
+
+ float inset = gapwidth + (gapwidth > 0.0 ? ANTIALIASING : 0.0);
+ float outset = gapwidth + halfwidth * (gapwidth > 0.0 ? 2.0 : 1.0) + ANTIALIASING;
+
+ // Scale the extrusion vector down to a normal and then up by the line width
+ // of this vertex.
+ mediump vec2 dist = outset * a_extrude * scale;
+
+ // Calculate the offset when drawing a line that is to the side of the actual line.
+ // We do this by creating a vector that points towards the extrude, but rotate
+ // it when we're drawing round end points (a_direction = -1 or 1) since their
+ // extrude vector points in another direction.
+ mediump float u = 0.5 * a_direction;
+ mediump float t = 1.0 - abs(u);
+ mediump vec2 offset2 = offset * a_extrude * scale * normal.y * mat2(t, -u, u, t);
+
+ vec4 projected_extrude = u_matrix * vec4(dist / u_ratio, 0.0, 0.0);
+ gl_Position = u_matrix * vec4(pos + offset2 / u_ratio, 0.0, 1.0) + projected_extrude;
+
+ // calculate how much the perspective view squishes or stretches the extrude
+ float extrude_length_without_perspective = length(dist);
+ float extrude_length_with_perspective = length(projected_extrude.xy / gl_Position.w * u_gl_units_to_pixels);
+ v_gamma_scale = extrude_length_without_perspective / extrude_length_with_perspective;
+
+ v_width2 = vec2(outset, inset);
+}
+
+)MBGL_SHADER";
+const char* line_gradient::fragmentSource = R"MBGL_SHADER(
+#define MAX_LINE_DISTANCE 32767.0
+
+
+#ifndef HAS_UNIFORM_u_color
+varying highp vec4 color;
+#else
+uniform highp vec4 u_color;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_blur
+varying lowp float blur;
+#else
+uniform lowp float u_blur;
+#endif
+
+
+#ifndef HAS_UNIFORM_u_opacity
+varying lowp float opacity;
+#else
+uniform lowp float u_opacity;
+#endif
+
+
+uniform sampler2D u_image;
+
+varying vec2 v_width2;
+varying vec2 v_normal;
+varying float v_gamma_scale;
+varying float v_linesofar;
+
+void main() {
+
+#ifdef HAS_UNIFORM_u_color
+ highp vec4 color = u_color;
+#endif
+
+
+#ifdef HAS_UNIFORM_u_blur
+ lowp float blur = u_blur;
+#endif
+
+
+#ifdef HAS_UNIFORM_u_opacity
+ lowp float opacity = u_opacity;
+#endif
+
+
+ // Calculate the distance of the pixel from the line in pixels.
+ float dist = length(v_normal) * v_width2.s;
+
+ // Calculate the antialiasing fade factor. This is either when fading in
+ // the line in case of an offset line (v_width2.t) or when fading out
+ // (v_width2.s)
+ float blur2 = (blur + 1.0 / DEVICE_PIXEL_RATIO) * v_gamma_scale;
+ float alpha = clamp(min(dist - (v_width2.t - blur2), v_width2.s - dist) / blur2, 0.0, 1.0);
+
+ // For gradient lines, v_linesofar is the ratio along the entire line,
+ // scaled to [0, 2^15), and the gradient ramp is stored in a texture.
+ color = texture2D(u_image, vec2(v_linesofar / MAX_LINE_DISTANCE, 0.5));
+
+ gl_FragColor = color * (alpha * opacity);
+
+#ifdef OVERDRAW_INSPECTOR
+ gl_FragColor = vec4(1.0);
+#endif
+}
+
+)MBGL_SHADER";
+
+} // namespace shaders
+} // namespace mbgl
diff --git a/src/mbgl/shaders/line_gradient.hpp b/src/mbgl/shaders/line_gradient.hpp
new file mode 100644
index 0000000000..87a9d6d38c
--- /dev/null
+++ b/src/mbgl/shaders/line_gradient.hpp
@@ -0,0 +1,16 @@
+// NOTE: DO NOT CHANGE THIS FILE. IT IS AUTOMATICALLY GENERATED.
+
+#pragma once
+
+namespace mbgl {
+namespace shaders {
+
+class line_gradient {
+public:
+ static const char* name;
+ static const char* vertexSource;
+ static const char* fragmentSource;
+};
+
+} // namespace shaders
+} // namespace mbgl
diff --git a/src/mbgl/style/conversion/make_property_setters.hpp b/src/mbgl/style/conversion/make_property_setters.hpp
index 25c8fdb1ca..c3e6da75aa 100644
--- a/src/mbgl/style/conversion/make_property_setters.hpp
+++ b/src/mbgl/style/conversion/make_property_setters.hpp
@@ -115,6 +115,8 @@ inline auto makePaintPropertySetters() {
result["line-dasharray-transition"] = &setTransition<LineLayer, &LineLayer::setLineDasharrayTransition>;
result["line-pattern"] = &setProperty<LineLayer, PropertyValue<std::string>, &LineLayer::setLinePattern>;
result["line-pattern-transition"] = &setTransition<LineLayer, &LineLayer::setLinePatternTransition>;
+ result["line-gradient"] = &setProperty<LineLayer, ColorRampPropertyValue, &LineLayer::setLineGradient>;
+ result["line-gradient-transition"] = &setTransition<LineLayer, &LineLayer::setLineGradientTransition>;
result["icon-opacity"] = &setProperty<SymbolLayer, DataDrivenPropertyValue<float>, &SymbolLayer::setIconOpacity>;
result["icon-opacity-transition"] = &setTransition<SymbolLayer, &SymbolLayer::setIconOpacityTransition>;
@@ -174,7 +176,7 @@ inline auto makePaintPropertySetters() {
result["heatmap-weight-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapWeightTransition>;
result["heatmap-intensity"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapIntensity>;
result["heatmap-intensity-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapIntensityTransition>;
- result["heatmap-color"] = &setProperty<HeatmapLayer, HeatmapColorPropertyValue, &HeatmapLayer::setHeatmapColor>;
+ result["heatmap-color"] = &setProperty<HeatmapLayer, ColorRampPropertyValue, &HeatmapLayer::setHeatmapColor>;
result["heatmap-color-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapColorTransition>;
result["heatmap-opacity"] = &setProperty<HeatmapLayer, PropertyValue<float>, &HeatmapLayer::setHeatmapOpacity>;
result["heatmap-opacity-transition"] = &setTransition<HeatmapLayer, &HeatmapLayer::setHeatmapOpacityTransition>;
diff --git a/src/mbgl/style/conversion/property_setter.hpp b/src/mbgl/style/conversion/property_setter.hpp
index e3716a18dc..ce2cd79b30 100644
--- a/src/mbgl/style/conversion/property_setter.hpp
+++ b/src/mbgl/style/conversion/property_setter.hpp
@@ -5,7 +5,7 @@
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/data_driven_property_value.hpp>
-#include <mbgl/style/conversion/heatmap_color_property_value.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <string>
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
index 42cb655024..e346b49c2f 100644
--- a/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -231,12 +231,21 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
});
define("heatmap-density", [](const EvaluationContext& params) -> Result<double> {
- if (!params.heatmapDensity) {
+ if (!params.rampEvaluationParameter) {
return EvaluationError {
"The 'heatmap-density' expression is unavailable in the current evaluation context."
};
}
- return *(params.heatmapDensity);
+ return *(params.rampEvaluationParameter);
+ });
+
+ define("line-progress", [](const EvaluationContext& params) -> Result<double> {
+ if (!params.rampEvaluationParameter) {
+ return EvaluationError {
+ "The 'line-progress' expression is unavailable in the current evaluation context."
+ };
+ }
+ return *(params.rampEvaluationParameter);
});
define("has", [](const EvaluationContext& params, const std::string& key) -> Result<bool> {
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 0215982209..1576c39164 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -52,7 +52,8 @@ bool isConstant(const Expression& expression) {
}
return isFeatureConstant(expression) &&
- isGlobalPropertyConstant(expression, std::array<std::string, 2>{{"zoom", "heatmap-density"}});
+ isGlobalPropertyConstant(expression, std::array<std::string, 2>{{"zoom", "heatmap-density"}}) &&
+ isGlobalPropertyConstant(expression, std::array<std::string, 2>{{"zoom", "line-progress"}});
}
using namespace mbgl::style::conversion;
diff --git a/src/mbgl/style/function/expression.cpp b/src/mbgl/style/function/expression.cpp
index d9dbbfa1d3..0c3fb5304c 100644
--- a/src/mbgl/style/function/expression.cpp
+++ b/src/mbgl/style/function/expression.cpp
@@ -28,9 +28,9 @@ public:
};
-EvaluationResult Expression::evaluate(optional<float> zoom, const Feature& feature, optional<double> heatmapDensity) const {
+EvaluationResult Expression::evaluate(optional<float> zoom, const Feature& feature, optional<double> rampEvaluationParameter) const {
GeoJSONFeature f(feature);
- return this->evaluate(EvaluationContext(zoom, &f, heatmapDensity));
+ return this->evaluate(EvaluationContext(zoom, &f, rampEvaluationParameter));
}
} // namespace expression
diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp
index 4989ff15f1..dcf85f2ed4 100644
--- a/src/mbgl/style/layers/heatmap_layer.cpp
+++ b/src/mbgl/style/layers/heatmap_layer.cpp
@@ -6,7 +6,7 @@
// for constructing default heatmap-color ramp expression from style JSON
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/json.hpp>
-#include <mbgl/style/conversion/heatmap_color_property_value.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
namespace mbgl {
namespace style {
@@ -179,17 +179,17 @@ TransitionOptions HeatmapLayer::getHeatmapIntensityTransition() const {
return impl().paint.template get<HeatmapIntensity>().options;
}
-HeatmapColorPropertyValue HeatmapLayer::getDefaultHeatmapColor() {
+ColorRampPropertyValue HeatmapLayer::getDefaultHeatmapColor() {
conversion::Error error;
std::string rawValue = R"JSON(["interpolate",["linear"],["heatmap-density"],0,"rgba(0, 0, 255, 0)",0.1,"royalblue",0.3,"cyan",0.5,"lime",0.7,"yellow",1,"red"])JSON";
- return *conversion::convertJSON<HeatmapColorPropertyValue>(rawValue, error);
+ return *conversion::convertJSON<ColorRampPropertyValue>(rawValue, error);
}
-HeatmapColorPropertyValue HeatmapLayer::getHeatmapColor() const {
+ColorRampPropertyValue HeatmapLayer::getHeatmapColor() const {
return impl().paint.template get<HeatmapColor>().value;
}
-void HeatmapLayer::setHeatmapColor(HeatmapColorPropertyValue value) {
+void HeatmapLayer::setHeatmapColor(ColorRampPropertyValue value) {
if (value == getHeatmapColor())
return;
auto impl_ = mutableImpl();
diff --git a/src/mbgl/style/layers/heatmap_layer_properties.hpp b/src/mbgl/style/layers/heatmap_layer_properties.hpp
index f7afa5fbeb..70bc120184 100644
--- a/src/mbgl/style/layers/heatmap_layer_properties.hpp
+++ b/src/mbgl/style/layers/heatmap_layer_properties.hpp
@@ -24,6 +24,8 @@ struct HeatmapIntensity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
+struct HeatmapColor : ColorRampProperty {};
+
struct HeatmapOpacity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index 657a7f5a8a..0d11b16a6d 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -12,7 +12,7 @@
// for constructing default heatmap-color ramp expression from style JSON
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/json.hpp>
-#include <mbgl/style/conversion/heatmap_color_property_value.hpp>
+#include <mbgl/style/conversion/color_ramp_property_value.hpp>
<% } -%>
namespace mbgl {
@@ -139,16 +139,18 @@ void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(<%- propertyV
// Paint properties
<% for (const property of paintProperties) { %>
+<% if (property.name !== 'line-gradient') { -%>
<%- propertyValueType(property) %> <%- camelize(type) %>Layer::getDefault<%- camelize(property.name) %>() {
-<% if (property.name === 'heatmap-color') { -%>
+<% if (property.name === 'heatmap-color') { -%>
conversion::Error error;
std::string rawValue = R"JSON(<%- JSON.stringify(property.default) %>)JSON";
return *conversion::convertJSON<<%- propertyValueType(property)%>>(rawValue, error);
-<% } else { -%>
+<% } else { -%>
return { <%- defaultValue(property) %> };
-<% } -%>
+<% } -%>
}
+<% } -%>
<%- propertyValueType(property) %> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const {
return impl().paint.template get<<%- camelize(property.name) %>>().value;
}
diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs
index 1bceb84960..58b0f6c569 100644
--- a/src/mbgl/style/layers/layer_properties.hpp.ejs
+++ b/src/mbgl/style/layers/layer_properties.hpp.ejs
@@ -25,10 +25,13 @@ struct <%- camelize(property.name) %> : <%- layoutPropertyType(property, type) %
<% } -%>
<% for (const property of paintProperties) { -%>
-<% if (property.name === 'heatmap-color') continue; -%>
+<% if (property.name === 'heatmap-color' || property.name === 'line-gradient') { -%>
+struct <%- camelize(property.name) %> : ColorRampProperty {};
+<% } else { -%>
struct <%- camelize(property.name) %> : <%- paintPropertyType(property, type) %> {
static <%- evaluatedType(property) %> defaultValue() { return <%- defaultValue(property) %>; }
};
+<% } -%>
<% } -%>
<% if (layoutProperties.length) { -%>
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 1c7f0d28ee..2d6bf5dd01 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -429,5 +429,28 @@ TransitionOptions LineLayer::getLinePatternTransition() const {
return impl().paint.template get<LinePattern>().options;
}
+ColorRampPropertyValue LineLayer::getLineGradient() const {
+ return impl().paint.template get<LineGradient>().value;
+}
+
+void LineLayer::setLineGradient(ColorRampPropertyValue value) {
+ if (value == getLineGradient())
+ return;
+ auto impl_ = mutableImpl();
+ impl_->paint.template get<LineGradient>().value = value;
+ baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
+}
+
+void LineLayer::setLineGradientTransition(const TransitionOptions& options) {
+ auto impl_ = mutableImpl();
+ impl_->paint.template get<LineGradient>().options = options;
+ baseImpl = std::move(impl_);
+}
+
+TransitionOptions LineLayer::getLineGradientTransition() const {
+ return impl().paint.template get<LineGradient>().options;
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
index aeaf51698a..ee6789205c 100644
--- a/src/mbgl/style/layers/line_layer_properties.hpp
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -72,6 +72,8 @@ struct LinePattern : CrossFadedPaintProperty<std::string> {
static std::string defaultValue() { return ""; }
};
+struct LineGradient : ColorRampProperty {};
+
class LineLayoutProperties : public Properties<
LineCap,
LineJoin,
@@ -89,7 +91,8 @@ class LinePaintProperties : public Properties<
LineOffset,
LineBlur,
LineDasharray,
- LinePattern
+ LinePattern,
+ LineGradient
> {};
} // namespace style
diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp
index 195eb645a9..15dbf9205c 100644
--- a/src/mbgl/style/paint_property.hpp
+++ b/src/mbgl/style/paint_property.hpp
@@ -2,7 +2,7 @@
#include <mbgl/style/properties.hpp>
#include <mbgl/style/property_value.hpp>
-#include <mbgl/style/heatmap_color_property_value.hpp>
+#include <mbgl/style/color_ramp_property_value.hpp>
#include <mbgl/style/data_driven_property_value.hpp>
#include <mbgl/renderer/property_evaluator.hpp>
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
@@ -50,19 +50,19 @@ public:
};
/*
- * Special-case paint property traits for heatmap-color, needed because
- * heatmap-color values do not fit into the
+ * Special-case paint property traits for heatmap-color and line-gradient,
+ * needed because these values do not fit into the
* Undefined | Value | {Camera,Source,Composite}Function taxonomy that applies
* to all other paint properties.
*
- * These traits are provided here--despite the fact that heatmap-color
- * is not used like other paint properties--to allow the parameter-pack-based
+ * These traits are provided here--despite the fact that color ramps
+ * are not used like other paint properties--to allow the parameter-pack-based
* batch evaluation of paint properties to compile properly.
*/
-class HeatmapColor {
+class ColorRampProperty {
public:
- using TransitionableType = Transitionable<HeatmapColorPropertyValue>;
- using UnevaluatedType = Transitioning<HeatmapColorPropertyValue>;
+ using TransitionableType = Transitionable<ColorRampPropertyValue>;
+ using UnevaluatedType = Transitioning<ColorRampPropertyValue>;
using EvaluatorType = PropertyEvaluator<Color>;
using PossiblyEvaluatedType = Color;
using Type = Color;