summaryrefslogtreecommitdiff
path: root/src/mbgl/style
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style')
-rw-r--r--src/mbgl/style/paint_properties_map.cpp114
-rw-r--r--src/mbgl/style/paint_properties_map.hpp89
-rw-r--r--src/mbgl/style/style.cpp9
-rw-r--r--src/mbgl/style/style_layer.cpp120
-rw-r--r--src/mbgl/style/style_layer.hpp97
-rw-r--r--src/mbgl/style/style_parser.cpp2
6 files changed, 232 insertions, 199 deletions
diff --git a/src/mbgl/style/paint_properties_map.cpp b/src/mbgl/style/paint_properties_map.cpp
new file mode 100644
index 0000000000..18f6867457
--- /dev/null
+++ b/src/mbgl/style/paint_properties_map.cpp
@@ -0,0 +1,114 @@
+#include <mbgl/style/paint_properties_map.hpp>
+#include <mbgl/style/property_transition.hpp>
+#include <mbgl/style/property_fallback.hpp>
+#include <mbgl/style/class_properties.hpp>
+
+namespace mbgl {
+
+void PaintPropertiesMap::cascade(const std::vector<std::string>& classes,
+ const TimePoint& now,
+ const PropertyTransition& defaultTransition) {
+ // Stores all keys that we have already added transitions for.
+ std::set<PropertyKey> alreadyApplied;
+
+ // We only apply the default style values if there are no classes set.
+ if (classes.empty()) {
+ cascadeClass(ClassID::Default, alreadyApplied, now, defaultTransition);
+ return;
+ }
+
+ // Reverse iterate through all class names and apply them last to first.
+ for (auto it = classes.rbegin(); it != classes.rend(); ++it) {
+ // From here on, we're only dealing with IDs to avoid comparing strings all the time.
+ cascadeClass(ClassDictionary::Get().lookup(*it), alreadyApplied, now, defaultTransition);
+ }
+
+ // As the last class, apply the default class.
+ cascadeClass(ClassID::Default, alreadyApplied, now, defaultTransition);
+
+ // Make sure that we also transition to the fallback value for keys that aren't changed by
+ // any applied classes.
+ for (auto& propertyPair : appliedStyle) {
+ const PropertyKey key = propertyPair.first;
+ if (alreadyApplied.find(key) != alreadyApplied.end()) {
+ // This property has already been set by a previous class, so we don't need to
+ // transition to the fallback.
+ continue;
+ }
+
+ AppliedClassPropertyValues &appliedProperties = propertyPair.second;
+ // Make sure that we don't do double transitions to the fallback value.
+ if (appliedProperties.mostRecent() == ClassID::Fallback) {
+ continue;
+ }
+
+ // This property key hasn't been set by a previous class, so we need to add a transition
+ // to the fallback value for that key.
+ const TimePoint begin = now + *defaultTransition.delay;
+ const TimePoint end = begin + *defaultTransition.duration;
+ const PropertyValue &value = PropertyFallbackValue::Get(key);
+ appliedProperties.add(ClassID::Fallback, begin, end, value);
+ }
+}
+
+void PaintPropertiesMap::cascadeClass(const ClassID classID,
+ std::set<PropertyKey>& alreadyApplied,
+ const TimePoint& now,
+ const PropertyTransition& defaultTransition) {
+ auto styleIt = paints.find(classID);
+ if (styleIt == paints.end()) {
+ // There is no class in this layer with this class_name.
+ return;
+ }
+
+ // Loop through all the properties in this style, and add transitions to them, if they're
+ // not already the most recent transition.
+ const ClassProperties& classProperties = styleIt->second;
+ for (const auto& propertyPair : classProperties) {
+ PropertyKey key = propertyPair.first;
+ if (alreadyApplied.find(key) != alreadyApplied.end()) {
+ // This property has already been set by a previous class.
+ continue;
+ }
+
+ // Mark this property as written by a previous class, so that subsequent
+ // classes won't override this.
+ alreadyApplied.insert(key);
+
+ // If the most recent transition is not the one with the highest priority, create
+ // a transition.
+ AppliedClassPropertyValues &appliedProperties = appliedStyle[key];
+ if (appliedProperties.mostRecent() != classID) {
+ PropertyTransition transition = classProperties.getTransition(key);
+ Duration delay = transition.delay ? *transition.delay : *defaultTransition.delay;
+ Duration duration = transition.duration ? *transition.duration : *defaultTransition.duration;
+ const TimePoint begin = now + delay;
+ const TimePoint end = begin + duration;
+ const PropertyValue &value = propertyPair.second;
+ appliedProperties.add(classID, begin, end, value);
+ }
+ }
+}
+
+bool PaintPropertiesMap::hasTransitions() const {
+ for (const auto& pair : appliedStyle) {
+ if (pair.second.hasTransitions()) {
+ return true;
+ }
+ }
+ return hasPendingTransitions;
+}
+
+void PaintPropertiesMap::removeExpiredTransitions(const TimePoint& now) {
+ for (auto it = appliedStyle.begin(); it != appliedStyle.end();) {
+ AppliedClassPropertyValues& values = it->second;
+ values.cleanup(now);
+ // If the current properties object is empty, remove it from the map entirely.
+ values.empty() ? appliedStyle.erase(it++) : ++it;
+ }
+
+ // Clear the pending transitions flag upon each update.
+ hasPendingTransitions = false;
+}
+
+}
diff --git a/src/mbgl/style/paint_properties_map.hpp b/src/mbgl/style/paint_properties_map.hpp
new file mode 100644
index 0000000000..14ed33fe4d
--- /dev/null
+++ b/src/mbgl/style/paint_properties_map.hpp
@@ -0,0 +1,89 @@
+#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 <map>
+#include <set>
+
+namespace mbgl {
+
+class ClassProperties;
+class PropertyTransition;
+
+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);
+
+ 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
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 84640be259..b68ce496b8 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -121,9 +121,9 @@ void Style::update(const TransformState& transform,
void Style::cascade() {
for (const auto& layer : layers) {
- layer->setClasses(data.getClasses(),
- data.getAnimationTime(),
- PropertyTransition { data.getDefaultTransitionDuration(), data.getDefaultTransitionDelay() });
+ layer->cascade(data.getClasses(),
+ data.getAnimationTime(),
+ PropertyTransition { data.getDefaultTransitionDuration(), data.getDefaultTransitionDelay() });
}
}
@@ -142,7 +142,8 @@ void Style::recalculate(float z) {
data.getDefaultFadeDuration());
for (const auto& layer : layers) {
- layer->updateProperties(parameters);
+ layer->recalculate(parameters);
+
if (!layer->bucket) {
continue;
}
diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp
index 5b87377608..eab8777d83 100644
--- a/src/mbgl/style/style_layer.cpp
+++ b/src/mbgl/style/style_layer.cpp
@@ -1,6 +1,4 @@
#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/property_fallback.hpp>
-
#include <mbgl/layer/fill_layer.hpp>
#include <mbgl/layer/line_layer.hpp>
#include <mbgl/layer/circle_layer.hpp>
@@ -29,122 +27,18 @@ std::unique_ptr<StyleLayer> StyleLayer::create(StyleLayerType type) {
}
}
-bool StyleLayer::hasRenderPass(RenderPass pass) const {
- return bool(passes & pass);
-}
-
-void StyleLayer::setClasses(const std::vector<std::string> &class_names, const TimePoint& now,
- const PropertyTransition &defaultTransition) {
- // Stores all keys that we have already added transitions for.
- std::set<PropertyKey> already_applied;
-
- // We only apply the default style values if there are no classes set.
- if (class_names.empty()) {
- applyClassProperties(ClassID::Default, already_applied, now, defaultTransition);
- return;
- }
-
- // Reverse iterate through all class names and apply them last to first.
- for (auto it = class_names.rbegin(); it != class_names.rend(); ++it) {
- const std::string &class_name = *it;
- // From here on, we're only dealing with IDs to avoid comparing strings all the time.
- const ClassID class_id = ClassDictionary::Get().lookup(class_name);
- applyClassProperties(class_id, already_applied, now, defaultTransition);
- }
-
- // As the last class, apply the default class.
- applyClassProperties(ClassID::Default, already_applied, now, defaultTransition);
-
- // Make sure that we also transition to the fallback value for keys that aren't changed by
- // any applied classes.
- for (auto& property_pair : appliedStyle) {
- const PropertyKey key = property_pair.first;
- if (already_applied.find(key) != already_applied.end()) {
- // This property has already been set by a previous class, so we don't need to
- // transition to the fallback.
- continue;
- }
-
- AppliedClassPropertyValues &appliedProperties = property_pair.second;
- // Make sure that we don't do double transitions to the fallback value.
- if (appliedProperties.mostRecent() == ClassID::Fallback) {
- continue;
- }
-
- // This property key hasn't been set by a previous class, so we need to add a transition
- // to the fallback value for that key.
- const TimePoint begin = now + *defaultTransition.delay;
- const TimePoint end = begin + *defaultTransition.duration;
- const PropertyValue &value = PropertyFallbackValue::Get(key);
- appliedProperties.add(ClassID::Fallback, begin, end, value);
- }
-}
-
-// Helper function for applying all properties of a a single class that haven't been applied yet.
-void StyleLayer::applyClassProperties(const ClassID class_id,
- std::set<PropertyKey> &already_applied, const TimePoint& now,
- const PropertyTransition &defaultTransition) {
- auto style_it = styles.find(class_id);
- if (style_it == styles.end()) {
- // There is no class in this layer with this class_name.
- return;
- }
-
- // Loop through all the properties in this style, and add transitions to them, if they're
- // not already the most recent transition.
- const ClassProperties &class_properties = style_it->second;
- for (const auto& property_pair : class_properties) {
- PropertyKey key = property_pair.first;
- if (already_applied.find(key) != already_applied.end()) {
- // This property has already been set by a previous class.
- continue;
- }
-
- // Mark this property as written by a previous class, so that subsequent
- // classes won't override this.
- already_applied.insert(key);
-
- // If the most recent transition is not the one with the highest priority, create
- // a transition.
- AppliedClassPropertyValues &appliedProperties = appliedStyle[key];
- if (appliedProperties.mostRecent() != class_id) {
- PropertyTransition transition = class_properties.getTransition(key);
- Duration delay = transition.delay ? *transition.delay : *defaultTransition.delay;
- Duration duration = transition.duration ? *transition.duration : *defaultTransition.duration;
- const TimePoint begin = now + delay;
- const TimePoint end = begin + duration;
- const PropertyValue &value = property_pair.second;
- appliedProperties.add(class_id, begin, end, value);
- }
- }
-}
-
-void StyleLayer::updateProperties(const StyleCalculationParameters& parameters) {
- cleanupAppliedStyleProperties(parameters.now);
-
- // Clear the pending transitions flag upon each update.
- hasPendingTransitions = false;
-
- // Update the render passes when this layer is visible.
- passes = applyStyleProperties(parameters);
+void StyleLayer::cascade(const std::vector<std::string>& classes,
+ const TimePoint& now,
+ const PropertyTransition& defaultTransition) {
+ paints.cascade(classes, now, defaultTransition);
}
bool StyleLayer::hasTransitions() const {
- for (const auto& pair : appliedStyle) {
- if (pair.second.hasTransitions()) {
- return true;
- }
- }
- return hasPendingTransitions;
+ return paints.hasTransitions();
}
-void StyleLayer::cleanupAppliedStyleProperties(const TimePoint& now) {
- for (auto it = appliedStyle.begin(); it != appliedStyle.end();) {
- AppliedClassPropertyValues& values = it->second;
- values.cleanup(now);
- // If the current properties object is empty, remove it from the map entirely.
- values.empty() ? appliedStyle.erase(it++) : ++it;
- }
+bool StyleLayer::hasRenderPass(RenderPass pass) const {
+ return bool(passes & pass);
}
}
diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp
index b6ff6ae8f7..43d595bb38 100644
--- a/src/mbgl/style/style_layer.hpp
+++ b/src/mbgl/style/style_layer.hpp
@@ -3,26 +3,23 @@
#include <mbgl/style/class_dictionary.hpp>
#include <mbgl/style/class_properties.hpp>
-#include <mbgl/style/applied_class_properties.hpp>
-#include <mbgl/style/zoom_history.hpp>
-#include <mbgl/style/property_evaluator.hpp>
-#include <mbgl/style/style_calculation_parameters.hpp>
+#include <mbgl/style/paint_properties_map.hpp>
#include <mbgl/renderer/render_pass.hpp>
-#include <mbgl/util/ptr.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/interpolate.hpp>
+#include <mbgl/util/ptr.hpp>
#include <vector>
#include <string>
#include <map>
-#include <set>
namespace mbgl {
class StyleBucket;
+class StyleCalculationParameters;
+class PropertyTransition;
class StyleLayer : public util::noncopyable {
public:
@@ -30,97 +27,35 @@ public:
virtual ~StyleLayer() = default;
- // Checks whether this layer needs to be rendered in the given render pass.
- bool hasRenderPass(RenderPass) const;
-
- // Updates the StyleProperties information in this layer by evaluating all
- // pending transitions and applied classes in order.
- void updateProperties(const StyleCalculationParameters&);
+ // Partially evaluate paint properties based on a set of classes.
+ void cascade(const std::vector<std::string>& classNames,
+ const TimePoint& now,
+ const PropertyTransition& defaultTransition);
- // Sets the list of classes and creates transitions to the currently applied values.
- void setClasses(const std::vector<std::string> &class_names, const TimePoint& now,
- const PropertyTransition &defaultTransition);
+ // Fully evaluate cascaded paint properties based on a zoom level.
+ virtual void recalculate(const StyleCalculationParameters&) = 0;
+ // Checks whether this layer has any active paint properties with transitions.
bool hasTransitions() const;
+ // Checks whether this layer needs to be rendered in the given render pass.
+ bool hasRenderPass(RenderPass) const;
+
public:
- // The name of this layer.
std::string id;
-
StyleLayerType type = StyleLayerType::Unknown;
// Bucket information, telling the renderer how to generate the geometries
// for this layer (feature property filters, tessellation instructions, ...).
util::ptr<StyleBucket> bucket;
- // Contains all style classes that can be applied to this layer.
- std::map<ClassID, ClassProperties> styles;
+ // Contains all paint classes that can be applied to this layer.
+ PaintPropertiesMap paints;
protected:
- // TODO: extract
- template <typename T>
- void applyStyleProperty(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 applyTransitionedStyleProperty(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.
- }
- }
- }
- }
-
-private:
- // Applies all properties from a class, if they haven't been applied already.
- void applyClassProperties(ClassID class_id, std::set<PropertyKey> &already_applied,
- const TimePoint& now, const PropertyTransition &defaultTransition);
-
- // Sets the properties of this object by evaluating all pending transitions and
- // aplied classes in order.
- virtual RenderPass applyStyleProperties(const StyleCalculationParameters&) = 0;
-
- // Removes all expired style transitions.
- void cleanupAppliedStyleProperties(const TimePoint& now);
-
- // For every property, stores a list of applied property values, with
- // optional transition times.
- std::map<PropertyKey, AppliedClassPropertyValues> appliedStyle;
-
// Stores what render passes this layer is currently enabled for. This depends on the
// evaluated StyleProperties object and is updated accordingly.
RenderPass passes = RenderPass::None;
-
- // Stores whether there are pending transitions to be done on each update.
- bool hasPendingTransitions = false;
};
}
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp
index 391f6b0e21..3aecfa51eb 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/style_parser.cpp
@@ -798,7 +798,7 @@ void StyleParser::parseLayer(const std::string& id, JSVal value, util::ptr<Style
std::map<ClassID, ClassProperties> paints;
parsePaints(value, paints);
- layer->styles = std::move(paints);
+ layer->paints.paints = std::move(paints);
}
#pragma mark - Parse Styles