summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/renderer/painter.cpp76
-rw-r--r--src/mbgl/renderer/painter.hpp5
-rw-r--r--src/mbgl/renderer/painter_fill.cpp42
-rw-r--r--src/mbgl/renderer/painter_line.cpp64
-rw-r--r--src/mbgl/shader/linepattern.fragment.glsl22
-rw-r--r--src/mbgl/shader/linepattern_shader.hpp9
-rw-r--r--src/mbgl/shader/pattern.fragment.glsl17
-rw-r--r--src/mbgl/shader/pattern.vertex.glsl9
-rw-r--r--src/mbgl/shader/pattern_shader.hpp9
-rw-r--r--src/mbgl/style/fadedfunction_properties.cpp50
-rw-r--r--src/mbgl/style/fadedfunction_properties.hpp24
-rw-r--r--src/mbgl/style/property_value.hpp4
-rw-r--r--src/mbgl/style/style.cpp4
-rw-r--r--src/mbgl/style/style.hpp2
-rw-r--r--src/mbgl/style/style_layer.cpp135
-rw-r--r--src/mbgl/style/style_layer.hpp9
-rw-r--r--src/mbgl/style/style_layer_group.cpp4
-rw-r--r--src/mbgl/style/style_layer_group.hpp2
-rw-r--r--src/mbgl/style/style_parser.cpp143
-rw-r--r--src/mbgl/style/style_parser.hpp4
-rw-r--r--src/mbgl/style/style_properties.hpp10
-rw-r--r--src/mbgl/style/types.hpp10
-rw-r--r--src/mbgl/style/zoom_history.hpp38
23 files changed, 443 insertions, 249 deletions
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 3f30e6d0f5..78b6c18e4a 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -231,7 +231,7 @@ void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>&
drawClippingMasks(sources);
- recordZoom(time, state.getNormalizedZoom());
+ frameHistory.record(time, state.getNormalizedZoom());
// Actually render the layers
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
@@ -375,39 +375,58 @@ void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc
void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
const BackgroundProperties& properties = layer_desc->getProperties<BackgroundProperties>();
- if (properties.image.size()) {
+ if (properties.image.low.size()) {
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
return;
- SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
+ SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.low, true);
+ SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.high, true);
float zoomFraction = state.getZoomFraction();
useProgram(patternShader->program);
patternShader->u_matrix = identityMatrix;
- patternShader->u_pattern_tl = imagePos.tl;
- patternShader->u_pattern_br = imagePos.br;
+ patternShader->u_pattern_tl_a = imagePosA.tl;
+ patternShader->u_pattern_br_a = imagePosA.br;
+ patternShader->u_pattern_tl_b = imagePosB.tl;
+ patternShader->u_pattern_br_b = imagePosB.br;
patternShader->u_mix = zoomFraction;
patternShader->u_opacity = properties.opacity;
- std::array<float, 2> size = imagePos.size;
double lon, lat;
state.getLonLat(lon, lat);
std::array<float, 2> center = state.locationCoordinate(lon, lat);
float scale = 1 / std::pow(2, zoomFraction);
- mat3 matrix;
- matrix::identity(matrix);
- matrix::scale(matrix, matrix,
- 1.0f / size[0],
- 1.0f / size[1]);
- matrix::translate(matrix, matrix,
- std::fmod(center[0] * 512, size[0]),
- std::fmod(center[1] * 512, size[1]));
- matrix::rotate(matrix, matrix, -state.getAngle());
- matrix::scale(matrix, matrix,
+ std::array<float, 2> sizeA = imagePosA.size;
+ mat3 matrixA;
+ matrix::identity(matrixA);
+ matrix::scale(matrixA, matrixA,
+ 1.0f / (sizeA[0] * properties.image.lowScale),
+ 1.0f / (sizeA[1] * properties.image.lowScale));
+ matrix::translate(matrixA, matrixA,
+ std::fmod(center[0] * 512, sizeA[0] * properties.image.lowScale),
+ std::fmod(center[1] * 512, sizeA[1] * properties.image.lowScale));
+ matrix::rotate(matrixA, matrixA, -state.getAngle());
+ matrix::scale(matrixA, matrixA,
scale * state.getWidth() / 2,
-scale * state.getHeight() / 2);
- patternShader->u_patternmatrix = matrix;
+
+ std::array<float, 2> sizeB = imagePosB.size;
+ mat3 matrixB;
+ matrix::identity(matrixB);
+ matrix::scale(matrixB, matrixB,
+ 1.0f / (sizeB[0] * properties.image.highScale),
+ 1.0f / (sizeB[1] * properties.image.highScale));
+ matrix::translate(matrixB, matrixB,
+ std::fmod(center[0] * 512, sizeB[0] * properties.image.highScale),
+ std::fmod(center[1] * 512, sizeB[1] * properties.image.highScale));
+ matrix::rotate(matrixB, matrixB, -state.getAngle());
+ matrix::scale(matrixB, matrixB,
+ scale * state.getWidth() / 2,
+ -scale * state.getHeight() / 2);
+
+ patternShader->u_patternmatrix_a = matrixA;
+ patternShader->u_patternmatrix_b = matrixB;
backgroundBuffer.bind();
patternShader->bind(0);
@@ -459,26 +478,3 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &t
return vtxMatrix;
}
}
-
-void Painter::recordZoom(const std::chrono::steady_clock::time_point time, const float zoom) {
- frameHistory.record(time, zoom);
-
- if (lastZoom < 0) {
- // first frame ever
- lastIntegerZoom = std::floor(zoom);
- lastZoom = zoom;
- }
-
- // check whether an integer zoom level was passed since the last frame
- // and if yes, record it with the time. Used for transitioning patterns.
- if (std::floor(lastZoom) < std::floor(zoom)) {
- lastIntegerZoom = std::floor(zoom);
- lastIntegerZoomTime = time;
-
- } else if (std::floor(lastZoom) > std::floor(zoom)) {
- lastIntegerZoom = std::floor(zoom) + 1;
- lastIntegerZoomTime = time;
- }
-
- lastZoom = zoom;
-}
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index bbce588642..f38a9f0559 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -140,7 +140,6 @@ private:
mat4 translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const Tile::ID &id, TranslateAnchorType anchor);
void prepareTile(const Tile& tile);
- void recordZoom(const std::chrono::steady_clock::time_point time, const float zoom);
template <typename BucketProperties, typename StyleProperties>
void renderSDF(SymbolBucket &bucket,
@@ -193,10 +192,6 @@ private:
RenderPass pass = RenderPass::Opaque;
const float strata_epsilon = 1.0f / (1 << 16);
- int lastIntegerZoom;
- std::chrono::steady_clock::time_point lastIntegerZoomTime = std::chrono::steady_clock::time_point::min();
- float lastZoom = -1;
-
public:
FrameHistory frameHistory;
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index 45de66201c..10d4aa3320 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -33,7 +33,7 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
stroke_color[3] *= properties.opacity;
}
- const bool pattern = properties.image.size();
+ const bool pattern = properties.image.low.size();
bool outline = properties.antialias && !pattern && properties.stroke_color != properties.fill_color;
bool fringeline = properties.antialias && !pattern && properties.stroke_color == properties.fill_color;
@@ -59,34 +59,32 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
if (pattern) {
// Image fill.
if (pass == RenderPass::Translucent) {
- const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, true);
+ const SpriteAtlasPosition posA = spriteAtlas.getPosition(properties.image.low, true);
+ const SpriteAtlasPosition posB = spriteAtlas.getPosition(properties.image.high, true);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
- float mix;
- std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
- const float fraction = std::fmod(float(state.getZoom()), 1.0f);
- float t = std::min(static_cast<float>((std::chrono::steady_clock::now() - lastIntegerZoomTime) / duration), 1.0f);
- if (state.getZoom() > lastIntegerZoom) {
- // zooming in
- mix = fraction + (1.0f - fraction) * t;
- factor *= 2.0;
- } else {
- // zooming out
- mix = fraction - fraction * t;
- }
-
- mat3 patternMatrix;
- matrix::identity(patternMatrix);
- matrix::scale(patternMatrix, patternMatrix, 1.0f / (pos.size[0] * factor), 1.0f / (pos.size[1] * factor));
+ mat3 patternMatrixA;
+ matrix::identity(patternMatrixA);
+ matrix::scale(patternMatrixA, patternMatrixA,
+ 1.0f / (posA.size[0] * factor * properties.image.lowScale),
+ 1.0f / (posA.size[1] * factor * properties.image.lowScale));
+ mat3 patternMatrixB;
+ matrix::identity(patternMatrixB);
+ matrix::scale(patternMatrixB, patternMatrixB,
+ 1.0f / (posB.size[0] * factor * properties.image.highScale),
+ 1.0f / (posB.size[1] * factor * properties.image.highScale));
useProgram(patternShader->program);
patternShader->u_matrix = vtxMatrix;
- patternShader->u_pattern_tl = pos.tl;
- patternShader->u_pattern_br = pos.br;
+ patternShader->u_pattern_tl_a = posA.tl;
+ patternShader->u_pattern_br_a = posA.br;
+ patternShader->u_pattern_tl_b = posB.tl;
+ patternShader->u_pattern_br_b = posB.br;
patternShader->u_opacity = properties.opacity;
patternShader->u_image = 0;
- patternShader->u_mix = mix;
- patternShader->u_patternmatrix = patternMatrix;
+ patternShader->u_mix = properties.image.t;
+ patternShader->u_patternmatrix_a = patternMatrixA;
+ patternShader->u_patternmatrix_b = patternMatrixB;
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
spriteAtlas.bind(true);
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 1f69a05511..149683cbcd 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -70,11 +70,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
bucket.drawPoints(*linejoinShader);
}
- std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
- const float fraction = std::fmod(float(state.getZoom()), 1.0f);
- float t = std::min(static_cast<float>(std::chrono::duration<float>(std::chrono::steady_clock::now() - lastIntegerZoomTime) / duration), 1.0f);
-
- if (properties.dash_array.size()) {
+ if (properties.dash_array.low.size()) {
useProgram(linesdfShader->program);
@@ -85,46 +81,31 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
linesdfShader->u_blur = blur;
linesdfShader->u_color = color;
- LinePatternPos pos = lineAtlas.getDashPosition(properties.dash_array, bucket.properties.cap == CapType::Round);
+ LinePatternPos posA = lineAtlas.getDashPosition(properties.dash_array.low, bucket.properties.cap == CapType::Round);
+ LinePatternPos posB = lineAtlas.getDashPosition(properties.dash_array.high, bucket.properties.cap == CapType::Round);
lineAtlas.bind();
float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0;
- float scaleX = patternratio / pos.width / properties.dash_line_width;
- float scaleY = -pos.height / 2.0;
-
- float mix;
- if (state.getZoom() > lastIntegerZoom) {
- // zooming in
- mix = fraction + (1.0f - fraction) * t;
- scaleX /= 2.0;
- } else {
- // zooming out
- mix = fraction - fraction * t;
- }
-
- linesdfShader->u_patternscale_a = {{ scaleX, scaleY }};
- linesdfShader->u_tex_y_a = pos.y;
- linesdfShader->u_patternscale_b = {{ scaleX * 2.0f, scaleY }};
- linesdfShader->u_tex_y_b = pos.y;
+ float scaleXA = patternratio / posA.width / properties.dash_line_width / properties.dash_array.lowScale;
+ float scaleYA = -posA.height / 2.0;
+ float scaleXB = patternratio / posB.width / properties.dash_line_width / properties.dash_array.highScale;
+ float scaleYB = -posB.height / 2.0;
+
+ linesdfShader->u_patternscale_a = {{ scaleXA, scaleYA }};
+ linesdfShader->u_tex_y_a = posA.y;
+ linesdfShader->u_patternscale_b = {{ scaleXB, scaleYB }};
+ linesdfShader->u_tex_y_b = posB.y;
linesdfShader->u_image = 0;
- linesdfShader->u_sdfgamma = lineAtlas.width / (properties.dash_line_width * pos.width * 256.0 * state.getPixelRatio()) / 2;
- linesdfShader->u_mix = mix;
+ linesdfShader->u_sdfgamma = lineAtlas.width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * state.getPixelRatio()) / 2;
+ linesdfShader->u_mix = properties.dash_array.t;
bucket.drawLineSDF(*linesdfShader);
- } else if (properties.image.size()) {
- SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
+ } else if (properties.image.low.size()) {
+ SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.low, true);
+ SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.high, true);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
- float fade;
- if (state.getZoom() > lastIntegerZoom) {
- // zooming in
- fade = fraction + (1.0f - fraction) * t;
- factor *= 2.0;
- } else {
- // zooming out
- fade = fraction - fraction * t;
- }
useProgram(linepatternShader->program);
@@ -134,10 +115,13 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
linepatternShader->u_ratio = ratio;
linepatternShader->u_blur = blur;
- linepatternShader->u_pattern_size = {{imagePos.size[0] * factor, imagePos.size[1]}};
- linepatternShader->u_pattern_tl = imagePos.tl;
- linepatternShader->u_pattern_br = imagePos.br;
- linepatternShader->u_fade = fade;
+ linepatternShader->u_pattern_size_a = {{imagePosA.size[0] * factor * properties.image.lowScale, imagePosA.size[1]}};
+ linepatternShader->u_pattern_tl_a = imagePosA.tl;
+ linepatternShader->u_pattern_br_a = imagePosA.br;
+ linepatternShader->u_pattern_size_b = {{imagePosB.size[0] * factor * properties.image.highScale, imagePosB.size[1]}};
+ linepatternShader->u_pattern_tl_b = imagePosB.tl;
+ linepatternShader->u_pattern_br_b = imagePosB.br;
+ linepatternShader->u_fade = properties.image.t;
linepatternShader->u_opacity = properties.opacity;
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
diff --git a/src/mbgl/shader/linepattern.fragment.glsl b/src/mbgl/shader/linepattern.fragment.glsl
index 45be7c8c2f..08feff4396 100644
--- a/src/mbgl/shader/linepattern.fragment.glsl
+++ b/src/mbgl/shader/linepattern.fragment.glsl
@@ -2,9 +2,12 @@ uniform vec2 u_linewidth;
uniform float u_point;
uniform float u_blur;
-uniform vec2 u_pattern_size;
-uniform vec2 u_pattern_tl;
-uniform vec2 u_pattern_br;
+uniform vec2 u_pattern_size_a;
+uniform vec2 u_pattern_tl_a;
+uniform vec2 u_pattern_br_a;
+uniform vec2 u_pattern_size_b;
+uniform vec2 u_pattern_tl_b;
+uniform vec2 u_pattern_br_b;
uniform float u_fade;
uniform float u_opacity;
@@ -24,13 +27,14 @@ void main() {
// (v_linewidth.s)
float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0);
- float x = mod(v_linesofar / u_pattern_size.x, 1.0);
- float y = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size.y);
- vec2 pos = mix(u_pattern_tl, u_pattern_br, vec2(x, y));
- float x2 = mod(x * 2.0, 1.0);
- vec2 pos2 = mix(u_pattern_tl, u_pattern_br, vec2(x2, y));
+ float x_a = mod(v_linesofar / u_pattern_size_a.x, 1.0);
+ float y_a = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size_a.y);
+ vec2 pos_a = mix(u_pattern_tl_a, u_pattern_br_a, vec2(x_a, y_a));
+ float x_b = mod(v_linesofar / u_pattern_size_b.x, 1.0);
+ float y_b = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size_b.y);
+ vec2 pos_b = mix(u_pattern_tl_b, u_pattern_br_b, vec2(x_b, y_b));
- vec4 color = texture2D(u_image, pos) * (1.0 - u_fade) + u_fade * texture2D(u_image, pos2);
+ vec4 color = mix(texture2D(u_image, pos_a), texture2D(u_image, pos_b), u_fade);
alpha *= u_opacity;
diff --git a/src/mbgl/shader/linepattern_shader.hpp b/src/mbgl/shader/linepattern_shader.hpp
index 388cff17d2..16d9ff8be7 100644
--- a/src/mbgl/shader/linepattern_shader.hpp
+++ b/src/mbgl/shader/linepattern_shader.hpp
@@ -15,9 +15,12 @@ public:
UniformMatrix<4> u_matrix = {"u_matrix", *this};
UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
- Uniform<std::array<float, 2>> u_pattern_size = {"u_pattern_size", *this};
- Uniform<std::array<float, 2>> u_pattern_tl = {"u_pattern_tl", *this};
- Uniform<std::array<float, 2>> u_pattern_br = {"u_pattern_br", *this};
+ Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this};
+ Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
+ Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
+ Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this};
+ Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
+ Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
Uniform<float> u_ratio = {"u_ratio", *this};
Uniform<float> u_point = {"u_point", *this};
Uniform<float> u_blur = {"u_blur", *this};
diff --git a/src/mbgl/shader/pattern.fragment.glsl b/src/mbgl/shader/pattern.fragment.glsl
index ba6aed3023..a28a52ce36 100644
--- a/src/mbgl/shader/pattern.fragment.glsl
+++ b/src/mbgl/shader/pattern.fragment.glsl
@@ -1,20 +1,23 @@
uniform float u_opacity;
-uniform vec2 u_pattern_tl;
-uniform vec2 u_pattern_br;
+uniform vec2 u_pattern_tl_a;
+uniform vec2 u_pattern_br_a;
+uniform vec2 u_pattern_tl_b;
+uniform vec2 u_pattern_br_b;
uniform float u_mix;
uniform sampler2D u_image;
-varying vec2 v_pos;
+varying vec2 v_pos_a;
+varying vec2 v_pos_b;
void main() {
- vec2 imagecoord = mod(v_pos, 1.0);
- vec2 pos = mix(u_pattern_tl, u_pattern_br, imagecoord);
+ vec2 imagecoord = mod(v_pos_a, 1.0);
+ vec2 pos = mix(u_pattern_tl_a, u_pattern_br_a, imagecoord);
vec4 color1 = texture2D(u_image, pos);
- vec2 imagecoord2 = mod(imagecoord * 2.0, 1.0);
- vec2 pos2 = mix(u_pattern_tl, u_pattern_br, imagecoord2);
+ vec2 imagecoord_b = mod(v_pos_b, 1.0);
+ vec2 pos2 = mix(u_pattern_tl_b, u_pattern_br_b, imagecoord_b);
vec4 color2 = texture2D(u_image, pos2);
gl_FragColor = mix(color1, color2, u_mix) * u_opacity;
diff --git a/src/mbgl/shader/pattern.vertex.glsl b/src/mbgl/shader/pattern.vertex.glsl
index f2de884ead..dff4469d2b 100644
--- a/src/mbgl/shader/pattern.vertex.glsl
+++ b/src/mbgl/shader/pattern.vertex.glsl
@@ -1,11 +1,14 @@
uniform mat4 u_matrix;
-uniform mat3 u_patternmatrix;
+uniform mat3 u_patternmatrix_a;
+uniform mat3 u_patternmatrix_b;
attribute vec2 a_pos;
-varying vec2 v_pos;
+varying vec2 v_pos_a;
+varying vec2 v_pos_b;
void main() {
gl_Position = u_matrix * vec4(a_pos, 0, 1);
- v_pos = (u_patternmatrix * vec3(a_pos, 1)).xy;
+ v_pos_a = (u_patternmatrix_a * vec3(a_pos, 1)).xy;
+ v_pos_b = (u_patternmatrix_b * vec3(a_pos, 1)).xy;
}
diff --git a/src/mbgl/shader/pattern_shader.hpp b/src/mbgl/shader/pattern_shader.hpp
index 9fabd8e18a..9fc8dcfa01 100644
--- a/src/mbgl/shader/pattern_shader.hpp
+++ b/src/mbgl/shader/pattern_shader.hpp
@@ -13,12 +13,15 @@ public:
void bind(char *offset);
UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<std::array<float, 2>> u_pattern_tl = {"u_pattern_tl", *this};
- Uniform<std::array<float, 2>> u_pattern_br = {"u_pattern_br", *this};
+ Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
+ Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
+ Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
+ Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
Uniform<float> u_opacity = {"u_opacity", *this};
Uniform<float> u_mix = {"u_mix", *this};
Uniform<int32_t> u_image = {"u_image", *this};
- UniformMatrix<3> u_patternmatrix = {"u_patternmatrix", *this};
+ UniformMatrix<3> u_patternmatrix_a = {"u_patternmatrix_a", *this};
+ UniformMatrix<3> u_patternmatrix_b = {"u_patternmatrix_b", *this};
private:
int32_t a_pos = -1;
diff --git a/src/mbgl/style/fadedfunction_properties.cpp b/src/mbgl/style/fadedfunction_properties.cpp
new file mode 100644
index 0000000000..21c3267519
--- /dev/null
+++ b/src/mbgl/style/fadedfunction_properties.cpp
@@ -0,0 +1,50 @@
+#include <mbgl/style/fadedfunction_properties.hpp>
+#include <mbgl/style/types.hpp>
+
+#include <cmath>
+
+namespace mbgl {
+
+template <typename T>
+uint32_t getBiggestStopLessThan(std::vector<std::pair<float, T>> stops, float z) {
+ for (uint32_t i = 0; i < stops.size(); i++) {
+ if (stops[i].first > z) {
+ return i == 0 ? i : i - 1;
+ }
+ }
+ return stops.size() - 1;
+}
+
+template <typename T>
+T FadedStopsFunction<T>::evaluate(float z, const ZoomHistory &zh) const {
+ T result;
+
+ float fraction = std::fmod(z, 1.0f);
+ float t = std::min((std::chrono::steady_clock::now() - zh.lastIntegerZoomTime) / duration, 1.0f);
+ float scale = 1.0f;
+ uint32_t low, high;
+
+ if (z > zh.lastIntegerZoom) {
+ result.t = fraction + (1.0f - fraction) * t;
+ scale *= 2.0f;
+ low = getBiggestStopLessThan(values, z - 1.0f);
+ high = getBiggestStopLessThan(values, z);
+
+ } else {
+ result.t = fraction - fraction * t;
+ low = getBiggestStopLessThan(values, z);
+ high = getBiggestStopLessThan(values, z + 1.0f);
+ }
+
+
+ result.low = values[low].second.low;
+ result.high = values[high].second.low;
+ result.lowScale = scale;
+ result.highScale = scale / 2;
+ return result;
+}
+
+template Faded<std::string> FadedStopsFunction<Faded<std::string>>::evaluate(float z, const ZoomHistory &zoomHistory) const;
+template Faded<std::vector<float>> FadedStopsFunction<Faded<std::vector<float>>>::evaluate(float z, const ZoomHistory &zoomHistory) const;
+
+}
diff --git a/src/mbgl/style/fadedfunction_properties.hpp b/src/mbgl/style/fadedfunction_properties.hpp
new file mode 100644
index 0000000000..7313d32759
--- /dev/null
+++ b/src/mbgl/style/fadedfunction_properties.hpp
@@ -0,0 +1,24 @@
+#ifndef MBGL_STYLE_FADEDFUNCTION_PROPERTIES
+#define MBGL_STYLE_FADEDFUNCTION_PROPERTIES
+
+#include <mbgl/style/zoom_history.hpp>
+
+#include <vector>
+
+namespace mbgl {
+
+template <typename T>
+struct FadedStopsFunction {
+ inline FadedStopsFunction(const std::vector<std::pair<float, T>> &values_, std::chrono::duration<float> duration_) : values(values_), duration(duration_) {}
+ inline FadedStopsFunction(T &value) : values({{ 0, value }}), duration(300) {}
+ inline FadedStopsFunction() : values(), duration(300) {}
+ T evaluate(float z, const ZoomHistory &zoomHistory) const;
+
+private:
+ const std::vector<std::pair<float, T>> values;
+ const std::chrono::duration<float> duration;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/style/property_value.hpp b/src/mbgl/style/property_value.hpp
index ff5a2f8685..49e837cf12 100644
--- a/src/mbgl/style/property_value.hpp
+++ b/src/mbgl/style/property_value.hpp
@@ -3,6 +3,7 @@
#include <mbgl/util/variant.hpp>
#include <mbgl/style/function_properties.hpp>
+#include <mbgl/style/fadedfunction_properties.hpp>
#include <mbgl/style/types.hpp>
#include <vector>
@@ -25,7 +26,8 @@ typedef mapbox::util::variant<
Function<bool>,
Function<float>,
Function<Color>,
- Function<std::vector<float>>
+ FadedStopsFunction<Faded<std::vector<float>>>,
+ FadedStopsFunction<Faded<std::string>>
> PropertyValue;
}
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 01781afe3c..45217950f6 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -28,8 +28,10 @@ Style::~Style() {}
void Style::updateProperties(float z, std::chrono::steady_clock::time_point now) {
uv::writelock lock(mtx);
+ zoomHistory.update(z, now);
+
if (layers) {
- layers->updateProperties(z, now);
+ layers->updateProperties(z, now, zoomHistory);
}
// Apply transitions after the first time.
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 751a91be62..4de827a38c 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -3,6 +3,7 @@
#include <mbgl/style/property_transition.hpp>
#include <mbgl/style/style_source.hpp>
+#include <mbgl/style/zoom_history.hpp>
#include <mbgl/util/uv.hpp>
#include <mbgl/util/ptr.hpp>
@@ -50,6 +51,7 @@ private:
PropertyTransition defaultTransition;
bool initial_render_complete = false;
std::unique_ptr<uv::rwlock> mtx;
+ ZoomHistory zoomHistory;
};
}
diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp
index 3b82d7f94a..795c651b85 100644
--- a/src/mbgl/style/style_layer.cpp
+++ b/src/mbgl/style/style_layer.cpp
@@ -94,7 +94,7 @@ void StyleLayer::applyClassProperties(const ClassID class_id,
template <typename T>
struct PropertyEvaluator {
typedef T result_type;
- PropertyEvaluator(float z_) : z(z_) {}
+ 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 {
@@ -105,6 +105,10 @@ struct PropertyEvaluator {
return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value);
}
+ T operator()(const FadedStopsFunction<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();
@@ -112,15 +116,16 @@ struct PropertyEvaluator {
private:
const float z;
+ const ZoomHistory &zoomHistory;
};
template <typename T>
-void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
auto it = appliedStyle.find(key);
if (it != appliedStyle.end()) {
AppliedClassProperties &applied = it->second;
// Iterate through all properties that we need to apply in order.
- const PropertyEvaluator<T> evaluator(z);
+ const PropertyEvaluator<T> evaluator(z, zoomHistory);
for (AppliedClassProperty &property : applied.properties) {
if (now >= property.begin) {
// We overwrite the current property with the new value.
@@ -133,12 +138,12 @@ void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, c
}
template <typename T>
-void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
auto it = appliedStyle.find(key);
if (it != appliedStyle.end()) {
AppliedClassProperties &applied = it->second;
// Iterate through all properties that we need to apply in order.
- const PropertyEvaluator<T> evaluator(z);
+ const PropertyEvaluator<T> evaluator(z, zoomHistory);
for (AppliedClassProperty &property : applied.properties) {
if (now >= property.end) {
// We overwrite the current property with the new value.
@@ -155,95 +160,95 @@ void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, cons
}
template <>
-void StyleLayer::applyStyleProperties<FillProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<FillProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<FillProperties>();
FillProperties &fill = properties.get<FillProperties>();
- applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillOutlineColor, fill.stroke_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::FillTranslateX, fill.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::FillTranslateY, fill.translate[1], z, now);
- applyStyleProperty(PropertyKey::FillTranslateAnchor, fill.translateAnchor, z, now);
- applyStyleProperty(PropertyKey::FillImage, fill.image, z, now);
+ 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::FillTranslateX, fill.translate[0], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::FillTranslateY, fill.translate[1], z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::FillTranslateAnchor, fill.translateAnchor, z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::FillImage, fill.image, z, now, zoomHistory);
}
template <>
-void StyleLayer::applyStyleProperties<LineProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<LineProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<LineProperties>();
LineProperties &line = properties.get<LineProperties>();
- applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineColor, line.color, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineTranslateX, line.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::LineTranslateY, line.translate[1], z, now);
- applyStyleProperty(PropertyKey::LineTranslateAnchor, line.translateAnchor, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now);
- applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now);
- applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now);
- applyStyleProperty(PropertyKey::LineImage, line.image, z, now);
+ applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineColor, line.color, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineTranslateX, line.translate[0], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::LineTranslateY, line.translate[1], 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), std::chrono::steady_clock::time_point::max());
+ applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), std::chrono::steady_clock::time_point::max(), zoomHistory);
}
template <>
-void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<SymbolProperties>();
SymbolProperties &symbol = properties.get<SymbolProperties>();
- applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconRotate, symbol.icon.rotate, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconSize, symbol.icon.size, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconColor, symbol.icon.color, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconHaloColor, symbol.icon.halo_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconHaloWidth, symbol.icon.halo_width, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconHaloBlur, symbol.icon.halo_blur, z, now);
- applyTransitionedStyleProperty(PropertyKey::IconTranslateX, symbol.icon.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::IconTranslateY, symbol.icon.translate[1], z, now);
- applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now);
-
- applyTransitionedStyleProperty(PropertyKey::TextOpacity, symbol.text.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextSize, symbol.text.size, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextColor, symbol.text.color, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextHaloColor, symbol.text.halo_color, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextHaloWidth, symbol.text.halo_width, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextHaloBlur, symbol.text.halo_blur, z, now);
- applyTransitionedStyleProperty(PropertyKey::TextTranslateX, symbol.text.translate[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::TextTranslateY, symbol.text.translate[1], z, now);
- applyStyleProperty(PropertyKey::TextTranslateAnchor, symbol.text.translate_anchor, z, now);
+ applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconRotate, symbol.icon.rotate, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconSize, symbol.icon.size, 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::IconTranslateX, symbol.icon.translate[0], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::IconTranslateY, symbol.icon.translate[1], z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now, zoomHistory);
+
+ applyTransitionedStyleProperty(PropertyKey::TextOpacity, symbol.text.opacity, z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextSize, symbol.text.size, 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::TextTranslateX, symbol.text.translate[0], z, now, zoomHistory);
+ applyTransitionedStyleProperty(PropertyKey::TextTranslateY, symbol.text.translate[1], z, now, zoomHistory);
+ applyStyleProperty(PropertyKey::TextTranslateAnchor, symbol.text.translate_anchor, z, now, zoomHistory);
}
template <>
-void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<RasterProperties>();
RasterProperties &raster = properties.get<RasterProperties>();
- applyTransitionedStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterHueRotate, raster.hue_rotate, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterBrightnessHigh, raster.brightness[1], z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterSaturation, raster.saturation, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterContrast, raster.contrast, z, now);
- applyTransitionedStyleProperty(PropertyKey::RasterFade, raster.fade, z, now);
+ 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<BackgroundProperties>(const float z, const std::chrono::steady_clock::time_point now) {
+void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
properties.set<BackgroundProperties>();
BackgroundProperties &background = properties.get<BackgroundProperties>();
- applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now);
- applyTransitionedStyleProperty(PropertyKey::BackgroundColor, background.color, z, now);
- applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now);
+ 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 std::chrono::steady_clock::time_point now) {
+void StyleLayer::updateProperties(float z, const std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory) {
cleanupAppliedStyleProperties(now);
switch (type) {
- case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now); break;
- case StyleLayerType::Line: applyStyleProperties<LineProperties>(z, now); break;
- case StyleLayerType::Symbol: applyStyleProperties<SymbolProperties>(z, now); break;
- case StyleLayerType::Raster: applyStyleProperties<RasterProperties>(z, now); break;
- case StyleLayerType::Background: applyStyleProperties<BackgroundProperties>(z, now); break;
+ case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Line: applyStyleProperties<LineProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Symbol: applyStyleProperties<SymbolProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Raster: applyStyleProperties<RasterProperties>(z, now, zoomHistory); break;
+ case StyleLayerType::Background: applyStyleProperties<BackgroundProperties>(z, now, zoomHistory); break;
default: properties.set<std::false_type>(); break;
}
}
diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp
index b6cfe779c7..69af1dc230 100644
--- a/src/mbgl/style/style_layer.hpp
+++ b/src/mbgl/style/style_layer.hpp
@@ -5,6 +5,7 @@
#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/util/ptr.hpp>
@@ -36,7 +37,7 @@ public:
// Updates the StyleProperties information in this layer by evaluating all
// pending transitions and applied classes in order.
- void updateProperties(float z, std::chrono::steady_clock::time_point now);
+ void updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory);
// Sets the list of classes and creates transitions to the currently applied values.
void setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
@@ -51,9 +52,9 @@ private:
// Sets the properties of this object by evaluating all pending transitions and
// aplied classes in order.
- template <typename T> void applyStyleProperties(float z, std::chrono::steady_clock::time_point now);
- template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now);
- template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now);
+ template <typename T> void applyStyleProperties(float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
+ template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
+ template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
// Removes all expired style transitions.
void cleanupAppliedStyleProperties(std::chrono::steady_clock::time_point now);
diff --git a/src/mbgl/style/style_layer_group.cpp b/src/mbgl/style/style_layer_group.cpp
index 3f1a4a5111..f57ec5cc7b 100644
--- a/src/mbgl/style/style_layer_group.cpp
+++ b/src/mbgl/style/style_layer_group.cpp
@@ -11,10 +11,10 @@ void StyleLayerGroup::setClasses(const std::vector<std::string> &class_names, st
}
}
-void StyleLayerGroup::updateProperties(float z, std::chrono::steady_clock::time_point now) {
+void StyleLayerGroup::updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory) {
for (const util::ptr<StyleLayer> &layer: layers) {
if (layer) {
- layer->updateProperties(z, now);
+ layer->updateProperties(z, now, zoomHistory);
}
}
}
diff --git a/src/mbgl/style/style_layer_group.hpp b/src/mbgl/style/style_layer_group.hpp
index 3f5a20073d..79b75a55e9 100644
--- a/src/mbgl/style/style_layer_group.hpp
+++ b/src/mbgl/style/style_layer_group.hpp
@@ -12,7 +12,7 @@ class StyleLayerGroup {
public:
void setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
const PropertyTransition &defaultTransition);
- void updateProperties(float z, std::chrono::steady_clock::time_point now);
+ void updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory);
bool hasTransitions() const;
public:
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp
index 15aedd8ead..1fc57e2f7e 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/style_parser.cpp
@@ -258,9 +258,57 @@ Color StyleParser::parseFunctionArgument(JSVal value) {
}
template <>
-std::vector<float> StyleParser::parseFunctionArgument(JSVal value) {
+Faded<std::vector<float>> StyleParser::parseFunctionArgument(JSVal value) {
+ Faded<std::vector<float>> parsed;
JSVal rvalue = replaceConstant(value);
- return std::get<1>(parseFloatArray(rvalue));
+ parsed.low = std::get<1>(parseFloatArray(rvalue));
+ return parsed;
+}
+
+template <>
+Faded<std::string> StyleParser::parseFunctionArgument(JSVal value) {
+ JSVal rvalue = replaceConstant(value);
+ if (rvalue.IsString()) {
+ Faded<std::string> parsed;
+ parsed.low = { value.GetString(), value.GetStringLength() };
+ return parsed;
+ } else {
+ Log::Warning(Event::ParseStyle, "function argument must be a string");
+ return {};
+ }
+}
+
+template <typename T>
+std::tuple<bool, std::vector<std::pair<float, T>>> StyleParser::parseStops(JSVal value_stops) {
+
+ if (!value_stops.IsArray()) {
+ Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+
+ std::vector<std::pair<float, T>> stops;
+
+ for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
+ JSVal stop = value_stops[i];
+ if (stop.IsArray()) {
+ if (stop.Size() != 2) {
+ Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+
+ JSVal z = stop[rapidjson::SizeType(0)];
+ if (!z.IsNumber()) {
+ Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+
+ stops.emplace_back(z.GetDouble(), parseFunctionArgument<T>(stop[rapidjson::SizeType(1)]));
+ } else {
+ Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
+ return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
+ }
+ }
+ return { true, stops };
}
template <typename T> inline float defaultBaseValue() { return 1.75; }
@@ -284,47 +332,51 @@ std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
}
}
- JSVal value_stops = value["stops"];
- if (!value_stops.IsArray()) {
- Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
+ auto stops = parseStops<T>(value["stops"]);
+
+ if (!std::get<0>(stops)) {
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
}
- std::vector<std::pair<float, T>> stops;
- for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
- JSVal stop = value_stops[i];
- if (stop.IsArray()) {
- if (stop.Size() != 2) {
- Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
+ return std::tuple<bool, Function<T>> { true, StopsFunction<T>(std::get<1>(stops), base) };
+}
- JSVal z = stop[rapidjson::SizeType(0)];
- if (!z.IsNumber()) {
- Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
- }
+template <typename T> inline std::chrono::duration<float> defaultDurationValue() { return std::chrono::duration<float>(300.0f); }
- stops.emplace_back(z.GetDouble(), parseFunctionArgument<T>(stop[rapidjson::SizeType(1)]));
+template <typename T>
+std::tuple<bool, FadedStopsFunction<T>> StyleParser::parseFadedStopsFunction(JSVal value) {
+ if (!value.HasMember("stops")) {
+ Log::Warning(Event::ParseStyle, "function must specify a function type");
+ return std::tuple<bool, FadedStopsFunction<T>> { false, {} };
+ }
+
+ std::chrono::duration<float> duration = defaultDurationValue<T>();
+
+ if (value.HasMember("duration")) {
+ JSVal value_duration = value["duration"];
+ if (value_duration.IsNumber()) {
+ duration = static_cast<std::chrono::duration<float>>(value_duration.GetDouble());
} else {
- Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
- return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
+ Log::Warning(Event::ParseStyle, "duration must be numeric");
}
}
- return std::tuple<bool, Function<T>> { true, StopsFunction<T>(stops, base) };
-}
+ auto stops = parseStops<T>(value["stops"]);
+ if (!std::get<0>(stops)) {
+ return std::tuple<bool, FadedStopsFunction<T>> { false, {} };
+ }
+
+ return std::tuple<bool, FadedStopsFunction<T>> { true, { std::get<1>(stops), duration } };
+}
template <typename T>
bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass) {
- bool parsed;
- T result;
- std::tie(parsed, result) = parseProperty<T>(value, property_name);
- if (parsed) {
- klass.set(key, result);
+ auto res = parseProperty<T>(value, property_name);
+ if (std::get<0>(res)) {
+ klass.set(key, std::get<1>(res));
}
- return parsed;
+ return std::get<0>(res);
}
template<typename T>
@@ -502,15 +554,30 @@ template<> std::tuple<bool, Function<Color>> StyleParser::parseProperty(JSVal va
}
}
-template<> std::tuple<bool, Function<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+template<> std::tuple<bool, FadedStopsFunction<Faded<std::vector<float>>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
if (value.IsObject()) {
- return parseFunction<std::vector<float>>(value);
+ return parseFadedStopsFunction<Faded<std::vector<float>>>(value);
} else if (value.IsArray()) {
- std::tuple<bool, std::vector<float>> parsed = parseFloatArray(value);
- return std::tuple<bool, Function<std::vector<float>>> { std::get<0>(parsed), ConstantFunction<std::vector<float>>(std::get<1>(parsed)) };
+ Faded<std::vector<float>> parsed;
+ std::tuple<bool, std::vector<float>> floatarray = parseFloatArray(value);
+ parsed.low = std::get<1>(floatarray);
+ return std::tuple<bool, FadedStopsFunction<Faded<std::vector<float>>>> { std::get<0>(floatarray), parsed };
} else {
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers, or a number array function", property_name);
- return std::tuple<bool, Function<std::vector<float>>> { false, ConstantFunction<std::vector<float>>(std::vector<float>()) };
+ return std::tuple<bool, FadedStopsFunction<Faded<std::vector<float>>>> { false, {} };
+ }
+}
+
+template<> std::tuple<bool, FadedStopsFunction<Faded<std::string>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
+ if (value.IsObject()) {
+ return parseFadedStopsFunction<Faded<std::string>>(value);
+ } else if (value.IsString()) {
+ Faded<std::string> parsed;
+ parsed.low = { value.GetString(), value.GetStringLength() };
+ return std::tuple<bool, FadedStopsFunction<Faded<std::string>>> { true, parsed };
+ } else {
+ Log::Warning(Event::ParseStyle, "value of '%s' must be string or a string function", property_name);
+ return std::tuple<bool, FadedStopsFunction<Faded<std::string>>> { false, {} };
}
}
@@ -657,7 +724,7 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<Function<float>>("fill-translate", { Key::FillTranslateX, Key::FillTranslateY }, klass, value);
parseOptionalProperty<PropertyTransition>("fill-translate-transition", Key::FillTranslate, klass, value);
parseOptionalProperty<TranslateAnchorType>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
- parseOptionalProperty<std::string>("fill-image", Key::FillImage, klass, value);
+ parseOptionalProperty<FadedStopsFunction<Faded<std::string>>>("fill-image", Key::FillImage, klass, value);
parseOptionalProperty<Function<float>>("line-opacity", Key::LineOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("line-opacity-transition", Key::LineOpacity, klass, value);
@@ -672,8 +739,8 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<PropertyTransition>("line-gap-width-transition", Key::LineGapWidth, klass, value);
parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value);
parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value);
- parseOptionalProperty<Function<std::vector<float>>>("line-dasharray", Key::LineDashArray, klass, value);
- parseOptionalProperty<std::string>("line-image", Key::LineImage, klass, value);
+ parseOptionalProperty<FadedStopsFunction<Faded<std::vector<float>>>>("line-dasharray", Key::LineDashArray, klass, value);
+ parseOptionalProperty<FadedStopsFunction<Faded<std::string>>>("line-image", Key::LineImage, klass, value);
parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
parseOptionalProperty<PropertyTransition>("icon-opacity-transition", Key::IconOpacity, klass, value);
@@ -723,7 +790,7 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
parseOptionalProperty<Function<float>>("background-opacity", Key::BackgroundOpacity, klass, value);
parseOptionalProperty<Function<Color>>("background-color", Key::BackgroundColor, klass, value);
- parseOptionalProperty<std::string>("background-image", Key::BackgroundImage, klass, value);
+ parseOptionalProperty<FadedStopsFunction<Faded<std::string>>>("background-image", Key::BackgroundImage, klass, value);
}
void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp
index 24fd4292a0..5b55d6116e 100644
--- a/src/mbgl/style/style_parser.hpp
+++ b/src/mbgl/style/style_parser.hpp
@@ -79,7 +79,11 @@ private:
template <typename T>
std::tuple<bool, Function<T>> parseFunction(JSVal value);
template <typename T>
+ std::tuple<bool, FadedStopsFunction<T>> parseFadedStopsFunction(JSVal value);
+ template <typename T>
T parseFunctionArgument(JSVal value);
+ template <typename T>
+ std::tuple<bool, std::vector<std::pair<float, T>>> parseStops(JSVal value);
FilterExpression parseFilter(JSVal);
diff --git a/src/mbgl/style/style_properties.hpp b/src/mbgl/style/style_properties.hpp
index c5149b2d1c..fd55cb0bb2 100644
--- a/src/mbgl/style/style_properties.hpp
+++ b/src/mbgl/style/style_properties.hpp
@@ -3,7 +3,7 @@
#include <mbgl/util/variant.hpp>
#include <mbgl/style/types.hpp>
-#include <mbgl/style/function_properties.hpp>
+#include <mbgl/style/fadedfunction_properties.hpp>
#include <array>
#include <string>
@@ -21,7 +21,7 @@ struct FillProperties {
Color stroke_color = {{ 0, 0, 0, -1 }};
std::array<float, 2> translate = {{ 0, 0 }};
TranslateAnchorType translateAnchor = TranslateAnchorType::Map;
- std::string image;
+ Faded<std::string> image;
inline bool isVisible() const {
return opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0);
@@ -37,9 +37,9 @@ struct LineProperties {
float width = 1;
float gap_width = 0;
float blur = 0;
- std::vector<float> dash_array;
+ Faded<std::vector<float>> dash_array;
float dash_line_width = 1;
- std::string image;
+ Faded<std::string> image;
inline bool isVisible() const {
return opacity > 0 && color[3] > 0 && width > 0;
@@ -96,7 +96,7 @@ struct BackgroundProperties {
inline BackgroundProperties() {}
float opacity = 1.0f;
Color color = {{ 0, 0, 0, 1 }};
- std::string image;
+ Faded<std::string> image;
};
typedef mapbox::util::variant<
diff --git a/src/mbgl/style/types.hpp b/src/mbgl/style/types.hpp
index 6149270170..b7d675857a 100644
--- a/src/mbgl/style/types.hpp
+++ b/src/mbgl/style/types.hpp
@@ -11,6 +11,16 @@ namespace mbgl {
// Stores a premultiplied color, with all four channels ranging from 0..1
typedef std::array<float, 4> Color;
+
+template <typename T>
+struct Faded {
+ T low;
+ float lowScale;
+ T high;
+ float highScale;
+ float t;
+};
+
// -------------------------------------------------------------------------------------------------
enum class StyleLayerType : uint8_t {
diff --git a/src/mbgl/style/zoom_history.hpp b/src/mbgl/style/zoom_history.hpp
new file mode 100644
index 0000000000..eee0d9b443
--- /dev/null
+++ b/src/mbgl/style/zoom_history.hpp
@@ -0,0 +1,38 @@
+#ifndef MBGL_STYLE_ZOOM_HISTORY
+#define MBGL_STYLE_ZOOM_HISTORY
+
+#include <chrono>
+#include <cmath>
+
+namespace mbgl {
+
+struct ZoomHistory {
+ float lastZoom;
+ float lastIntegerZoom;
+ std::chrono::steady_clock::time_point lastIntegerZoomTime;
+ bool first = true;
+
+ void update(float z, std::chrono::steady_clock::time_point now) {
+ if (first) {
+ first = false;
+
+ lastIntegerZoom = std::floor(z);
+ lastIntegerZoomTime = std::chrono::steady_clock::time_point::min();
+ lastZoom = z;
+ }
+
+ if (std::floor(lastZoom) < std::floor(z)) {
+ lastIntegerZoom = std::floor(z);
+ lastIntegerZoomTime = now;
+
+ } else if (std::floor(lastZoom) > std::floor(z)) {
+ lastIntegerZoom = std::floor(z + 1);
+ lastIntegerZoomTime = now;
+ }
+
+ lastZoom = z;
+ }
+};
+}
+
+#endif