summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-11 10:39:12 +0200
committerAlexander Shalamov <alexander.shalamov@mapbox.com>2019-03-13 14:17:51 +0200
commit6545ca574c7087d2e753191262ba71baa7482bf8 (patch)
tree019529dd20a12fbd013fb119fb0d7cc18d4e0ce8
parent430e32d6c4f29340ead215c3c186b0629d3bcb04 (diff)
downloadqtlocation-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-xscripts/generate-style-code.js25
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.cpp29
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.hpp20
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp2
-rw-r--r--src/mbgl/style/layers/layer_properties.hpp.ejs5
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp15
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp98
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp5
-rw-r--r--src/mbgl/style/layout_property.hpp2
-rw-r--r--src/mbgl/style/light_impl.hpp1
-rw-r--r--src/mbgl/style/paint_property.hpp7
-rw-r--r--src/mbgl/style/properties.hpp4
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>;