1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
#ifndef MBGL_PAINT_PROPERTIES_MAP
#define MBGL_PAINT_PROPERTIES_MAP
#include <mbgl/style/applied_class_properties.hpp>
#include <mbgl/style/property_evaluator.hpp>
#include <mbgl/style/class_dictionary.hpp>
#include <mbgl/style/property_key.hpp>
#include <mbgl/util/interpolate.hpp>
#include <rapidjson/document.h>
#include <map>
#include <set>
#include <functional>
namespace mbgl {
class ClassProperties;
class PropertyTransition;
using JSVal = rapidjson::Value;
class PaintPropertiesMap {
public:
void cascade(const std::vector<std::string>& classNames,
const TimePoint& now,
const PropertyTransition& defaultTransition);
bool hasTransitions() const;
void removeExpiredTransitions(const TimePoint& now);
// Call the function for each "paint" or "paint.*" object in the layer.
void parseEach(const JSVal& layer, std::function<void (ClassProperties&, const JSVal&)>);
template <typename T>
void calculate(PropertyKey key, T& target, const StyleCalculationParameters& parameters) {
auto it = appliedStyle.find(key);
if (it != appliedStyle.end()) {
AppliedClassPropertyValues &applied = it->second;
// Iterate through all properties that we need to apply in order.
const PropertyEvaluator<T> evaluator(parameters);
for (auto& property : applied.propertyValues) {
if (parameters.now >= property.begin) {
// We overwrite the current property with the new value.
target = mapbox::util::apply_visitor(evaluator, property.value);
} else {
// Do not apply this property because its transition hasn't begun yet.
}
}
}
}
template <typename T>
void calculateTransitioned(PropertyKey key, T& target, const StyleCalculationParameters& parameters) {
auto it = appliedStyle.find(key);
if (it != appliedStyle.end()) {
AppliedClassPropertyValues &applied = it->second;
// Iterate through all properties that we need to apply in order.
const PropertyEvaluator<T> evaluator(parameters);
for (auto& property : applied.propertyValues) {
if (parameters.now >= property.end) {
// We overwrite the current property with the new value.
target = mapbox::util::apply_visitor(evaluator, property.value);
} else if (parameters.now >= property.begin) {
// We overwrite the current property partially with the new value.
float progress = std::chrono::duration<float>(parameters.now - property.begin) / (property.end - property.begin);
target = util::interpolate(target, mapbox::util::apply_visitor(evaluator, property.value), progress);
hasPendingTransitions = true;
} else {
// Do not apply this property because its transition hasn't begun yet.
}
}
}
}
// Raw parsed paint class to property value map.
std::map<ClassID, ClassProperties> paints;
private:
// Applies all properties from a class, if they haven't been applied already.
void cascadeClass(const ClassID,
std::set<PropertyKey>&,
const TimePoint&,
const PropertyTransition&);
// For every property, stores a list of applied property values, with
// optional transition times.
std::map<PropertyKey, AppliedClassPropertyValues> appliedStyle;
// Stores whether there are pending transitions to be done on each update.
bool hasPendingTransitions = false;
};
};
#endif
|