#pragma once #include #include #include #include #include #include namespace mbgl { namespace style { class PropertyExpressionBase { public: explicit PropertyExpressionBase(std::unique_ptr); bool isZoomConstant() const noexcept; bool isFeatureConstant() const noexcept; bool canEvaluateWith(const expression::EvaluationContext&) const noexcept; float interpolationFactor(const Range&, const float) const noexcept; Range getCoveringStops(const float, const float) const noexcept; const expression::Expression& getExpression() const noexcept; bool useIntegerZoom = false; protected: std::shared_ptr expression; variant zoomCurve; bool isZoomConstant_; bool isFeatureConstant_; }; template class PropertyExpression final : public PropertyExpressionBase { public: // Second parameter to be used only for conversions from legacy functions. PropertyExpression(std::unique_ptr expression_, optional defaultValue_ = nullopt) : PropertyExpressionBase(std::move(expression_)), defaultValue(std::move(defaultValue_)) { } T evaluate(const expression::EvaluationContext& context, T finalDefaultValue = T()) const { assert(canEvaluateWith(context)); const expression::EvaluationResult result = expression->evaluate(context); if (result) { const optional typed = expression::fromExpressionValue(*result); return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue; } return defaultValue ? *defaultValue : finalDefaultValue; } T evaluate(float zoom) const { return evaluate(expression::EvaluationContext(zoom)); } T evaluate(optional accumulated, mapbox::feature::feature& f, T finalDefaultValue = T()) const { const expression::EvaluationResult result = expression->evaluate(accumulated, f); if (result) { const optional typed = expression::fromExpressionValue(*result); return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue; } return defaultValue ? *defaultValue : finalDefaultValue; } T evaluate(const GeometryTileFeature& feature, T finalDefaultValue) const { return evaluate(expression::EvaluationContext(&feature), finalDefaultValue); } T evaluate(float zoom, const GeometryTileFeature& feature, T finalDefaultValue) const { return evaluate(expression::EvaluationContext(zoom, &feature), finalDefaultValue); } std::vector> possibleOutputs() const { return expression::fromExpressionValues(expression->possibleOutputs()); } friend bool operator==(const PropertyExpression& lhs, const PropertyExpression& rhs) { return *lhs.expression == *rhs.expression; } private: optional defaultValue; }; } // namespace style } // namespace mbgl