#pragma once #include #include #include #include #include #include #include #include namespace mbgl { namespace style { template struct FormatSectionOverrides; template struct FormatSectionOverrides> { template static void setOverride(const T& overrides, U& overridable) { if (hasOverride(overrides.template get())) { auto override = std::make_unique>(Property::expressionType(), std::move(overridable.template get()), Property::name()); PropertyExpression expr(std::move(override)); overridable.template get() = PossiblyEvaluatedPropertyValue(std::move(expr)); } } template static void setOverrides(const T& overrides, U& overridable) { util::ignore({(setOverride(overrides, overridable), 0)...}); } template static void updateOverride(T& evaluated, U& updated) { auto property = evaluated.template get(); if (!property.isConstant()) { const bool hasFormatSectionOverride = property.match( [] (const style::PropertyExpression& e) { return e.getExpression().getKind() == expression::Kind::FormatSectionOverride; }, [] (const auto&) { return false; }); if (hasFormatSectionOverride) { updated.template get() = std::move(property); } } } template static void updateOverrides(T& evaluated, U& updated) { util::ignore({(updateOverride(evaluated, updated), 0)...}); } template static bool hasOverride(const FormattedProperty& formatted) { const auto checkLiteral = [] (const TextField::Type& literal) { for (const auto& section : literal.sections) { if (Property::hasOverride(section)) { return true; } } return false; }; return formatted.match( [&checkLiteral] (const TextField::Type& literal) { return checkLiteral(literal); }, [&checkLiteral] (const PropertyExpression& property) { bool expressionHasOverrides = false; const std::function checkExpression = [&](const expression::Expression& e) { if (expressionHasOverrides) { return; } if (e.getKind() == expression::Kind::Literal && e.getType() == expression::type::Formatted) { const auto* literalExpr = static_cast(&e); const auto formattedValue = expression::fromExpressionValue(literalExpr->getValue()); if (formattedValue && checkLiteral(*formattedValue)) { expressionHasOverrides = true; } return; } else if (e.getKind() == expression::Kind::FormatExpression) { const auto* formatExpr = static_cast(&e); for (const auto& section : formatExpr->getSections()) { if (Property::hasOverride(section)) { expressionHasOverrides = true; break; } } } else { e.eachChild(checkExpression); } }; checkExpression(property.getExpression()); return expressionHasOverrides; }, [] (const auto&) { return false; } ); } template static bool hasOverrides(const FormattedProperty& formatted) { bool result = false; util::ignore({ (result |= hasOverride(formatted))... }); return result; } template static bool hasPaintPropertyDifference(const PaintProperties& lhs, const PaintProperties& rhs) { bool result = false; util::ignore({ (result |= lhs.template get().value.isConstant() && rhs.template get().value.isConstant() && (lhs.template get().value.asConstant() != rhs.template get().value.asConstant()))... }); return result; } }; using SymbolLayerPaintPropertyOverrides = FormatSectionOverrides; class SymbolLayer::Impl : public Layer::Impl { public: using Layer::Impl::Impl; bool hasLayoutDifference(const Layer::Impl&) const override; void stringifyLayout(rapidjson::Writer&) const override; void populateFontStack(std::set& fontStack) const final; SymbolLayoutProperties::Unevaluated layout; SymbolPaintProperties::Transitionable paint; DECLARE_LAYER_TYPE_INFO; private: bool hasFormatSectionOverrides() const; mutable optional hasFormatSectionOverrides_; }; } // namespace style } // namespace mbgl