From c4089b60bc630ee78c6755ebd7702943a30dd07d Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 25 Apr 2016 09:51:47 -0700 Subject: [PATCH] [core] Extract Function::evaluation to a separate class (#4811) This allows the Function> partial specialization to be eliminated, giving all property functions a consistent storage type. --- include/mbgl/style/types.hpp | 12 --- src/mbgl/layer/background_layer.hpp | 2 +- src/mbgl/layer/fill_layer.hpp | 2 +- src/mbgl/layer/line_layer.hpp | 4 +- src/mbgl/style/function.hpp | 27 ------- .../{function.cpp => function_evaluator.cpp} | 45 ++++++----- src/mbgl/style/function_evaluator.hpp | 38 +++++++++ src/mbgl/style/layout_property.hpp | 4 +- src/mbgl/style/paint_property.hpp | 9 ++- src/mbgl/style/property_parsing.cpp | 46 +---------- src/mbgl/util/interpolate.hpp | 1 + test/style/functions.cpp | 78 ++++++++++--------- 12 files changed, 121 insertions(+), 147 deletions(-) rename src/mbgl/style/{function.cpp => function_evaluator.cpp} (73%) create mode 100644 src/mbgl/style/function_evaluator.hpp diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index ca56d3999..939dbc3a6 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -21,18 +21,6 @@ struct FontStackHash { std::size_t operator()(const FontStack&) const; }; -template -struct Faded { - Faded() = default; - Faded(const T& v) : to(v) {} - - T from; - float fromScale = 0; - T to; - float toScale = 0; - float t = 0; -}; - // ------------------------------------------------------------------------------------------------- enum class SourceType : uint8_t { diff --git a/src/mbgl/layer/background_layer.hpp b/src/mbgl/layer/background_layer.hpp index 786dd0732..fb9f8b714 100644 --- a/src/mbgl/layer/background_layer.hpp +++ b/src/mbgl/layer/background_layer.hpp @@ -10,7 +10,7 @@ class BackgroundPaintProperties { public: PaintProperty backgroundOpacity { 1.0f }; PaintProperty backgroundColor { {{ 0, 0, 0, 1 }} }; - PaintProperty> backgroundPattern { "" }; + PaintProperty backgroundPattern { "" }; }; class BackgroundLayer : public StyleLayer { diff --git a/src/mbgl/layer/fill_layer.hpp b/src/mbgl/layer/fill_layer.hpp index 3a6f1fbf1..b0740a810 100644 --- a/src/mbgl/layer/fill_layer.hpp +++ b/src/mbgl/layer/fill_layer.hpp @@ -14,7 +14,7 @@ public: PaintProperty fillOutlineColor { {{ 0, 0, 0, -1 }} }; PaintProperty> fillTranslate { {{ 0, 0 }} }; PaintProperty fillTranslateAnchor { TranslateAnchorType::Map }; - PaintProperty> fillPattern { "" }; + PaintProperty fillPattern { "" }; }; class FillLayer : public StyleLayer { diff --git a/src/mbgl/layer/line_layer.hpp b/src/mbgl/layer/line_layer.hpp index 4000b9562..324573d6d 100644 --- a/src/mbgl/layer/line_layer.hpp +++ b/src/mbgl/layer/line_layer.hpp @@ -25,8 +25,8 @@ public: PaintProperty lineGapWidth { 0 }; PaintProperty lineBlur { 0 }; PaintProperty lineOffset { 0 }; - PaintProperty, Faded>> lineDasharray { {} }; - PaintProperty> linePattern { "" }; + PaintProperty, CrossFadedFunctionEvaluator> lineDasharray { {} }; + PaintProperty linePattern { "" }; }; class LineLayer : public StyleLayer { diff --git a/src/mbgl/style/function.hpp b/src/mbgl/style/function.hpp index f28d71eba..c5de6b5db 100644 --- a/src/mbgl/style/function.hpp +++ b/src/mbgl/style/function.hpp @@ -1,17 +1,11 @@ #ifndef MBGL_STYLE_FUNCTION #define MBGL_STYLE_FUNCTION -#include -#include -#include - #include #include namespace mbgl { -class StyleCalculationParameters; - template class Function { public: @@ -24,8 +18,6 @@ public: explicit Function(const Stops& stops_, float base_) : base(base_), stops(stops_) {} - T evaluate(const StyleCalculationParameters&) const; - float getBase() const { return base; } const std::vector>& getStops() const { return stops; } @@ -34,25 +26,6 @@ private: std::vector> stops; }; -// Partial specialization for cross-faded properties (*-pattern, line-dasharray). -template -class Function> { -public: - using Stop = std::pair; - using Stops = std::vector; - - explicit Function(const T& constant) - : stops({{ 0, constant }}) {} - - explicit Function(const Stops& stops_) - : stops(stops_) {} - - Faded evaluate(const StyleCalculationParameters&) const; - -private: - std::vector> stops; -}; - } // namespace mbgl #endif diff --git a/src/mbgl/style/function.cpp b/src/mbgl/style/function_evaluator.cpp similarity index 73% rename from src/mbgl/style/function.cpp rename to src/mbgl/style/function_evaluator.cpp index bc3e6074f..4c60207da 100644 --- a/src/mbgl/style/function.cpp +++ b/src/mbgl/style/function_evaluator.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -29,7 +29,9 @@ template <> inline TextTransformType defaultStopsValue() { return {}; }; template <> inline RotationAlignmentType defaultStopsValue() { return {}; }; template -T Function::evaluate(const StyleCalculationParameters& parameters) const { +T NormalFunctionEvaluator::operator()(const Function& fn, const StyleCalculationParameters& parameters) const { + float base = fn.getBase(); + const std::vector>& stops = fn.getStops(); float z = parameters.z; bool smaller = false; float smaller_z = 0.0f; @@ -76,23 +78,23 @@ T Function::evaluate(const StyleCalculationParameters& parameters) const { } } -template class Function; -template class Function; -template class Function; -template class Function>; -template class Function>; -template class Function>; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator>; +template class NormalFunctionEvaluator>; +template class NormalFunctionEvaluator>; -template class Function; -template class Function; -template class Function; -template class Function; -template class Function; -template class Function; -template class Function; -template class Function; -template class Function; -template class Function; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; +template class NormalFunctionEvaluator; template inline size_t getBiggestStopLessThan(const std::vector>& stops, float z) { @@ -105,9 +107,10 @@ inline size_t getBiggestStopLessThan(const std::vector>& sto } template -Faded Function>::evaluate(const StyleCalculationParameters& parameters) const { +Faded CrossFadedFunctionEvaluator::operator()(const Function& fn, const StyleCalculationParameters& parameters) const { Faded result; + const std::vector>& stops = fn.getStops(); float z = parameters.z; const float fraction = z - std::floor(z); std::chrono::duration d = parameters.defaultFadeDuration; @@ -136,7 +139,7 @@ Faded Function>::evaluate(const StyleCalculationParameters& paramete return result; } -template class Function>; -template class Function>>; +template class CrossFadedFunctionEvaluator; +template class CrossFadedFunctionEvaluator>; } // namespace mbgl diff --git a/src/mbgl/style/function_evaluator.hpp b/src/mbgl/style/function_evaluator.hpp new file mode 100644 index 000000000..3a73ec909 --- /dev/null +++ b/src/mbgl/style/function_evaluator.hpp @@ -0,0 +1,38 @@ +#ifndef MBGL_STYLE_FUNCTION_EVALUATOR +#define MBGL_STYLE_FUNCTION_EVALUATOR + +#include + +namespace mbgl { + +class StyleCalculationParameters; + +template +class NormalFunctionEvaluator { +public: + using ResultType = T; + T operator()(const Function&, const StyleCalculationParameters&) const; +}; + +template +struct Faded { + Faded() = default; + Faded(const T& v) : to(v) {} + + T from; + float fromScale = 0; + T to; + float toScale = 0; + float t = 0; +}; + +template +class CrossFadedFunctionEvaluator { +public: + using ResultType = Faded; + Faded operator()(const Function&, const StyleCalculationParameters&) const; +}; + +} // namespace mbgl + +#endif diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp index a35728d87..894fc4446 100644 --- a/src/mbgl/style/layout_property.hpp +++ b/src/mbgl/style/layout_property.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -22,7 +23,8 @@ public: void calculate(const StyleCalculationParameters& parameters) { if (parsedValue) { - value = (*parsedValue).evaluate(parameters); + NormalFunctionEvaluator evaluator; + value = evaluator(*parsedValue, parameters); } } diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp index e742b2c10..124b0a7c0 100644 --- a/src/mbgl/style/paint_property.hpp +++ b/src/mbgl/style/paint_property.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -16,10 +17,11 @@ namespace mbgl { -template +template class Evaluator = NormalFunctionEvaluator> class PaintProperty { public: - using Fn = Function; + using Fn = Function; + using Result = typename Evaluator::ResultType; explicit PaintProperty(T fallbackValue) : value(fallbackValue) { @@ -114,7 +116,8 @@ public: } Result calculate(const StyleCalculationParameters& parameters) { - Result final = value.evaluate(parameters); + Evaluator evaluator; + Result final = evaluator(value, parameters); if (!prior) { // No prior value. return final; diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp index 6f052222e..993245197 100644 --- a/src/mbgl/style/property_parsing.cpp +++ b/src/mbgl/style/property_parsing.cpp @@ -363,50 +363,12 @@ template<> optional> parseProperty(const char* name, const JSVal return parseFunction(name, value); } +template<> optional>> parseProperty(const char* name, const JSValue& value) { + return parseFunction>(name, value); +} + template<> optional>> parseProperty(const char* name, const JSValue& value) { return parseFunction>(name, value); } -template -optional>> parseFadedFunction(const JSValue& value) { - if (!value.HasMember("stops")) { - Log::Warning(Event::ParseStyle, "function must specify a function type"); - return {}; - } - - auto stops = parseStops("", value["stops"]); - - if (!stops) { - return {}; - } - - return Function>(*stops); -} - -template <> -optional>>> parseProperty(const char* name, const JSValue& value) { - if (value.IsObject()) { - return parseFadedFunction>(value); - } - - auto constant = parseProperty>(name, value); - if (!constant) { - return {}; - } - return Function>>(*constant); -} - -template <> -optional>> parseProperty(const char* name, const JSValue& value) { - if (value.IsObject()) { - return parseFadedFunction(value); - } - - auto constant = parseProperty(name, value); - if (!constant) { - return {}; - } - return Function>(*constant); -} - } // namespace mbgl diff --git a/src/mbgl/util/interpolate.hpp b/src/mbgl/util/interpolate.hpp index f456a0ecb..c2b7afcb8 100644 --- a/src/mbgl/util/interpolate.hpp +++ b/src/mbgl/util/interpolate.hpp @@ -5,6 +5,7 @@ #include #include +#include namespace mbgl { namespace util { diff --git a/test/style/functions.cpp b/test/style/functions.cpp index 26b952d7b..2389459db 100644 --- a/test/style/functions.cpp +++ b/test/style/functions.cpp @@ -2,58 +2,62 @@ #include #include +#include #include using namespace mbgl; TEST(Function, Constant) { - EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(StyleCalculationParameters(0))); - EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(StyleCalculationParameters(0))); - EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(StyleCalculationParameters(0))); - EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(StyleCalculationParameters(4))); - EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(StyleCalculationParameters(4))); - EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(StyleCalculationParameters(4))); - EXPECT_EQ(2.0f, mbgl::Function(2).evaluate(StyleCalculationParameters(22))); - EXPECT_EQ(3.8f, mbgl::Function(3.8).evaluate(StyleCalculationParameters(22))); - EXPECT_EQ(22.0f, mbgl::Function(22).evaluate(StyleCalculationParameters(22))); + NormalFunctionEvaluator evaluate; + EXPECT_EQ(2.0f, evaluate(Function(2), StyleCalculationParameters(0))); + EXPECT_EQ(3.8f, evaluate(Function(3.8), StyleCalculationParameters(0))); + EXPECT_EQ(22.0f, evaluate(Function(22), StyleCalculationParameters(0))); + EXPECT_EQ(2.0f, evaluate(Function(2), StyleCalculationParameters(4))); + EXPECT_EQ(3.8f, evaluate(Function(3.8), StyleCalculationParameters(4))); + EXPECT_EQ(22.0f, evaluate(Function(22), StyleCalculationParameters(4))); + EXPECT_EQ(2.0f, evaluate(Function(2), StyleCalculationParameters(22))); + EXPECT_EQ(3.8f, evaluate(Function(3.8), StyleCalculationParameters(22))); + EXPECT_EQ(22.0f, evaluate(Function(22), StyleCalculationParameters(22))); } TEST(Function, Stops) { + NormalFunctionEvaluator evaluate; + // Explicit constant slope in fringe regions. - mbgl::Function slope_1({ { 0, 1.5 }, { 6, 1.5 }, { 8, 3 }, { 22, 3 } }, 1.75); - EXPECT_EQ(1.5, slope_1.evaluate(StyleCalculationParameters(0))); - EXPECT_EQ(1.5, slope_1.evaluate(StyleCalculationParameters(4))); - EXPECT_EQ(1.5, slope_1.evaluate(StyleCalculationParameters(6))); - ASSERT_FLOAT_EQ(2.0454545454545454, slope_1.evaluate(StyleCalculationParameters(7))); - EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(8))); - EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(9))); - EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(15))); - EXPECT_EQ(3.0, slope_1.evaluate(StyleCalculationParameters(22))); + Function slope_1({ { 0, 1.5 }, { 6, 1.5 }, { 8, 3 }, { 22, 3 } }, 1.75); + EXPECT_EQ(1.5, evaluate(slope_1, StyleCalculationParameters(0))); + EXPECT_EQ(1.5, evaluate(slope_1, StyleCalculationParameters(4))); + EXPECT_EQ(1.5, evaluate(slope_1, StyleCalculationParameters(6))); + ASSERT_FLOAT_EQ(2.0454545454545454, evaluate(slope_1, StyleCalculationParameters(7))); + EXPECT_EQ(3.0, evaluate(slope_1, StyleCalculationParameters(8))); + EXPECT_EQ(3.0, evaluate(slope_1, StyleCalculationParameters(9))); + EXPECT_EQ(3.0, evaluate(slope_1, StyleCalculationParameters(15))); + EXPECT_EQ(3.0, evaluate(slope_1, StyleCalculationParameters(22))); // Test constant values in fringe regions. - mbgl::Function slope_2({ { 6, 1.5 }, { 8, 3 } }, 1.75); - EXPECT_EQ(1.5, slope_2.evaluate(StyleCalculationParameters(0))); - EXPECT_EQ(1.5, slope_2.evaluate(StyleCalculationParameters(4))); - EXPECT_EQ(1.5, slope_2.evaluate(StyleCalculationParameters(6))); - ASSERT_FLOAT_EQ(2.0454545454545454, slope_2.evaluate(StyleCalculationParameters(7))); - EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(8))); - EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(9))); - EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(15))); - EXPECT_EQ(3.0, slope_2.evaluate(StyleCalculationParameters(22))); + Function slope_2({ { 6, 1.5 }, { 8, 3 } }, 1.75); + EXPECT_EQ(1.5, evaluate(slope_2, StyleCalculationParameters(0))); + EXPECT_EQ(1.5, evaluate(slope_2, StyleCalculationParameters(4))); + EXPECT_EQ(1.5, evaluate(slope_2, StyleCalculationParameters(6))); + ASSERT_FLOAT_EQ(2.0454545454545454, evaluate(slope_2, StyleCalculationParameters(7))); + EXPECT_EQ(3.0, evaluate(slope_2, StyleCalculationParameters(8))); + EXPECT_EQ(3.0, evaluate(slope_2, StyleCalculationParameters(9))); + EXPECT_EQ(3.0, evaluate(slope_2, StyleCalculationParameters(15))); + EXPECT_EQ(3.0, evaluate(slope_2, StyleCalculationParameters(22))); // Test no values. - mbgl::Function slope_3({}, 1.75); - EXPECT_EQ(1, slope_3.evaluate(StyleCalculationParameters(2))); - EXPECT_EQ(1, slope_3.evaluate(StyleCalculationParameters(6))); - EXPECT_EQ(1, slope_3.evaluate(StyleCalculationParameters(12))); + Function slope_3({}, 1.75); + EXPECT_EQ(1, evaluate(slope_3, StyleCalculationParameters(2))); + EXPECT_EQ(1, evaluate(slope_3, StyleCalculationParameters(6))); + EXPECT_EQ(1, evaluate(slope_3, StyleCalculationParameters(12))); // Explicit constant slope in fringe regions. - mbgl::Function slope_4({ { 0, 2 }, { 8, 10 } }, 1); - EXPECT_EQ(2, slope_4.evaluate(StyleCalculationParameters(0))); - EXPECT_EQ(3, slope_4.evaluate(StyleCalculationParameters(1))); - EXPECT_EQ(4, slope_4.evaluate(StyleCalculationParameters(2))); - EXPECT_EQ(4.75, slope_4.evaluate(StyleCalculationParameters(2.75))); - EXPECT_EQ(10, slope_4.evaluate(StyleCalculationParameters(8))); + Function slope_4({ { 0, 2 }, { 8, 10 } }, 1); + EXPECT_EQ(2, evaluate(slope_4, StyleCalculationParameters(0))); + EXPECT_EQ(3, evaluate(slope_4, StyleCalculationParameters(1))); + EXPECT_EQ(4, evaluate(slope_4, StyleCalculationParameters(2))); + EXPECT_EQ(4.75, evaluate(slope_4, StyleCalculationParameters(2.75))); + EXPECT_EQ(10, evaluate(slope_4, StyleCalculationParameters(8))); }