implement functions for patterns
It introduces a new function type, FadedStopsFunction, that transitions between the stops values instead of interpolating between them.
This commit is contained in:
@@ -385,8 +385,8 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
|
||||
|
||||
useProgram(patternShader->program);
|
||||
patternShader->u_matrix = identityMatrix;
|
||||
patternShader->u_pattern_tl = imagePos.tl;
|
||||
patternShader->u_pattern_br = imagePos.br;
|
||||
patternShader->u_pattern_tl_a = imagePos.tl;
|
||||
patternShader->u_pattern_br_a = imagePos.br;
|
||||
patternShader->u_mix = zoomFraction;
|
||||
patternShader->u_opacity = properties.opacity;
|
||||
|
||||
@@ -408,7 +408,7 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
|
||||
matrix::scale(matrix, matrix,
|
||||
scale * state.getWidth() / 2,
|
||||
-scale * state.getHeight() / 2);
|
||||
patternShader->u_patternmatrix = matrix;
|
||||
patternShader->u_patternmatrix_a = matrix;
|
||||
|
||||
backgroundBuffer.bind();
|
||||
patternShader->bind(0);
|
||||
|
||||
@@ -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;
|
||||
float duration = 300 * 1_millisecond;
|
||||
const float fraction = std::fmod(float(state.getZoom()), 1.0f);
|
||||
float t = std::min((util::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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
51
src/mbgl/style/fadedfunction_properties.cpp
Normal file
51
src/mbgl/style/fadedfunction_properties.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#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 tDiff = (util::now() - zh.lastIntegerZoomTime) / 1_millisecond;
|
||||
float fDuration = duration / 1_millisecond;
|
||||
float t = std::min(tDiff / fDuration, 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;
|
||||
|
||||
}
|
||||
24
src/mbgl/style/fadedfunction_properties.hpp
Normal file
24
src/mbgl/style/fadedfunction_properties.hpp
Normal file
@@ -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_, timestamp duration_) : values(values_), duration(duration_) {}
|
||||
inline FadedStopsFunction(T &value) : values({{ 0, value }}), duration(0.0f) {}
|
||||
inline FadedStopsFunction() : values(), duration(0.0f) {}
|
||||
T evaluate(float z, const ZoomHistory &zoomHistory) const;
|
||||
|
||||
private:
|
||||
const std::vector<std::pair<float, T>> values;
|
||||
const timestamp duration;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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>
|
||||
@@ -16,7 +17,8 @@ typedef mapbox::util::variant<
|
||||
Function<bool>,
|
||||
Function<float>,
|
||||
Function<Color>,
|
||||
Function<std::vector<float>>
|
||||
Function<std::vector<float>>,
|
||||
FadedStopsFunction<Faded<std::string>>
|
||||
> PropertyValue;
|
||||
|
||||
}
|
||||
|
||||
@@ -29,8 +29,10 @@ Style::~Style() {}
|
||||
void Style::updateProperties(float z, timestamp 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.
|
||||
|
||||
@@ -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/time.hpp>
|
||||
#include <mbgl/util/uv.hpp>
|
||||
@@ -49,6 +50,7 @@ private:
|
||||
PropertyTransition defaultTransition;
|
||||
bool initial_render_complete = false;
|
||||
std::unique_ptr<uv::rwlock> mtx;
|
||||
ZoomHistory zoomHistory;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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 timestamp now) {
|
||||
void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const timestamp 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 timestamp now) {
|
||||
void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const timestamp 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 timestamp now) {
|
||||
void StyleLayer::applyStyleProperties<FillProperties>(const float z, const timestamp 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 timestamp now) {
|
||||
void StyleLayer::applyStyleProperties<LineProperties>(const float z, const timestamp 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), now + 10000);
|
||||
applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), now + 10000, zoomHistory);
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const timestamp now) {
|
||||
void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const timestamp 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::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);
|
||||
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::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 timestamp now) {
|
||||
void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const timestamp 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 timestamp now) {
|
||||
void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const timestamp 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 timestamp now) {
|
||||
void StyleLayer::updateProperties(float z, const timestamp 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -35,7 +36,7 @@ public:
|
||||
|
||||
// Updates the StyleProperties information in this layer by evaluating all
|
||||
// pending transitions and applied classes in order.
|
||||
void updateProperties(float z, timestamp now);
|
||||
void updateProperties(float z, timestamp 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, timestamp now,
|
||||
@@ -50,9 +51,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, timestamp now);
|
||||
template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, timestamp now);
|
||||
template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, timestamp now);
|
||||
template <typename T> void applyStyleProperties(float z, timestamp now, const ZoomHistory &zoomHistory);
|
||||
template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, timestamp now, const ZoomHistory &zoomHistory);
|
||||
template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, timestamp now, const ZoomHistory &zoomHistory);
|
||||
|
||||
// Removes all expired style transitions.
|
||||
void cleanupAppliedStyleProperties(timestamp now);
|
||||
|
||||
@@ -11,10 +11,10 @@ void StyleLayerGroup::setClasses(const std::vector<std::string> &class_names, ti
|
||||
}
|
||||
}
|
||||
|
||||
void StyleLayerGroup::updateProperties(float z, timestamp t) {
|
||||
void StyleLayerGroup::updateProperties(float z, timestamp t, ZoomHistory &zoomHistory) {
|
||||
for (const util::ptr<StyleLayer> &layer: layers) {
|
||||
if (layer) {
|
||||
layer->updateProperties(z, t);
|
||||
layer->updateProperties(z, t, zoomHistory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class StyleLayerGroup {
|
||||
public:
|
||||
void setClasses(const std::vector<std::string> &class_names, timestamp now,
|
||||
const PropertyTransition &defaultTransition);
|
||||
void updateProperties(float z, timestamp t);
|
||||
void updateProperties(float z, timestamp t, ZoomHistory &zoomHistory);
|
||||
|
||||
bool hasTransitions() const;
|
||||
public:
|
||||
|
||||
@@ -263,6 +263,52 @@ std::vector<float> StyleParser::parseFunctionArgument(JSVal value) {
|
||||
return std::get<1>(parseFloatArray(rvalue));
|
||||
}
|
||||
|
||||
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; }
|
||||
template <> inline float defaultBaseValue<Color>() { return 1.0; }
|
||||
|
||||
@@ -284,47 +330,52 @@ 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 timestamp defaultDurationValue() { return 300_milliseconds; }
|
||||
|
||||
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, {} };
|
||||
}
|
||||
|
||||
timestamp duration = defaultDurationValue<T>();
|
||||
|
||||
if (value.HasMember("duration")) {
|
||||
JSVal value_duration = value["duration"];
|
||||
if (value_duration.IsNumber()) {
|
||||
float duration_ = value_duration.GetDouble();
|
||||
duration = 1_millisecond * duration_;
|
||||
} 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>
|
||||
@@ -430,6 +481,19 @@ template<> std::tuple<bool, Function<std::vector<float>>> StyleParser::parseProp
|
||||
}
|
||||
}
|
||||
|
||||
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, {} };
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool StyleParser::parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value) {
|
||||
if (value.HasMember(property_name)) {
|
||||
@@ -573,7 +637,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);
|
||||
|
||||
@@ -77,7 +77,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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
39
src/mbgl/style/zoom_history.hpp
Normal file
39
src/mbgl/style/zoom_history.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef MBGL_STYLE_ZOOM_HISTORY
|
||||
#define MBGL_STYLE_ZOOM_HISTORY
|
||||
|
||||
#include <mbgl/util/time.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct ZoomHistory {
|
||||
float lastZoom;
|
||||
float lastIntegerZoom;
|
||||
timestamp lastIntegerZoomTime;
|
||||
bool first = true;
|
||||
|
||||
void update(float z, timestamp now) {
|
||||
if (first) {
|
||||
first = false;
|
||||
|
||||
lastIntegerZoom = std::floor(z);
|
||||
lastIntegerZoomTime = 0;
|
||||
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
|
||||
Reference in New Issue
Block a user