diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-07-16 18:53:56 -0700 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-07-16 18:53:56 -0700 |
commit | 4ea281c750c5afcc68f2832bb42d98a1cbce6735 (patch) | |
tree | 60bc7d3ccba2c54859e2e023997cc027cc67aea7 /include/mbgl/style | |
parent | c1a64dc5fa73b54cc5de77629781dfc74302a1e7 (diff) | |
download | qtlocation-mapboxgl-4ea281c750c5afcc68f2832bb42d98a1cbce6735.tar.gz |
rename llmr => mbgl
Diffstat (limited to 'include/mbgl/style')
23 files changed, 1419 insertions, 0 deletions
diff --git a/include/mbgl/style/applied_class_properties.hpp b/include/mbgl/style/applied_class_properties.hpp new file mode 100644 index 0000000000..827f15a2a1 --- /dev/null +++ b/include/mbgl/style/applied_class_properties.hpp @@ -0,0 +1,39 @@ +#ifndef MBGL_STYLE_APPLIED_CLASS_PROPERTIES +#define MBGL_STYLE_APPLIED_CLASS_PROPERTIES + +#include <mbgl/style/property_value.hpp> +#include <mbgl/style/class_dictionary.hpp> +#include <mbgl/util/time.hpp> + +#include <list> + +namespace mbgl { + +class AppliedClassProperty { +public: + AppliedClassProperty(ClassID class_id, timestamp begin, timestamp end, const PropertyValue &value); + +public: + const ClassID name; + const timestamp begin; + const timestamp end; + const PropertyValue value; +}; + + +class AppliedClassProperties { +public: + std::list<AppliedClassProperty> properties; + +public: + // Returns thie ID of the most recent + ClassID mostRecent() const; + void add(ClassID class_id, timestamp begin, timestamp end, const PropertyValue &value); + bool hasTransitions() const; + void cleanup(timestamp now); + bool empty() const; +}; + +} + +#endif diff --git a/include/mbgl/style/class_dictionary.hpp b/include/mbgl/style/class_dictionary.hpp new file mode 100644 index 0000000000..c7f9c6a284 --- /dev/null +++ b/include/mbgl/style/class_dictionary.hpp @@ -0,0 +1,32 @@ +#ifndef MBGL_STYLE_CLASS_DICTIONARY +#define MBGL_STYLE_CLASS_DICTIONARY + +#include <cstdint> +#include <string> +#include <unordered_map> + +namespace mbgl { + +enum class ClassID : uint32_t { + Fallback = 0, // These values are from the fallback properties + Default = 1, // These values are from the default style for a layer + Named = 2 // These values (and all subsequent IDs) are from a named style from the layer +}; + +class ClassDictionary { +public: + // Returns an ID for a class name. If the class name does not yet have an ID, one is + // auto-generated and stored for future reference. + static ClassID Lookup(const std::string &class_name); + + // Returns either Fallback, Default or Named, depending on the type of the class id. + static ClassID Normalize(ClassID id); + +private: + static std::unordered_map<std::string, ClassID> store; + static uint32_t offset; +}; + +} + +#endif diff --git a/include/mbgl/style/class_properties.hpp b/include/mbgl/style/class_properties.hpp new file mode 100644 index 0000000000..84b6f483bd --- /dev/null +++ b/include/mbgl/style/class_properties.hpp @@ -0,0 +1,43 @@ +#ifndef MBGL_STYLE_CLASS_PROPERTIES +#define MBGL_STYLE_CLASS_PROPERTIES + +#include <mbgl/style/property_key.hpp> +#include <mbgl/style/property_value.hpp> +#include <mbgl/style/property_transition.hpp> + +#include <map> + +namespace mbgl { + +class ClassProperties { +public: + inline ClassProperties() {} + inline ClassProperties(ClassProperties &&properties) + : properties(std::move(properties.properties)) {} + + inline void set(PropertyKey key, const PropertyValue &value) { + properties.emplace(key, value); + } + + inline void set(PropertyKey key, const PropertyTransition &transition) { + transitions.emplace(key, transition); + } + + const PropertyTransition &getTransition(PropertyKey key, const PropertyTransition &defaultTransition) const; + + // Route-through iterable interface so that you can iterate on the object as is. + inline std::map<PropertyKey, PropertyValue>::const_iterator begin() const { + return properties.begin(); + } + inline std::map<PropertyKey, PropertyValue>::const_iterator end() const { + return properties.end(); + } + +public: + std::map<PropertyKey, PropertyValue> properties; + std::map<PropertyKey, PropertyTransition> transitions; +}; + +} + +#endif diff --git a/include/mbgl/style/filter_comparison.hpp b/include/mbgl/style/filter_comparison.hpp new file mode 100644 index 0000000000..bf48744f1e --- /dev/null +++ b/include/mbgl/style/filter_comparison.hpp @@ -0,0 +1,65 @@ +#ifndef MBGL_STYLE_FILTER_COMPARISON +#define MBGL_STYLE_FILTER_COMPARISON + +#include <mbgl/style/value.hpp> + +#include <vector> +#include <string> +#include <iosfwd> + +namespace mbgl { + +class FilterComparison { +public: + enum class Operator : uint8_t { + Equal, + NotEqual, + Greater, + GreaterEqual, + Less, + LessEqual, + In, + NotIn + }; + + class Instance { + public: + Instance(Operator op, std::vector<Value> &&values) + : op(op), values(values) {} + + bool compare(const std::vector<Value> &property_values) const; + + private: + Operator op = Operator::Equal; + std::vector<Value> values; + + friend std::ostream& operator <<(std::ostream &, const Instance &); + }; + +public: + FilterComparison(const std::string &field) : field(field) {}; + + const std::string &getField() const; + template <typename Extractor> inline bool compare(const Extractor &extractor) const; + + template <typename ...Args> + inline void add(Args&& ...args) { + instances.emplace_back(::std::forward<Args>(args)...); + } + +private: + std::string field; + std::vector<Instance> instances; + + friend std::ostream& operator <<(std::ostream &, const FilterComparison &); +}; + +std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison); +std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance); + + +FilterComparison::Operator parseFilterComparisonOperator(const std::string &op); + +} + +#endif diff --git a/include/mbgl/style/filter_comparison_private.hpp b/include/mbgl/style/filter_comparison_private.hpp new file mode 100644 index 0000000000..6486832424 --- /dev/null +++ b/include/mbgl/style/filter_comparison_private.hpp @@ -0,0 +1,23 @@ +#ifndef MBGL_STYLE_FILTER_COMPARISON_PRIVATE +#define MBGL_STYLE_FILTER_COMPARISON_PRIVATE + +#include "filter_comparison.hpp" + +namespace mbgl { + +template <typename Extractor> +inline bool FilterComparison::compare(const Extractor &extractor) const { + const std::vector<Value> values = extractor.getValues(field); + + // All instances are ANDed together. + for (const Instance &instance : instances) { + if (!instance.compare(values)) { + return false; + } + } + return true; +} + +} + +#endif diff --git a/include/mbgl/style/filter_expression.hpp b/include/mbgl/style/filter_expression.hpp new file mode 100644 index 0000000000..2a6a2927e7 --- /dev/null +++ b/include/mbgl/style/filter_expression.hpp @@ -0,0 +1,54 @@ +#ifndef MBGL_STYLE_FILTER_EXPRESSION +#define MBGL_STYLE_FILTER_EXPRESSION + +#include <mbgl/style/filter_comparison.hpp> +#include <mbgl/util/recursive_wrapper.hpp> + +#include <iosfwd> + +namespace mbgl { + +class FilterExpression { +public: + typedef util::recursive_wrapper<FilterExpression> Wrapper; + + enum class Operator : uint8_t { + And, + Or, + Xor, + Nor + }; + + enum class GeometryType : uint8_t { + Any, + Point, + LineString, + Polygon + }; + +public: + FilterExpression() = default; + FilterExpression(Operator op) : op(op) {}; + + bool empty() const; + + template <typename Extractor> bool compare(const Extractor &extractor) const; + void add(const FilterComparison &comparison); + void add(const FilterExpression &expression); + void setGeometryType(GeometryType g); + +private: + Operator op = Operator::And; + GeometryType type = GeometryType::Any; + std::vector<FilterComparison> comparisons; + std::vector<FilterExpression::Wrapper> expressions; + + friend std::ostream& operator <<(std::ostream &, const FilterExpression &); +}; + +std::ostream& operator <<(std::ostream &s, const FilterExpression &expression); + +FilterExpression::GeometryType parseGeometryType(const std::string &geometry); +} + +#endif diff --git a/include/mbgl/style/filter_expression_private.hpp b/include/mbgl/style/filter_expression_private.hpp new file mode 100644 index 0000000000..9379d250ba --- /dev/null +++ b/include/mbgl/style/filter_expression_private.hpp @@ -0,0 +1,75 @@ +#ifndef MBGL_STYLE_FILTER_EXPRESSION_PRIVATE +#define MBGL_STYLE_FILTER_EXPRESSION_PRIVATE + +#include "filter_expression.hpp" +#include "filter_comparison_private.hpp" + +namespace mbgl { + +template <typename Extractor> +bool FilterExpression::compare(const Extractor &extractor) const { + if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) { + return false; + } + + switch (op) { + case Operator::And: + for (const FilterComparison &comparison : comparisons) { + if (!comparison.compare(extractor)) { + return false; + } + } + for (const FilterExpression &expression: expressions) { + if (!expression.compare(extractor)) { + return false; + } + } + return true; + case Operator::Or: + for (const FilterComparison &comparison : comparisons) { + if (comparison.compare(extractor)) { + return true; + } + } + for (const FilterExpression &expression: expressions) { + if (expression.compare(extractor)) { + return true; + } + } + return false; + case Operator::Xor: { + int count = 0; + for (const FilterComparison &comparison : comparisons) { + count += comparison.compare(extractor); + if (count > 1) { + return false; + } + } + for (const FilterExpression &expression: expressions) { + count += expression.compare(extractor); + if (count > 1) { + return false; + } + } + return count == 1; + } + case Operator::Nor: + for (const FilterComparison &comparison : comparisons) { + if (comparison.compare(extractor)) { + return false; + } + } + for (const FilterExpression &expression: expressions) { + if (expression.compare(extractor)) { + return false; + } + } + return true; + default: + return true; + } +} + +} + +#endif diff --git a/include/mbgl/style/function_properties.hpp b/include/mbgl/style/function_properties.hpp new file mode 100644 index 0000000000..74ac80f83c --- /dev/null +++ b/include/mbgl/style/function_properties.hpp @@ -0,0 +1,79 @@ +#ifndef MBGL_STYLE_FUNCTION_PROPERTIES +#define MBGL_STYLE_FUNCTION_PROPERTIES + +#include <mbgl/util/variant.hpp> + +#include <vector> + +namespace mbgl { + +template <typename T> +struct ConstantFunction { + inline ConstantFunction(const T &value) : value(value) {} + inline T evaluate(float) const { return value; } + +private: + const T value; +}; + +template <typename T> +struct LinearFunction { + inline LinearFunction(const T &value, float z_base, float slope, const T &min, const T &max) + : value(value), min(min), max(max), z_base(z_base), slope(slope) {} + T evaluate(float z) const; + +private: + const T value, min, max; + const float z_base, slope; +}; + +template <typename T> +struct ExponentialFunction { + inline ExponentialFunction(const T &value, float z_base, float exp_base, float slope, const T &min, + const T &max) + : value(value), min(min), max(max), z_base(z_base), exp_base(exp_base), slope(slope) {} + T evaluate(float z) const; + +private: + const T value, min, max; + const float z_base, exp_base, slope; +}; + +template <typename T> +struct StopsFunction { + inline StopsFunction(const std::vector<std::pair<float, T>> &values) : values(values) {} + T evaluate(float z) const; + +private: + const std::vector<std::pair<float, T>> values; +}; + +template <typename T> +using Function = util::variant< + std::false_type, + ConstantFunction<T>, + LinearFunction<T>, + ExponentialFunction<T>, + StopsFunction<T> +>; + +template <typename T> +struct FunctionEvaluator { + typedef T result_type; + inline FunctionEvaluator(float z) : z(z) {} + + inline result_type operator()(const std::false_type &) { + return result_type(); + } + + template <template <typename> class Fn> + inline result_type operator()(const Fn<T>& fn) { + return fn.evaluate(z); + } +private: + float z; +}; + +} + +#endif diff --git a/include/mbgl/style/property_fallback.hpp b/include/mbgl/style/property_fallback.hpp new file mode 100644 index 0000000000..5c5eae0cd6 --- /dev/null +++ b/include/mbgl/style/property_fallback.hpp @@ -0,0 +1,29 @@ +#ifndef MBGL_STYLE_PROPERTY_FALLBACK +#define MBGL_STYLE_PROPERTY_FALLBACK + +#include <mbgl/style/property_key.hpp> +#include <mbgl/style/property_value.hpp> + +#include <map> + +namespace mbgl { + +class PropertyFallbackValue { +public: + static const PropertyValue &Get(PropertyKey key) { + auto it = properties.find(key); + if (it != properties.end()) { + return it->second; + } else { + return defaultProperty; + } + } + +private: + static const std::map<PropertyKey, PropertyValue> properties; + static const PropertyValue defaultProperty; +}; + +} + +#endif diff --git a/include/mbgl/style/property_key.hpp b/include/mbgl/style/property_key.hpp new file mode 100644 index 0000000000..d9005f2f4a --- /dev/null +++ b/include/mbgl/style/property_key.hpp @@ -0,0 +1,57 @@ +#ifndef MBGL_STYLE_PROPERTY_KEY +#define MBGL_STYLE_PROPERTY_KEY + +namespace mbgl { + +enum class PropertyKey { + FillAntialias, + FillOpacity, + FillColor, + FillOutlineColor, + FillTranslate, // for transitions only + FillTranslateX, + FillTranslateY, + FillTranslateAnchor, + FillImage, + + LineOpacity, + LineColor, + LineTranslate, // for transitions only + LineTranslateX, + LineTranslateY, + LineTranslateAnchor, + LineWidth, + LineOffset, + LineBlur, + LineDashArray, // for transitions only + LineDashLand, + LineDashGap, + LineImage, + + IconOpacity, + IconRotate, + IconRotateAnchor, + + TextOpacity, + TextSize, + TextColor, + TextHaloColor, + TextHaloWidth, + TextHaloBlur, + + CompositeOpacity, + + RasterOpacity, + RasterSpin, + RasterBrightnessLow, + RasterBrightnessHigh, + RasterSaturation, + RasterContrast, + RasterFade, + + BackgroundColor +}; + +} + +#endif diff --git a/include/mbgl/style/property_transition.hpp b/include/mbgl/style/property_transition.hpp new file mode 100644 index 0000000000..07b7cfe288 --- /dev/null +++ b/include/mbgl/style/property_transition.hpp @@ -0,0 +1,15 @@ +#ifndef MBGL_STYLE_PROPERTY_TRANSITION +#define MBGL_STYLE_PROPERTY_TRANSITION + +#include <cstdint> + +namespace mbgl { + +struct PropertyTransition { + uint16_t duration = 0; + uint16_t delay = 0; +}; + +} + +#endif
\ No newline at end of file diff --git a/include/mbgl/style/property_value.hpp b/include/mbgl/style/property_value.hpp new file mode 100644 index 0000000000..4d148dc029 --- /dev/null +++ b/include/mbgl/style/property_value.hpp @@ -0,0 +1,21 @@ +#ifndef MBGL_STYLE_PROPERTY_VALUE +#define MBGL_STYLE_PROPERTY_VALUE + +#include <mbgl/util/variant.hpp> +#include <mbgl/style/function_properties.hpp> +#include <mbgl/style/types.hpp> + +namespace mbgl { + +typedef util::variant< + std::string, + TranslateAnchorType, + RotateAnchorType, + Function<bool>, + Function<float>, + Function<Color> +> PropertyValue; + +} + +#endif diff --git a/include/mbgl/style/rasterize_properties.hpp b/include/mbgl/style/rasterize_properties.hpp new file mode 100644 index 0000000000..aea90dfbdd --- /dev/null +++ b/include/mbgl/style/rasterize_properties.hpp @@ -0,0 +1,38 @@ +#ifndef MBGL_STYLE_RASTERIZE_PROPERTIES +#define MBGL_STYLE_RASTERIZE_PROPERTIES + +#include <mbgl/style/function_properties.hpp> + +namespace mbgl { + +// The calculated properties for a layer in a tile. +class RasterizedProperties { +public: + float buffer = 1.0f / 32.0f; + uint16_t size = 256; + uint8_t blur = 0; +}; + +class RasterizeProperties { +public: + Function<bool> enabled = ConstantFunction<bool>(false); + Function<float> buffer = ConstantFunction<float>(1.0f / 32.0f); + Function<float> size = ConstantFunction<float>(256); + Function<float> blur = ConstantFunction<float>(0); + + inline bool isEnabled(const int8_t z) const { + return util::apply_visitor(FunctionEvaluator<bool>(z), enabled); + } + + inline RasterizedProperties get(const int8_t z) const { + RasterizedProperties properties; + properties.buffer = util::apply_visitor(FunctionEvaluator<float>(z), buffer); + properties.size = util::apply_visitor(FunctionEvaluator<float>(z), size); + properties.blur = util::apply_visitor(FunctionEvaluator<float>(z), blur); + return properties; + } +}; + +} + +#endif diff --git a/include/mbgl/style/style.hpp b/include/mbgl/style/style.hpp new file mode 100644 index 0000000000..6aab71a4c6 --- /dev/null +++ b/include/mbgl/style/style.hpp @@ -0,0 +1,68 @@ +#ifndef MBGL_STYLE_STYLE +#define MBGL_STYLE_STYLE + +#include <mbgl/style/property_transition.hpp> +#include <mbgl/style/style_source.hpp> + +#include <mbgl/util/time.hpp> +#include <mbgl/util/uv.hpp> + +#include <cstdint> +#include <map> +#include <string> +#include <unordered_map> +#include <vector> +#include <set> +#include <memory> + +namespace mbgl { + +class Sprite; +class StyleLayer; +class StyleLayerGroup; +struct BackgroundProperties; + +class Style { +public: + struct exception : std::runtime_error { exception(const char *msg) : std::runtime_error(msg) {} }; + +public: + Style(); + + void loadJSON(const uint8_t *const data); + + size_t layerCount() const; + void updateProperties(float z, timestamp t); + + void setDefaultTransitionDuration(uint16_t duration_milliseconds = 0); + + void setAppliedClasses(const std::vector<std::string> &classes); + const std::vector<std::string> &getAppliedClasses() const; + void toggleClass(const std::string &name); + + // Updates the styling information to reflect the current array + // of applied classes. + void updateClasses(); + + bool hasTransitions() const; + + const BackgroundProperties &getBackgroundProperties() const; + +public: + std::shared_ptr<Sprite> sprite; + std::shared_ptr<StyleLayerGroup> layers; + std::vector<std::string> appliedClasses; + std::string sprite_url; + std::string glyph_url; + + +private: + PropertyTransition defaultTransition; + bool initial_render_complete = false; + + mutable uv::rwlock mtx; +}; + +} + +#endif diff --git a/include/mbgl/style/style_bucket.hpp b/include/mbgl/style/style_bucket.hpp new file mode 100644 index 0000000000..62f072d9cd --- /dev/null +++ b/include/mbgl/style/style_bucket.hpp @@ -0,0 +1,88 @@ +#ifndef MBGL_STYLE_STYLE_BUCKET +#define MBGL_STYLE_STYLE_BUCKET + +#include <mbgl/style/types.hpp> +#include <mbgl/style/filter_expression.hpp> +#include <mbgl/style/style_source.hpp> +#include <mbgl/util/vec.hpp> +#include <mbgl/util/variant.hpp> + +#include <memory> +#include <forward_list> + +namespace mbgl { + +class Source; + +class StyleBucketFill { +public: + WindingType winding = WindingType::Default; +}; + +class StyleBucketLine { +public: + CapType cap = CapType::Default; + JoinType join = JoinType::Default; + float miter_limit = 2.0f; + float round_limit = 1.0f; +}; + +class StyleBucketIcon { +public: + uint16_t size = 16; + vec2<float> translate {0, 0}; + TranslateAnchorType translate_anchor = TranslateAnchorType::Default; + std::string icon; + float spacing = 0.0f; + float padding = 2.0f; +}; + +class StyleBucketText { +public: + std::string field; + TextPathType path = TextPathType::Default; + TextTransformType transform = TextTransformType::Default; + std::string font; + float max_size = 16.0f; + float max_width = 15.0f * 24; + float line_height = 1.2f * 24; + float letter_spacing = 0.0f; + float alignment = 0.5f; + float vertical_alignment = 0.5; + vec2<float> translate {0, 0}; + TranslateAnchorType translate_anchor = TranslateAnchorType::Default; + float max_angle_delta = M_PI; + float min_distance = 250.0f; + float rotate = 0.0f; // what is this? + float padding = 2.0f; + float slant = 0.0f; + bool always_visible = false; +}; + +class StyleBucketRaster { +public: +}; + +typedef util::variant<StyleBucketFill, StyleBucketLine, StyleBucketIcon, + StyleBucketText, StyleBucketRaster, + std::false_type> StyleBucketRender; + + +class StyleBucket { +public: + typedef std::shared_ptr<StyleBucket> Ptr; + + StyleBucket(StyleLayerType type); + + std::string name; + std::shared_ptr<StyleSource> style_source; + std::string source_layer; + FilterExpression filter; + StyleBucketRender render = std::false_type(); +}; + + + +}; + +#endif diff --git a/include/mbgl/style/style_layer.hpp b/include/mbgl/style/style_layer.hpp new file mode 100644 index 0000000000..14d60ed9b6 --- /dev/null +++ b/include/mbgl/style/style_layer.hpp @@ -0,0 +1,94 @@ +#ifndef MBGL_STYLE_STYLE_LAYER +#define MBGL_STYLE_STYLE_LAYER + +#include <mbgl/style/class_dictionary.hpp> +#include <mbgl/style/class_properties.hpp> +#include <mbgl/style/style_properties.hpp> +#include <mbgl/style/rasterize_properties.hpp> +#include <mbgl/style/applied_class_properties.hpp> + +#include <vector> +#include <memory> +#include <string> +#include <map> +#include <set> + +namespace mbgl { + +class StyleBucket; +class StyleLayerGroup; + +class StyleLayer { +public: + StyleLayer(const std::string &id, std::map<ClassID, ClassProperties> &&styles, + std::unique_ptr<const RasterizeProperties> &&rasterize); + + template <typename T> const T &getProperties() { + if (properties.is<T>()) { + return properties.get<T>(); + } else { + return defaultStyleProperties<T>(); + } + } + + // Determines whether this layer is the background layer. + bool isBackground() const; + + // Updates the StyleProperties information in this layer by evaluating all + // pending transitions and applied classes in order. + void updateProperties(float z, timestamp now); + + // Sets the list of classes and creates transitions to the currently applied values. + void setClasses(const std::vector<std::string> &class_names, timestamp now, + const PropertyTransition &defaultTransition); + + bool hasTransitions() const; + +private: + // Applies all properties from a class, if they haven't been applied already. + void applyClassProperties(ClassID class_id, std::set<PropertyKey> &already_applied, + timestamp now, const PropertyTransition &defaultTransition); + + // 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); + + // Removes all expired style transitions. + void cleanupAppliedStyleProperties(timestamp now); + +public: + // The name of this layer. + const 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, ...). + std::shared_ptr<StyleBucket> bucket; + + // Contains all style classes that can be applied to this layer. + const std::map<ClassID, ClassProperties> styles; + +private: + // For every property, stores a list of applied property values, with + // optional transition times. + std::map<PropertyKey, AppliedClassProperties> appliedStyle; + +public: + // Stores the evaluated, and cascaded styling information, specific to this + // layer's type. + StyleProperties properties; + + // Rasterization properties are used for prerendering the tile to a bitmap, + // which is then used as a raster image instead of rendering this layer + // directly in every frame. + const std::unique_ptr<const RasterizeProperties> rasterize; + + // Child layer array (if this layer has child layers). + std::shared_ptr<StyleLayerGroup> layers; +}; + +} + +#endif diff --git a/include/mbgl/style/style_layer_group.hpp b/include/mbgl/style/style_layer_group.hpp new file mode 100644 index 0000000000..983dd136f0 --- /dev/null +++ b/include/mbgl/style/style_layer_group.hpp @@ -0,0 +1,23 @@ +#ifndef MBGL_STYLE_STYLE_LAYER_GROUP +#define MBGL_STYLE_STYLE_LAYER_GROUP + +#include <mbgl/style/style_layer.hpp> + +#include <vector> + +namespace mbgl { + +class StyleLayerGroup { +public: + void setClasses(const std::vector<std::string> &class_names, timestamp now, + const PropertyTransition &defaultTransition); + void updateProperties(float z, timestamp t); + + bool hasTransitions() const; +public: + std::vector<std::shared_ptr<StyleLayer>> layers; +}; + +} + +#endif diff --git a/include/mbgl/style/style_parser.hpp b/include/mbgl/style/style_parser.hpp new file mode 100644 index 0000000000..431e3af8db --- /dev/null +++ b/include/mbgl/style/style_parser.hpp @@ -0,0 +1,119 @@ +#ifndef MBGL_STYLE_STYLE_PARSER +#define MBGL_STYLE_STYLE_PARSER + +#include <rapidjson/document.h> +#include <mbgl/style/style.hpp> +#include <mbgl/style/style_source.hpp> +#include <mbgl/style/filter_expression.hpp> +#include <mbgl/style/class_properties.hpp> +#include <mbgl/style/rasterize_properties.hpp> +#include <mbgl/style/style_bucket.hpp> + +#include <unordered_map> +#include <forward_list> +#include <tuple> + +namespace mbgl { + +enum class ClassID : uint32_t; + +class StyleLayer; +class StyleLayerGroup; + +class StyleParser { +public: + using JSVal = const rapidjson::Value&; + + StyleParser(); + + void parse(JSVal document); + + std::shared_ptr<StyleLayerGroup> getLayers() { + return root; + } + + std::string getSprite() const { + return sprite; + } + + std::string getGlyphURL() const { + return glyph_url; + } + +private: + void parseConstants(JSVal value); + JSVal replaceConstant(JSVal value); + + void parseSources(JSVal value); + + std::unique_ptr<StyleLayerGroup> createLayers(JSVal value); + std::shared_ptr<StyleLayer> createLayer(JSVal value); + void parseLayers(); + void parseLayer(std::pair<JSVal, std::shared_ptr<StyleLayer>> &pair); + void parseStyles(JSVal value, std::map<ClassID, ClassProperties> &styles); + void parseStyle(JSVal, ClassProperties &properties); + std::unique_ptr<RasterizeProperties> parseRasterize(JSVal value); + void parseReference(JSVal value, std::shared_ptr<StyleLayer> &layer); + void parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer); + void parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer); + void parseSprite(JSVal value); + void parseGlyphURL(JSVal value); + + // Parses optional properties into a render bucket. + template<typename T> + bool parseRenderProperty(JSVal value, T &target, const char *name); + template <typename T, typename Parser> + bool parseRenderProperty(JSVal value, T &target, const char *name, Parser &parser); + + // Parses optional properties into style class properties. + template <typename T> + bool parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value); + template <typename T> + bool parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value); + template <typename T> + bool parseOptionalProperty(const char *property_name, T &target, JSVal value); + template <typename T> + bool setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass); + template <typename T> + bool setProperty(JSVal value, const char *property_name, T &target); + + template <typename T> + std::tuple<bool, T> parseProperty(JSVal value, const char *property_name); + + template <typename T> + bool parseFunction(PropertyKey key, ClassProperties &klass, JSVal value); + template <typename T> + std::tuple<bool, Function<T>> parseFunction(JSVal value); + template <typename T> + T parseFunctionArgument(JSVal value); + + + FilterExpression parseFilter(JSVal, FilterExpression::Operator op); + FilterExpression parseFilter(JSVal); + Value parseValue(JSVal value); + std::vector<Value> parseValues(JSVal values); + +private: + std::unordered_map<std::string, const rapidjson::Value *> constants; + + std::unordered_map<std::string, const std::shared_ptr<StyleSource>> sources; + + // This stores the root layer. + std::shared_ptr<StyleLayerGroup> root; + + // This maps ids to Layer objects, with all items being at the root level. + std::unordered_map<std::string, std::pair<JSVal, std::shared_ptr<StyleLayer>>> layers; + + // Store a stack of layers we're parsing right now. This is to prevent reference cycles. + std::forward_list<StyleLayer *> stack; + + // Base URL of the sprite image. + std::string sprite; + + // URL template for glyph PBFs. + std::string glyph_url; +}; + +} + +#endif diff --git a/include/mbgl/style/style_properties.hpp b/include/mbgl/style/style_properties.hpp new file mode 100644 index 0000000000..c7606be254 --- /dev/null +++ b/include/mbgl/style/style_properties.hpp @@ -0,0 +1,116 @@ +#ifndef MBGL_STYLE_STYLE_PROPERTIES +#define MBGL_STYLE_STYLE_PROPERTIES + +#include <mbgl/util/variant.hpp> +#include <mbgl/style/types.hpp> +#include <mbgl/style/function_properties.hpp> + +#include <array> +#include <string> +#include <type_traits> +#include <memory> + +namespace mbgl { + +struct FillProperties { + FillProperties() {} + bool antialias = true; + float opacity = 1.0f; + Color fill_color = {{ 0, 0, 0, 1 }}; + Color stroke_color = {{ 0, 0, 0, -1 }}; + std::array<float, 2> translate = {{ 0, 0 }}; + TranslateAnchorType translateAnchor = TranslateAnchorType::Default; + std::string image; + + inline bool isVisible() const { + return opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0); + } +}; + +struct LineProperties { + inline LineProperties() {} + float opacity = 1.0f; + Color color = {{ 0, 0, 0, 1 }}; + std::array<float, 2> translate = {{ 0, 0 }}; + TranslateAnchorType translateAnchor = TranslateAnchorType::Default; + float width = 0; + float offset = 0; + float blur = 0; + std::array<float, 2> dash_array = {{ 1, -1 }}; + std::string image; + + inline bool isVisible() const { + return opacity > 0 && color[3] > 0 && width > 0; + } +}; + +struct IconProperties { + inline IconProperties() {} + float opacity = 1.0f; + float rotate = 0.0f; + RotateAnchorType rotate_anchor = RotateAnchorType::Default; + + inline bool isVisible() const { + return opacity > 0; + } +}; + +struct TextProperties { + inline TextProperties() {} + float opacity = 1.0f; + float size = 12.0f; + Color color = {{ 0, 0, 0, 1 }}; + Color halo_color = {{ 1, 1, 1, 0.75 }}; + float halo_width = 0.25f; + float halo_blur = 1.0f; + + inline bool isVisible() const { + return opacity > 0 && (color[3] > 0 || halo_color[3] > 0) && size > 0; + } +}; + +struct CompositeProperties { + inline CompositeProperties() {} + float opacity = 1.0f; + + inline bool isVisible() const { + return opacity > 0; + } +}; + +struct RasterProperties { + inline RasterProperties() {} + float opacity = 1.0f; + float spin = 0.0f; + std::array<float, 2> brightness = {{ 0, 1 }}; + float saturation = 0.0f; + float contrast = 0.0f; + float fade = 0.0f; + + inline bool isVisible() const { + return opacity > 0; + } +}; + +struct BackgroundProperties { + inline BackgroundProperties() {} + Color color = {{ 1, 1, 1, 1 }}; +}; + +typedef util::variant< + FillProperties, + LineProperties, + IconProperties, + TextProperties, + CompositeProperties, + RasterProperties, + BackgroundProperties, + std::false_type +> StyleProperties; + +template <typename T> +const T &defaultStyleProperties(); + +} + +#endif diff --git a/include/mbgl/style/style_source.hpp b/include/mbgl/style/style_source.hpp new file mode 100644 index 0000000000..6b86c30907 --- /dev/null +++ b/include/mbgl/style/style_source.hpp @@ -0,0 +1,29 @@ +#ifndef MBGL_STYLE_STYLE_SOURCE +#define MBGL_STYLE_STYLE_SOURCE + +#include <mbgl/style/types.hpp> + +#include <memory> + +namespace mbgl { + +class Source; + +class StyleSource { +public: + const SourceType type; + const std::string url; + const uint32_t tile_size; + const int32_t min_zoom; + const int32_t max_zoom; + + bool enabled = false; + std::shared_ptr<Source> source; + + StyleSource(SourceType type = SourceType::Vector, const std::string &url = "", + uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22) + : type(type), url(url), tile_size(tile_size), min_zoom(min_zoom), max_zoom(max_zoom) {} +}; +}; + +#endif diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp new file mode 100644 index 0000000000..ca2061fa91 --- /dev/null +++ b/include/mbgl/style/types.hpp @@ -0,0 +1,160 @@ +#ifndef MBGL_STYLE_TYPES +#define MBGL_STYLE_TYPES + +#include <mbgl/util/enum.hpp> + +#include <string> +#include <array> + +namespace mbgl { + +// Stores a premultiplied color, with all four channels ranging from 0..1 +typedef std::array<float, 4> Color; + +enum class StyleLayerType : uint8_t { + Unknown, + Fill, + Line, + Icon, + Text, + Raster, + Composite, + Background +}; + +MBGL_DEFINE_ENUM_CLASS(StyleLayerTypeClass, StyleLayerType, { + { StyleLayerType::Unknown, "unknown" }, + { StyleLayerType::Fill, "fill" }, + { StyleLayerType::Line, "line" }, + { StyleLayerType::Icon, "icon" }, + { StyleLayerType::Text, "text" }, + { StyleLayerType::Raster, "raster" }, + { StyleLayerType::Composite, "composite" }, + { StyleLayerType::Background, "background" }, + { StyleLayerType(-1), "unknown" }, +}); + + +enum class WindingType : uint8_t { + EvenOdd, + NonZero, + Default = NonZero +}; + +enum class CapType : uint8_t { + None, + Round, + Butt, + Square, + Default = None +}; + +enum class JoinType : uint8_t { + None, + Miter, + Bevel, + Round, + Default = None +}; + +enum class TextPathType : uint8_t { + Horizontal, + Curve, + Default = Horizontal +}; + +enum class TextTransformType : uint8_t { + None, + Uppercase, + Lowercase, + Default = None +}; + +enum class TranslateAnchorType : uint8_t { + Map, + Viewport, + Default = Map +}; + +enum class RotateAnchorType : uint8_t { + Map, + Viewport, + Default = Viewport +}; + +enum class SourceType : uint8_t { + Vector, + Raster, + GeoJSON, + Video, + Default = Vector +}; + +inline WindingType parseWindingType(const std::string &type) { + if (type == "even-odd") return WindingType::EvenOdd; + if (type == "non-zero") return WindingType::NonZero; + return WindingType::Default; +} + +inline CapType parseCapType(const std::string &cap) { + if (cap == "round") return CapType::Round; + if (cap == "butt") return CapType::Butt; + if (cap == "square") return CapType::Square; + return CapType::None; +} + +inline JoinType parseJoinType(const std::string &join) { + if (join == "miter") return JoinType::Miter; + if (join == "bevel") return JoinType::Bevel; + if (join == "round") return JoinType::Round; + return JoinType::None; +} + +inline TextPathType parseTextPathType(const std::string &path) { + if (path == "horizontal") return TextPathType::Horizontal; + if (path == "curve") return TextPathType::Curve; + return TextPathType::Default; +} + +inline TextTransformType parseTextTransformType(const std::string& transform) { + if (transform == "uppercase") return TextTransformType::Uppercase; + if (transform == "lowercase") return TextTransformType::Lowercase; + return TextTransformType::Default; +}; + +inline TranslateAnchorType parseTranslateAnchorType(const std::string &anchor) { + if (anchor == "map") return TranslateAnchorType::Map; + if (anchor == "viewport") return TranslateAnchorType::Viewport; + return TranslateAnchorType::Default; +} + +inline RotateAnchorType parseRotateAnchorType(const std::string &anchor) { + if (anchor == "map") return RotateAnchorType::Map; + if (anchor == "viewport") return RotateAnchorType::Viewport; + return RotateAnchorType::Default; +} + +inline float parseAlignmentType(const std::string &alignment) { + if (alignment == "right") return 1.0f; + if (alignment == "left") return 0.0f; + return 0.5f; +} + +inline float parseVerticalAlignmentType(const std::string &alignment) { + if (alignment == "bottom") return 1.0f; + if (alignment == "top") return 0.0f; + return 0.5f; +} + +inline SourceType parseSourceType(const std::string &source) { + if (source == "vector") return SourceType::Vector; + if (source == "raster") return SourceType::Raster; + if (source == "geojson") return SourceType::GeoJSON; + if (source == "video") return SourceType::Video; + return SourceType::Default; +} + +} + +#endif + diff --git a/include/mbgl/style/value.hpp b/include/mbgl/style/value.hpp new file mode 100644 index 0000000000..5e6260e5a6 --- /dev/null +++ b/include/mbgl/style/value.hpp @@ -0,0 +1,43 @@ +#ifndef MBGL_STYLE_VALUE +#define MBGL_STYLE_VALUE + +#include <mbgl/util/variant.hpp> +#include <mbgl/util/pbf.hpp> + +#include <cstdlib> +#include <cerrno> + +namespace mbgl { + +typedef util::variant<bool, int64_t, uint64_t, double, std::string> Value; + +std::string toString(const Value &value); + +Value parseValue(pbf data); + +namespace util { +inline bool parseNumericString(const std::string &str, double &result) { + char *end = nullptr; + const char *begin = str.c_str(); + result = std::strtod(begin, &end); + while (*end != '\0' && isspace(*end)) end++; // eat whitespace after the end + return errno == 0 && end - begin == long(str.size()); +} +} + +template <typename T> +T toNumber(const Value &value) { + if (value.is<std::string>()) { + double val; + return util::parseNumericString(value.get<std::string>(), val) ? val : 0; + } + else if (value.is<bool>()) return value.get<bool>(); + else if (value.is<int64_t>()) return value.get<int64_t>(); + else if (value.is<uint64_t>()) return value.get<uint64_t>(); + else if (value.is<double>()) return value.get<double>(); + else return 0; +} + +} + +#endif diff --git a/include/mbgl/style/value_comparison.hpp b/include/mbgl/style/value_comparison.hpp new file mode 100644 index 0000000000..41c1d44123 --- /dev/null +++ b/include/mbgl/style/value_comparison.hpp @@ -0,0 +1,109 @@ +#ifndef MBGL_STYLE_VALUE_COMPARISON +#define MBGL_STYLE_VALUE_COMPARISON + +#include "value.hpp" +#include <cstdlib> +#include <cerrno> + +namespace mbgl { + +namespace util { + +namespace detail { + +template <typename Operator> +struct relaxed_operator_visitor { + typedef bool result_type; + + inline bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); } + + template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> + inline bool operator()(bool lhs, T rhs) const { return Operator()(T(lhs), rhs); } + + template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> + inline bool operator()(T lhs, bool rhs) const { return Operator()(lhs, T(rhs)); } + + inline bool operator()(int64_t lhs, uint64_t rhs) const { + return lhs < 0 ? false : Operator()(uint64_t(lhs), rhs); + } + inline bool operator()(uint64_t lhs, int64_t rhs) const { + return rhs < 0 ? false : Operator()(lhs, uint64_t(rhs)); + } + + template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> + inline bool operator()(const std::string &lhs, T rhs) const { + double value; + return parseNumericString(lhs, value) ? Operator()(value, double(rhs)) : false; + } + + template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type> + inline bool operator()(T lhs, const std::string &rhs) const { + double value; + return parseNumericString(rhs, value) ? Operator()(double(lhs), value) : false; + } + + template <typename T0, typename T1> + inline bool operator()(T0 lhs, T1 rhs) const { return Operator()(lhs, rhs); } +}; + +struct relaxed_equal_operator { + template <typename T0, typename T1> + inline bool operator()(T0 lhs, T1 rhs) const { return lhs == rhs; } +}; + +struct relaxed_not_equal_operator { + template <typename T0, typename T1> + inline bool operator()(T0 lhs, T1 rhs) const { return lhs != rhs; } +}; + +struct relaxed_greater_operator { + template <typename T0, typename T1> + inline bool operator()(T0 lhs, T1 rhs) const { return lhs > rhs; } +}; + +struct relaxed_greater_equal_operator { + template <typename T0, typename T1> + inline bool operator()(T0 lhs, T1 rhs) const { return lhs >= rhs; } +}; + +struct relaxed_less_operator { + template <typename T0, typename T1> + inline bool operator()(T0 lhs, T1 rhs) const { return lhs < rhs; } +}; + +struct relaxed_less_equal_operator { + template <typename T0, typename T1> + inline bool operator()(T0 lhs, T1 rhs) const { return lhs <= rhs; } +}; + +} // end namespace detail + +inline bool relaxed_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_equal_operator>(), lhs, rhs); +} + +inline bool relaxed_not_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_not_equal_operator>(), lhs, rhs); +} + +inline bool relaxed_greater(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_operator>(), lhs, rhs); +} + +inline bool relaxed_greater_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_equal_operator>(), lhs, rhs); +} + +inline bool relaxed_less(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_operator>(), lhs, rhs); +} + +inline bool relaxed_less_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_equal_operator>(), lhs, rhs); +} + +} + +} + +#endif |