diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-03-11 10:39:12 +0200 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-03-13 14:17:51 +0200 |
commit | 6545ca574c7087d2e753191262ba71baa7482bf8 (patch) | |
tree | 019529dd20a12fbd013fb119fb0d7cc18d4e0ce8 | |
parent | 430e32d6c4f29340ead215c3c186b0629d3bcb04 (diff) | |
download | qtlocation-mapboxgl-6545ca574c7087d2e753191262ba71baa7482bf8.tar.gz |
[core] Add FormatSectionOverrides and introduce overridable properties
This commit adds FormatSectionOverrides generic class that can be used to
manage overridable paint properties for particular property set.
-rwxr-xr-x | scripts/generate-style-code.js | 25 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.cpp | 29 | ||||
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.hpp | 20 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_symbol_layer.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/layers/layer_properties.hpp.ejs | 5 | ||||
-rw-r--r-- | src/mbgl/style/layers/symbol_layer_impl.cpp | 15 | ||||
-rw-r--r-- | src/mbgl/style/layers/symbol_layer_impl.hpp | 98 | ||||
-rw-r--r-- | src/mbgl/style/layers/symbol_layer_properties.hpp | 5 | ||||
-rw-r--r-- | src/mbgl/style/layout_property.hpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/light_impl.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/style/paint_property.hpp | 7 | ||||
-rw-r--r-- | src/mbgl/style/properties.hpp | 4 |
12 files changed, 190 insertions, 23 deletions
diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js index c002718038..ae25a856a8 100755 --- a/scripts/generate-style-code.js +++ b/scripts/generate-style-code.js @@ -19,6 +19,29 @@ global.isLightProperty = function (property) { return property['light-property'] === true; }; +global.isOverridable = function (property) { + return ['text-color'].includes(property.name); +}; + +global.expressionType = function (property) { + switch (property.type) { + case 'boolean': + return 'BooleanType'; + case 'number': + case 'enum': + return 'NumberType'; + case 'string': + return 'StringType'; + case 'color': + return `ColorType`; + case 'formatted': + return `FormattedType`; + case 'array': + return `Array<${expressionType({type: property.value})}>`; + default: throw new Error(`unknown type for ${property.name}`) + } +}; + global.evaluatedType = function (property) { if (/-translate-anchor$/.test(property.name)) { return 'TranslateAnchorType'; @@ -93,6 +116,8 @@ global.layoutPropertyType = function (property) { global.paintPropertyType = function (property, type) { switch (property['property-type']) { case 'data-driven': + if (isOverridable(property)) + return `DataDrivenPaintProperty<${evaluatedType(property)}, ${attributeUniformType(property, type)}, true>`; return `DataDrivenPaintProperty<${evaluatedType(property)}, ${attributeUniformType(property, type)}>`; case 'cross-faded-data-driven': return `CrossFadedDataDrivenPaintProperty<${evaluatedType(property)}, ${attributeUniformType(property, type)}>`; diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index 3a3688a60b..9220235f1d 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -28,13 +28,17 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layo iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())) { for (const auto& pair : paintProperties_) { + auto layerPaintProperties = pair.second; + if (hasFormatSectionOverrides()) { + setPaintPropertyOverrides(layerPaintProperties); + } paintProperties.emplace( std::piecewise_construct, std::forward_as_tuple(pair.first), std::forward_as_tuple(PaintProperties { - pair.second, - { RenderSymbolLayer::iconPaintProperties(pair.second), zoom }, - { RenderSymbolLayer::textPaintProperties(pair.second), zoom } + layerPaintProperties, + { RenderSymbolLayer::iconPaintProperties(layerPaintProperties), zoom }, + { RenderSymbolLayer::textPaintProperties(layerPaintProperties), zoom } })); } } @@ -226,4 +230,23 @@ void SymbolBucket::sortFeatures(const float angle) { } } +void SymbolBucket::updatePaintProperties(const std::string& layerID, + style::SymbolPaintProperties::PossiblyEvaluated updated) { + if (hasFormatSectionOverrides()) { + SymbolLayerPaintPropertyOverrides::updateOverrides(paintProperties.at(layerID).evaluated, updated); + } + paintProperties.at(layerID).evaluated = updated; +} + +void SymbolBucket::setPaintPropertyOverrides(style::SymbolPaintProperties::PossiblyEvaluated& paint) { + SymbolLayerPaintPropertyOverrides::setOverrides(layout, paint); +} + +bool SymbolBucket::hasFormatSectionOverrides() { + if (!hasFormatSectionOverrides_) { + hasFormatSectionOverrides_= SymbolLayerPaintPropertyOverrides::hasOverrides(layout.get<TextField>()); + } + return *hasFormatSectionOverrides_; +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index 709e48dd2e..9764d870da 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -58,6 +58,10 @@ public: bool hasIconData() const; bool hasCollisionBoxData() const; bool hasCollisionCircleData() const; + bool hasFormatSectionOverrides(); + void updatePaintProperties(const std::string& layerID, + style::SymbolPaintProperties::PossiblyEvaluated); + void setPaintPropertyOverrides(style::SymbolPaintProperties::PossiblyEvaluated&); void updateOpacity(); void sortFeatures(const float angle); @@ -87,7 +91,7 @@ public: std::unique_ptr<SymbolSizeBinder> textSizeBinder; - struct TextBuffer { + struct Buffer { gfx::VertexVector<SymbolLayoutVertex> vertices; gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>> dynamicVertices; gfx::VertexVector<gfx::Vertex<SymbolOpacityAttributes>> opacityVertices; @@ -103,19 +107,8 @@ public: std::unique_ptr<SymbolSizeBinder> iconSizeBinder; - struct IconBuffer { - gfx::VertexVector<SymbolLayoutVertex> vertices; - gfx::VertexVector<gfx::Vertex<SymbolDynamicLayoutAttributes>> dynamicVertices; - gfx::VertexVector<gfx::Vertex<SymbolOpacityAttributes>> opacityVertices; - gfx::IndexVector<gfx::Triangles> triangles; - SegmentVector<SymbolIconAttributes> segments; - std::vector<PlacedSymbol> placedSymbols; + struct IconBuffer : public Buffer { PremultipliedImage atlasImage; - - optional<gfx::VertexBuffer<SymbolLayoutVertex>> vertexBuffer; - optional<gfx::VertexBuffer<gfx::Vertex<SymbolDynamicLayoutAttributes>>> dynamicVertexBuffer; - optional<gfx::VertexBuffer<gfx::Vertex<SymbolOpacityAttributes>>> opacityVertexBuffer; - optional<gfx::IndexBuffer> indexBuffer; } icon; struct CollisionBuffer { @@ -139,6 +132,7 @@ public: uint32_t bucketInstanceId = 0; bool justReloaded = false; + optional<bool> hasFormatSectionOverrides_; std::shared_ptr<std::vector<size_t>> featureSortOrder; }; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index e523a869b2..43e3068ff0 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -411,7 +411,7 @@ void RenderSymbolLayer::sortRenderTiles(const TransformState& state) { void RenderSymbolLayer::updateBucketPaintProperties(Bucket* bucket) const { assert(bucket->supportsLayer(*baseImpl)); - static_cast<SymbolBucket*>(bucket)->paintProperties.at(getID()).evaluated = evaluated; + static_cast<SymbolBucket*>(bucket)->updatePaintProperties(getID(), evaluated); } } // namespace mbgl diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs index 792f858862..89dffdcd42 100644 --- a/src/mbgl/style/layers/layer_properties.hpp.ejs +++ b/src/mbgl/style/layers/layer_properties.hpp.ejs @@ -31,6 +31,11 @@ struct <%- camelize(property.name) %> : ColorRampProperty { <% } else { -%> struct <%- camelize(property.name) %> : <%- paintPropertyType(property, type) %> { static <%- evaluatedType(property) %> defaultValue() { return <%- defaultValue(property) %>; } +<% if (isOverridable(property)) { -%> + static constexpr const char *name() { return "<%- property.name %>"; } + static constexpr auto expressionType() { return expression::type::<%- expressionType(property) %>{}; }; + template<typename T> static bool hasOverride(const T& t) { return !!t.<%- camelizeWithLeadingLowercase(property.name) %>; }; +<% } -%> }; <% } -%> diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp index 3dd1da1136..e35e7b0b9f 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.cpp +++ b/src/mbgl/style/layers/symbol_layer_impl.cpp @@ -1,17 +1,24 @@ #include <mbgl/style/layers/symbol_layer_impl.hpp> - #include <mbgl/util/logging.hpp> namespace mbgl { namespace style { +bool SymbolLayer::Impl::hasFormatSectionOverrides() const { + if (!hasFormatSectionOverrides_) { + hasFormatSectionOverrides_ = SymbolLayerPaintPropertyOverrides::hasOverrides(layout.get<TextField>()); + } + return *hasFormatSectionOverrides_; +} + bool SymbolLayer::Impl::hasLayoutDifference(const Layer::Impl& other) const { assert(other.getTypeInfo() == getTypeInfo()); const auto& impl = static_cast<const style::SymbolLayer::Impl&>(other); return filter != impl.filter || visibility != impl.visibility || layout != impl.layout || - paint.hasDataDrivenPropertyDifference(impl.paint); + paint.hasDataDrivenPropertyDifference(impl.paint) || + (hasFormatSectionOverrides() && SymbolLayerPaintPropertyOverrides::hasPaintPropertyDifference(paint, impl.paint)); } void SymbolLayer::Impl::populateFontStack(std::set<FontStack>& fontStack) const { @@ -20,10 +27,10 @@ void SymbolLayer::Impl::populateFontStack(std::set<FontStack>& fontStack) const } layout.get<TextFont>().match( - [&] (Undefined) { + [&fontStack] (Undefined) { fontStack.insert({"Open Sans Regular", "Arial Unicode MS Regular"}); }, - [&] (const FontStack& constant) { + [&fontStack] (const FontStack& constant) { fontStack.insert(constant); }, [&] (const auto& function) { diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp index a5b0332f6c..f937fccaa8 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.hpp +++ b/src/mbgl/style/layers/symbol_layer_impl.hpp @@ -3,10 +3,104 @@ #include <mbgl/style/layer_impl.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_properties.hpp> +#include <mbgl/style/expression/format_expression.hpp> +#include <mbgl/style/expression/formatted.hpp> +#include <mbgl/style/expression/format_section_override.hpp> namespace mbgl { namespace style { +template<typename PaintProperty> +struct FormatSectionOverrides; + +template<typename... PaintProperty> +struct FormatSectionOverrides<TypeList<PaintProperty...>> { + template<typename Property, typename T, typename U> + static void setOverride(const T& overrides, U& overridable) { + if (hasOverride<Property>(overrides.template get<TextField>())) { + auto override = + std::make_unique<expression::FormatSectionOverride<typename Property::Type>>(Property::expressionType(), + std::move(overridable.template get<Property>()), + Property::name()); + PropertyExpression<typename Property::Type> expr(std::move(override)); + overridable.template get<Property>() = PossiblyEvaluatedPropertyValue<typename Property::Type>(std::move(expr)); + } + } + + template<typename T, typename U> + static void setOverrides(const T& overrides, U& overridable) { + util::ignore({(setOverride<PaintProperty>(overrides, overridable), 0)...}); + } + + template<typename Property, typename T, typename U> + static void updateOverride(T& evaluated, U& updated) { + auto property = evaluated.template get<Property>(); + if (!property.isConstant()) { + const bool hasFormatSectionOverride = property.match( + [] (const style::PropertyExpression<typename Property::Type>& e) { + return e.getExpression().getKind() == expression::Kind::FormatSectionOverride; + }, + [] (const auto&) { + return false; + }); + if (hasFormatSectionOverride) { + updated.template get<Property>() = std::move(property); + } + } + } + + template<typename T, typename U> + static void updateOverrides(T& evaluated, U& updated) { + util::ignore({(updateOverride<PaintProperty>(evaluated, updated), 0)...}); + } + + template<typename Property, typename FormattedProperty> + static bool hasOverride(const FormattedProperty& formatted) { + return formatted.match( + [] (const TextField::Type& t) { + for (const auto& section : t.sections) { + if (Property::hasOverride(section)) { + return true; + } + } + return false; + }, + [] (const PropertyExpression<TextField::Type>& t) { + if (t.getExpression().getKind() == expression::Kind::FormatExpression) { + const auto* e = static_cast<const expression::FormatExpression*>(&t.getExpression()); + for (const auto& section : e->getSections()) { + if (Property::hasOverride(section)) { + return true; + } + } + } + return false; + }, + [] (const auto&) { + return false; + } + ); + } + + template <typename FormattedProperty> + static bool hasOverrides(const FormattedProperty& formatted) { + bool result = false; + util::ignore({ (result |= hasOverride<PaintProperty>(formatted))... }); + return result; + } + + template <typename PaintProperties> + static bool hasPaintPropertyDifference(const PaintProperties& lhs, const PaintProperties& rhs) { + bool result = false; + util::ignore({ (result |= lhs.template get<PaintProperty>().value.isConstant() && + rhs.template get<PaintProperty>().value.isConstant() && + (lhs.template get<PaintProperty>().value.asConstant() != rhs.template get<PaintProperty>().value.asConstant()))... }); + return result; + } +}; + +using SymbolLayerPaintPropertyOverrides = FormatSectionOverrides<SymbolPaintProperties::OverridableProperties>; + class SymbolLayer::Impl : public Layer::Impl { public: using Layer::Impl::Impl; @@ -19,6 +113,10 @@ public: SymbolPaintProperties::Transitionable paint; DECLARE_LAYER_TYPE_INFO; + +private: + bool hasFormatSectionOverrides() const; + mutable optional<bool> hasFormatSectionOverrides_; }; } // namespace style diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp index d5bdce1f5d..c352ab8e77 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.hpp +++ b/src/mbgl/style/layers/symbol_layer_properties.hpp @@ -229,8 +229,11 @@ struct TextOpacity : DataDrivenPaintProperty<float, attributes::a_opacity, unifo static float defaultValue() { return 1; } }; -struct TextColor : DataDrivenPaintProperty<Color, attributes::a_fill_color, uniforms::u_fill_color> { +struct TextColor : DataDrivenPaintProperty<Color, attributes::a_fill_color, uniforms::u_fill_color, true> { static Color defaultValue() { return Color::black(); } + static constexpr const char *name() { return "text-color"; } + static constexpr auto expressionType() { return expression::type::ColorType{}; }; + template<typename T> static bool hasOverride(const T& t) { return !!t.textColor; }; }; struct TextHaloColor : DataDrivenPaintProperty<Color, attributes::a_halo_color, uniforms::u_halo_color> { diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp index 0fcad30cc4..d98a1cbf31 100644 --- a/src/mbgl/style/layout_property.hpp +++ b/src/mbgl/style/layout_property.hpp @@ -16,6 +16,7 @@ public: using PossiblyEvaluatedType = T; using Type = T; static constexpr bool IsDataDriven = false; + static constexpr bool IsOverridable = false; }; template <class T> @@ -27,6 +28,7 @@ public: using PossiblyEvaluatedType = PossiblyEvaluatedPropertyValue<T>; using Type = T; static constexpr bool IsDataDriven = true; + static constexpr bool IsOverridable = false; }; } // namespace style diff --git a/src/mbgl/style/light_impl.hpp b/src/mbgl/style/light_impl.hpp index f094c9d462..33db64ae3f 100644 --- a/src/mbgl/style/light_impl.hpp +++ b/src/mbgl/style/light_impl.hpp @@ -21,6 +21,7 @@ public: using PossiblyEvaluatedType = T; using Type = T; static constexpr bool IsDataDriven = false; + static constexpr bool IsOverridable = false; }; struct LightAnchor : LightProperty<LightAnchorType> { diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp index 343e689a32..7d398748f2 100644 --- a/src/mbgl/style/paint_property.hpp +++ b/src/mbgl/style/paint_property.hpp @@ -21,9 +21,10 @@ public: using PossiblyEvaluatedType = T; using Type = T; static constexpr bool IsDataDriven = false; + static constexpr bool IsOverridable = false; }; -template <class T, class A, class U> +template <class T, class A, class U, bool isOverridable = false> class DataDrivenPaintProperty { public: using TransitionableType = Transitionable<PropertyValue<T>>; @@ -32,6 +33,7 @@ public: using PossiblyEvaluatedType = PossiblyEvaluatedPropertyValue<T>; using Type = T; static constexpr bool IsDataDriven = true; + static constexpr bool IsOverridable = isOverridable; using Attribute = A; using AttributeList = TypeList<A>; @@ -48,6 +50,7 @@ public: using PossiblyEvaluatedType = PossiblyEvaluatedPropertyValue<Faded<T>>; using Type = T; static constexpr bool IsDataDriven = true; + static constexpr bool IsOverridable = false; using Attribute = A1; using AttributeList = TypeList<A1, A2>; @@ -64,6 +67,7 @@ public: using PossiblyEvaluatedType = Faded<T>; using Type = T; static constexpr bool IsDataDriven = false; + static constexpr bool IsOverridable = false; }; /* @@ -84,6 +88,7 @@ public: using PossiblyEvaluatedType = Color; using Type = Color; static constexpr bool IsDataDriven = false; + static constexpr bool IsOverridable = false; static Color defaultValue() { return {}; } }; diff --git a/src/mbgl/style/properties.hpp b/src/mbgl/style/properties.hpp index d836735c65..7f58ff223d 100644 --- a/src/mbgl/style/properties.hpp +++ b/src/mbgl/style/properties.hpp @@ -99,6 +99,9 @@ public: template <class P> struct IsDataDriven : std::integral_constant<bool, P::IsDataDriven> {}; +template <class P> +struct IsOverridable : std::integral_constant<bool, P::IsOverridable> {}; + template <class... Ps> class Properties { public: @@ -122,6 +125,7 @@ public: using EvaluatedTypes = TypeList<typename Ps::Type...>; using DataDrivenProperties = FilteredTypeList<PropertyTypes, IsDataDriven>; + using OverridableProperties = FilteredTypeList<PropertyTypes, IsOverridable>; template <class TypeList> using Tuple = IndexedTuple<PropertyTypes, TypeList>; |