[core] Implement image expression (#15877)

* [core] Bump gl-js version
* [core] Implement image expression
* [core] Use new image expression
* [core] Coerce image expression to / from string
* [core] Serialize evaluated image
* [core] Pass available images to layout
* [core] Pass images to evaluation context
* [core] Set available flag value based on image availability
* [core] Allow image coercion to boolean to indicate image availability
* [core] Coalesce image expression
* [core] Add image expression to next build system
* [core] Align serialization format and evaluated type with gl-js
* [core] Add images to expression evaluation method
* [core] Add support for Image expression to expression test runner
* [core] Unskip image expression tests
* [core] Update unit tests
* [core] Use image expression in annotation manager
* [core] Add string to ImageExpression conversion
* [core] Add image expression to expression dsl
* [core] Convert tokens for implicitly created Image literal
* [core] Fix clang format
* [core] Split generated style code lines that are over 120 characters
* [core] Add unit test for image expression equality
* [core] Add image property expression evaluation unit test
* [core] Unskip image expression render test
* [core] Skip 'in' expression tests
* [core] Ignore fill-pattern/update-feature-state render test
* [core] Rename Image::serialize to Image::toValue
This commit is contained in:
Alexander Shalamov
2019-10-30 10:21:17 +02:00
parent e1556fc539
commit c6f3cc8b60
86 changed files with 1056 additions and 531 deletions

View File

@@ -104,8 +104,7 @@ optional<Value> toValue(const JSValue& jsvalue) {
style::expression::type::Type stringToType(const std::string& type) {
using namespace style::expression;
if (type == "string"s || type == "number-format"s ||
type == "image"s) { // TODO: replace once we implement image expressions
if (type == "string"s || type == "number-format"s) {
return type::String;
} else if (type == "number"s) {
return type::Number;
@@ -119,6 +118,8 @@ style::expression::type::Type stringToType(const std::string& type) {
return type::Value;
} else if (type == "formatted"s) {
return type::Formatted;
} else if (type == "resolvedImage"s) {
return type::Image;
}
// Should not reach.
@@ -253,6 +254,16 @@ bool parseInputs(const JSValue& inputsValue, TestData& data) {
heatmapDensity = evaluationContext["heatmapDensity"].GetDouble();
}
// Parse availableImages
std::set<std::string> availableImages;
if (evaluationContext.HasMember("availableImages")) {
assert(evaluationContext["availableImages"].IsArray());
for (const auto& image : evaluationContext["availableImages"].GetArray()) {
assert(image.IsString());
availableImages.emplace(toString(image));
}
}
// Parse feature properties
Feature feature(mapbox::geometry::point<double>(0.0, 0.0));
const auto& featureObject = input[1].GetObject();
@@ -271,7 +282,8 @@ bool parseInputs(const JSValue& inputsValue, TestData& data) {
feature.id = mapbox::geojson::convert<mapbox::feature::identifier>(featureObject["id"]);
}
data.inputs.emplace_back(std::move(zoom), std::move(heatmapDensity), std::move(feature));
data.inputs.emplace_back(
std::move(zoom), std::move(heatmapDensity), std::move(availableImages), std::move(feature));
}
return true;
}

View File

@@ -7,18 +7,24 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <vector>
#include <set>
#include <string>
#include <vector>
using namespace mbgl;
struct Input {
Input(optional<float> zoom_, optional<double> heatmapDensity_, Feature feature_)
Input(optional<float> zoom_,
optional<double> heatmapDensity_,
std::set<std::string> availableImages_,
Feature feature_)
: zoom(std::move(zoom_)),
heatmapDensity(std::move(heatmapDensity_)),
availableImages(std::move(availableImages_)),
feature(std::move(feature_)) {}
optional<float> zoom;
optional<double> heatmapDensity;
std::set<std::string> availableImages;
Feature feature;
};

View File

@@ -104,7 +104,8 @@ TestRunOutput runExpressionTest(TestData& data, const std::string& rootPath, con
std::vector<Value> outputs;
if (!data.inputs.empty()) {
for (const auto& input : data.inputs) {
auto evaluationResult = expression->evaluate(input.zoom, input.feature, input.heatmapDensity);
auto evaluationResult =
expression->evaluate(input.zoom, input.feature, input.heatmapDensity, input.availableImages);
if (!evaluationResult) {
std::unordered_map<std::string, Value> error{{"error", Value{evaluationResult.error().message}}};
outputs.emplace_back(Value{std::move(error)});

View File

@@ -12,6 +12,7 @@ namespace conversion {
bool hasTokens(const std::string&);
std::unique_ptr<expression::Expression> convertTokenStringToFormatExpression(const std::string&);
std::unique_ptr<expression::Expression> convertTokenStringToImageExpression(const std::string&);
std::unique_ptr<expression::Expression> convertTokenStringToExpression(const std::string&);
optional<std::unique_ptr<expression::Expression>> convertFunctionToExpression(expression::type::Type, const Convertible&, Error&, bool convertTokens);

View File

@@ -39,6 +39,12 @@ struct Converter<PropertyValue<T>> {
? PropertyValue<T>(PropertyExpression<T>(convertTokenStringToFormatExpression(firstUnformattedSection)))
: PropertyValue<T>(t);
}
PropertyValue<T> maybeConvertTokens(const expression::Image& image) const {
return hasTokens(image.id())
? PropertyValue<T>(PropertyExpression<T>(convertTokenStringToImageExpression(image.id())))
: PropertyValue<T>(image);
}
};
} // namespace conversion

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/color_ramp_property_value.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/style/property_value.hpp>
#include <mbgl/style/transition_options.hpp>

View File

@@ -49,6 +49,7 @@ std::unique_ptr<Expression> toString(std::unique_ptr<Expression>,
std::unique_ptr<Expression> def = nullptr);
std::unique_ptr<Expression> toFormatted(std::unique_ptr<Expression>,
std::unique_ptr<Expression> def = nullptr);
std::unique_ptr<Expression> toImage(std::unique_ptr<Expression>, std::unique_ptr<Expression> def = nullptr);
std::unique_ptr<Expression> get(const char* value);
std::unique_ptr<Expression> get(std::unique_ptr<Expression>);
@@ -89,6 +90,9 @@ std::unique_ptr<Expression> concat(std::vector<std::unique_ptr<Expression>> inpu
std::unique_ptr<Expression> format(const char* value);
std::unique_ptr<Expression> format(std::unique_ptr<Expression>);
std::unique_ptr<Expression> image(const char* value);
std::unique_ptr<Expression> image(std::unique_ptr<Expression>);
} // namespace dsl
} // namespace expression
} // namespace style

View File

@@ -28,9 +28,7 @@ public:
EvaluationContext() = default;
explicit EvaluationContext(float zoom_) : zoom(zoom_) {}
explicit EvaluationContext(GeometryTileFeature const * feature_) : feature(feature_) {}
EvaluationContext(float zoom_, GeometryTileFeature const * feature_) :
zoom(zoom_), feature(feature_)
{}
EvaluationContext(float zoom_, GeometryTileFeature const* feature_) : zoom(zoom_), feature(feature_) {}
EvaluationContext(optional<mbgl::Value> accumulated_, GeometryTileFeature const * feature_) :
accumulated(std::move(accumulated_)), feature(feature_)
{}
@@ -50,6 +48,11 @@ public:
return *this;
};
EvaluationContext& withAvailableImages(const std::set<std::string>* availableImages_) noexcept {
availableImages = availableImages_;
return *this;
};
optional<float> zoom;
optional<mbgl::Value> accumulated;
GeometryTileFeature const * feature = nullptr;
@@ -57,6 +60,7 @@ public:
// Contains formatted section object, std::unordered_map<std::string, Value>.
const Value* formattedSection = nullptr;
const FeatureState* featureState = nullptr;
const std::set<std::string>* availableImages = nullptr;
};
template <typename T>
@@ -155,7 +159,8 @@ enum class Kind : int32_t {
Comparison,
FormatExpression,
FormatSectionOverride,
NumberFormat
NumberFormat,
ImageExpression
};
class Expression {
@@ -172,9 +177,14 @@ public:
Kind getKind() const { return kind; };
type::Type getType() const { return type; };
EvaluationResult evaluate(optional<float> zoom, const Feature& feature, optional<double> colorRampParameter) const;
EvaluationResult evaluate(optional<float> zoom,
const Feature& feature,
optional<double> colorRampParameter,
const std::set<std::string>& availableImages) const;
EvaluationResult evaluate(optional<mbgl::Value> accumulated, const Feature& feature) const;
/**
* Statically analyze the expression, attempting to enumerate possible outputs. Returns
* an array of values plus the sentinel null optional value, used to indicate that the

View File

@@ -36,7 +36,7 @@ struct FormattedSection {
class Formatted {
public:
Formatted() = default;
Formatted(const char* plainU8String) {
sections.emplace_back(std::string(plainU8String), nullopt, nullopt, nullopt);
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/optional.hpp>
#include <string>
#include <vector>
namespace mbgl {
namespace style {
namespace expression {
class Image {
public:
Image() = default;
Image(const char* imageID);
Image(std::string imageID);
explicit Image(std::string imageID, bool available);
bool operator==(const Image&) const;
mbgl::Value toValue() const;
const std::string& id() const;
bool isAvailable() const;
bool empty() const;
private:
std::string imageID;
bool available;
};
} // namespace expression
namespace conversion {
template <>
struct Converter<expression::Image> {
public:
optional<expression::Image> operator()(const Convertible& value, Error& error) const;
};
template <>
struct ValueFactory<expression::Image> {
static Value make(const expression::Image& image) { return image.toValue(); }
};
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -0,0 +1,33 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
namespace mbgl {
namespace style {
namespace expression {
class ParsingContext;
class ImageExpression final : public Expression {
public:
explicit ImageExpression(std::unique_ptr<Expression> imageID);
EvaluationResult evaluate(const EvaluationContext&) const override;
static ParseResult parse(const mbgl::style::conversion::Convertible&, ParsingContext&);
void eachChild(const std::function<void(const Expression&)>&) const override;
bool operator==(const Expression& e) const override;
std::vector<optional<Value>> possibleOutputs() const override { return {nullopt}; }
mbgl::Value serialize() const override;
std::string getOperator() const override { return "image"; }
private:
std::shared_ptr<Expression> imageID;
};
} // namespace expression
} // namespace style
} // namespace mbgl

View File

@@ -30,6 +30,8 @@ bool isGlobalPropertyConstant(const Expression& expression, const T& properties)
bool isFeatureConstant(const Expression& expression);
bool isZoomConstant(const Expression& e);
// Returns true if expression does not depend on information provided by the runtime.
bool isRuntimeConstant(const Expression& e);
} // namespace expression
} // namespace style

View File

@@ -14,65 +14,70 @@ template <class T>
std::string toString(const T& t);
struct NullType {
constexpr NullType() {};
constexpr NullType() = default;
std::string getName() const { return "null"; }
bool operator==(const NullType&) const { return true; }
};
struct NumberType {
constexpr NumberType() {};
constexpr NumberType() = default;
std::string getName() const { return "number"; }
bool operator==(const NumberType&) const { return true; }
};
struct BooleanType {
constexpr BooleanType() {};
constexpr BooleanType() = default;
std::string getName() const { return "boolean"; }
bool operator==(const BooleanType&) const { return true; }
};
struct StringType {
constexpr StringType() {};
constexpr StringType() = default;
std::string getName() const { return "string"; }
bool operator==(const StringType&) const { return true; }
};
struct ColorType {
constexpr ColorType() {};
constexpr ColorType() = default;
std::string getName() const { return "color"; }
bool operator==(const ColorType&) const { return true; }
};
struct ObjectType {
constexpr ObjectType() {};
constexpr ObjectType() = default;
std::string getName() const { return "object"; }
bool operator==(const ObjectType&) const { return true; }
};
struct ErrorType {
constexpr ErrorType() {};
constexpr ErrorType() = default;
std::string getName() const { return "error"; }
bool operator==(const ErrorType&) const { return true; }
};
struct ValueType {
constexpr ValueType() {};
constexpr ValueType() = default;
std::string getName() const { return "value"; }
bool operator==(const ValueType&) const { return true; }
};
struct CollatorType {
constexpr CollatorType() {}; // NOLINT
constexpr CollatorType() = default;
std::string getName() const { return "collator"; }
bool operator==(const CollatorType&) const { return true; }
};
struct FormattedType {
constexpr FormattedType() {}; // NOLINT
constexpr FormattedType() = default;
std::string getName() const { return "formatted"; }
bool operator==(const FormattedType&) const { return true; }
};
struct ImageType {
constexpr ImageType() = default;
std::string getName() const { return "resolvedImage"; }
bool operator==(const ImageType&) const { return true; }
};
constexpr NullType Null;
constexpr NumberType Number;
@@ -84,21 +89,22 @@ constexpr ObjectType Object;
constexpr CollatorType Collator;
constexpr FormattedType Formatted;
constexpr ErrorType Error;
constexpr ImageType Image;
struct Array;
using Type = variant<
NullType,
NumberType,
BooleanType,
StringType,
ColorType,
ObjectType,
ValueType,
mapbox::util::recursive_wrapper<Array>,
CollatorType,
FormattedType,
ErrorType>;
using Type = variant<NullType,
NumberType,
BooleanType,
StringType,
ColorType,
ObjectType,
ValueType,
mapbox::util::recursive_wrapper<Array>,
CollatorType,
FormattedType,
ErrorType,
ImageType>;
struct Array {
explicit Array(Type itemType_) : itemType(std::move(itemType_)) {}

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/expression/collator.hpp>
#include <mbgl/style/expression/formatted.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/expression/type.hpp>
#include <mbgl/style/position.hpp>
#include <mbgl/style/types.hpp>
@@ -19,16 +20,16 @@ namespace expression {
struct Value;
using ValueBase = variant<
NullValue,
bool,
double,
std::string,
Color,
Collator,
Formatted,
mapbox::util::recursive_wrapper<std::vector<Value>>,
mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>;
using ValueBase = variant<NullValue,
bool,
double,
std::string,
Color,
Collator,
Formatted,
Image,
mapbox::util::recursive_wrapper<std::vector<Value>>,
mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>;
struct Value : ValueBase {
using ValueBase::ValueBase;

View File

@@ -40,9 +40,9 @@ public:
void setBackgroundOpacityTransition(const TransitionOptions&);
TransitionOptions getBackgroundOpacityTransition() const;
static PropertyValue<std::string> getDefaultBackgroundPattern();
const PropertyValue<std::string>& getBackgroundPattern() const;
void setBackgroundPattern(const PropertyValue<std::string>&);
static PropertyValue<expression::Image> getDefaultBackgroundPattern();
const PropertyValue<expression::Image>& getBackgroundPattern() const;
void setBackgroundPattern(const PropertyValue<expression::Image>&);
void setBackgroundPatternTransition(const TransitionOptions&);
TransitionOptions getBackgroundPatternTransition() const;

View File

@@ -52,9 +52,9 @@ public:
void setFillExtrusionOpacityTransition(const TransitionOptions&);
TransitionOptions getFillExtrusionOpacityTransition() const;
static PropertyValue<std::string> getDefaultFillExtrusionPattern();
const PropertyValue<std::string>& getFillExtrusionPattern() const;
void setFillExtrusionPattern(const PropertyValue<std::string>&);
static PropertyValue<expression::Image> getDefaultFillExtrusionPattern();
const PropertyValue<expression::Image>& getFillExtrusionPattern() const;
void setFillExtrusionPattern(const PropertyValue<expression::Image>&);
void setFillExtrusionPatternTransition(const TransitionOptions&);
TransitionOptions getFillExtrusionPatternTransition() const;

View File

@@ -52,9 +52,9 @@ public:
void setFillOutlineColorTransition(const TransitionOptions&);
TransitionOptions getFillOutlineColorTransition() const;
static PropertyValue<std::string> getDefaultFillPattern();
const PropertyValue<std::string>& getFillPattern() const;
void setFillPattern(const PropertyValue<std::string>&);
static PropertyValue<expression::Image> getDefaultFillPattern();
const PropertyValue<expression::Image>& getFillPattern() const;
void setFillPattern(const PropertyValue<expression::Image>&);
void setFillPatternTransition(const TransitionOptions&);
TransitionOptions getFillPatternTransition() const;

View File

@@ -91,9 +91,9 @@ public:
void setLineOpacityTransition(const TransitionOptions&);
TransitionOptions getLineOpacityTransition() const;
static PropertyValue<std::string> getDefaultLinePattern();
const PropertyValue<std::string>& getLinePattern() const;
void setLinePattern(const PropertyValue<std::string>&);
static PropertyValue<expression::Image> getDefaultLinePattern();
const PropertyValue<expression::Image>& getLinePattern() const;
void setLinePattern(const PropertyValue<expression::Image>&);
void setLinePatternTransition(const TransitionOptions&);
TransitionOptions getLinePatternTransition() const;

View File

@@ -42,9 +42,9 @@ public:
const PropertyValue<bool>& getIconIgnorePlacement() const;
void setIconIgnorePlacement(const PropertyValue<bool>&);
static PropertyValue<std::string> getDefaultIconImage();
const PropertyValue<std::string>& getIconImage() const;
void setIconImage(const PropertyValue<std::string>&);
static PropertyValue<expression::Image> getDefaultIconImage();
const PropertyValue<expression::Image>& getIconImage() const;
void setIconImage(const PropertyValue<expression::Image>&);
static PropertyValue<bool> getDefaultIconKeepUpright();
const PropertyValue<bool>& getIconKeepUpright() const;

View File

@@ -16,7 +16,7 @@ public:
bool isZoomConstant() const noexcept;
bool isFeatureConstant() const noexcept;
bool canEvaluateWith(const expression::EvaluationContext&) const noexcept;
bool isRuntimeConstant() const noexcept;
float interpolationFactor(const Range<float>&, const float) const noexcept;
Range<float> getCoveringStops(const float, const float) const noexcept;
const expression::Expression& getExpression() const noexcept;
@@ -28,6 +28,7 @@ protected:
variant<std::nullptr_t, const expression::Interpolate*, const expression::Step*> zoomCurve;
bool isZoomConstant_;
bool isFeatureConstant_;
bool isRuntimeConstant_;
};
template <class T>
@@ -40,7 +41,6 @@ public:
}
T evaluate(const expression::EvaluationContext& context, T finalDefaultValue = T()) const {
assert(canEvaluateWith(context));
const expression::EvaluationResult result = expression->evaluate(context);
if (result) {
const optional<T> typed = expression::fromExpressionValue<T>(*result);
@@ -50,18 +50,38 @@ public:
}
T evaluate(float zoom) const {
assert(!isZoomConstant());
assert(isFeatureConstant());
return evaluate(expression::EvaluationContext(zoom));
}
T evaluate(const GeometryTileFeature& feature, T finalDefaultValue) const {
assert(isZoomConstant());
assert(!isFeatureConstant());
return evaluate(expression::EvaluationContext(&feature), finalDefaultValue);
}
T evaluate(const GeometryTileFeature& feature,
const std::set<std::string>& availableImages,
T finalDefaultValue) const {
return evaluate(expression::EvaluationContext(&feature).withAvailableImages(&availableImages),
finalDefaultValue);
}
T evaluate(float zoom, const GeometryTileFeature& feature, T finalDefaultValue) const {
return evaluate(expression::EvaluationContext(zoom, &feature), finalDefaultValue);
}
T evaluate(float zoom,
const GeometryTileFeature& feature,
const std::set<std::string>& availableImages,
T finalDefaultValue) const {
return evaluate(expression::EvaluationContext(zoom, &feature).withAvailableImages(&availableImages),
finalDefaultValue);
}
T evaluate(float zoom, const GeometryTileFeature& feature, const FeatureState& state, T finalDefaultValue) const {
assert(!isFeatureConstant());
return evaluate(expression::EvaluationContext(zoom, &feature, &state), finalDefaultValue);
}

View File

@@ -151,6 +151,8 @@ add_library(
${MBGL_ROOT}/include/mbgl/style/expression/format_section_override.hpp
${MBGL_ROOT}/include/mbgl/style/expression/formatted.hpp
${MBGL_ROOT}/include/mbgl/style/expression/get_covering_stops.hpp
${MBGL_ROOT}/include/mbgl/style/expression/image.hpp
${MBGL_ROOT}/include/mbgl/style/expression/image_expression.hpp
${MBGL_ROOT}/include/mbgl/style/expression/interpolate.hpp
${MBGL_ROOT}/include/mbgl/style/expression/interpolator.hpp
${MBGL_ROOT}/include/mbgl/style/expression/is_constant.hpp
@@ -613,6 +615,8 @@ add_library(
${MBGL_ROOT}/src/mbgl/style/expression/format_expression.cpp
${MBGL_ROOT}/src/mbgl/style/expression/formatted.cpp
${MBGL_ROOT}/src/mbgl/style/expression/get_covering_stops.cpp
${MBGL_ROOT}/src/mbgl/style/expression/image.cpp
${MBGL_ROOT}/src/mbgl/style/expression/image_expression.cpp
${MBGL_ROOT}/src/mbgl/style/expression/interpolate.cpp
${MBGL_ROOT}/src/mbgl/style/expression/is_constant.cpp
${MBGL_ROOT}/src/mbgl/style/expression/is_expression.cpp

View File

@@ -35,16 +35,14 @@ void NodeExpression::Init(v8::Local<v8::Object> target) {
}
type::Type parseType(v8::Local<v8::Object> type) {
static std::unordered_map<std::string, type::Type> types = {
{"string", type::String},
{"number", type::Number},
{"boolean", type::Boolean},
{"object", type::Object},
{"color", type::Color},
{"value", type::Value},
{"formatted", type::Formatted},
{"number-format", type::String}
};
static std::unordered_map<std::string, type::Type> types = {{"string", type::String},
{"number", type::Number},
{"boolean", type::Boolean},
{"object", type::Object},
{"color", type::Color},
{"value", type::Value},
{"formatted", type::Formatted},
{"number-format", type::String}};
v8::Local<v8::Value> v8kind = Nan::Get(type, Nan::New("kind").ToLocalChecked()).ToLocalChecked();
std::string kind(*v8::String::Utf8Value(v8kind));

View File

@@ -16,10 +16,12 @@
"expression-tests/legacy/interval/composite": "https://github.com/mapbox/mapbox-gl-native/issues/12747",
"expression-tests/legacy/interval/composite-default": "https://github.com/mapbox/mapbox-gl-native/issues/12747",
"expression-tests/legacy/interval/tokens-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/12747",
"expression-tests/image/basic": "https://github.com/mapbox/mapbox-gl-native/issues/15800",
"expression-tests/image/compound": "https://github.com/mapbox/mapbox-gl-native/issues/15800",
"expression-tests/image/coalesce": "https://github.com/mapbox/mapbox-gl-native/issues/15800",
"expression-tests/image/implicit-assert": "https://github.com/mapbox/mapbox-gl-native/issues/15800",
"expression-tests/in/assert-array": "https://github.com/mapbox/mapbox-gl-native/issues/15893",
"expression-tests/in/assert-string": "https://github.com/mapbox/mapbox-gl-native/issues/15893",
"expression-tests/in/basic-array": "https://github.com/mapbox/mapbox-gl-native/issues/15893",
"expression-tests/in/basic-string": "https://github.com/mapbox/mapbox-gl-native/issues/15893",
"expression-tests/in/invalid-haystack": "https://github.com/mapbox/mapbox-gl-native/issues/15893",
"expression-tests/in/invalid-needle": "https://github.com/mapbox/mapbox-gl-native/issues/15893",
"query-tests/geometry/multilinestring": "needs investigation",
"query-tests/geometry/multipolygon": "needs investigation",
"query-tests/geometry/polygon": "needs investigation",
@@ -77,7 +79,6 @@
"render-tests/line-sort-key/literal": "https://github.com/mapbox/mapbox-gl-native/issues/15008",
"render-tests/regressions/mapbox-gl-js#8817": "skip - https://github.com/mapbox/mapbox-gl-native/issues/15737",
"render-tests/text-max-width/zero-width-point-placement": "https://github.com/mapbox/mapbox-gl-native/issues/15648",
"render-tests/icon-image/image-expression": "https://github.com/mapbox/mapbox-gl-native/issues/15800",
"render-tests/icon-text-fit/text-variable-anchor-overlap": "https://github.com/mapbox/mapbox-gl-native/issues/15809",
"query-tests/fill-extrusion/base-in": "https://github.com/mapbox/mapbox-gl-native/issues/13139",
"query-tests/fill-extrusion/box-in": "https://github.com/mapbox/mapbox-gl-native/issues/13139",
@@ -87,5 +88,6 @@
"query-tests/fill-extrusion/sort-rotated": "https://github.com/mapbox/mapbox-gl-native/issues/13139",
"query-tests/fill-extrusion/sort": "https://github.com/mapbox/mapbox-gl-native/issues/13139",
"query-tests/fill-extrusion/top-in": "https://github.com/mapbox/mapbox-gl-native/issues/13139",
"query-tests/regressions/mapbox-gl-js#7883": "https://github.com/mapbox/mapbox-gl-native/issues/14585"
"query-tests/regressions/mapbox-gl-js#7883": "https://github.com/mapbox/mapbox-gl-native/issues/14585",
"render-tests/fill-pattern/update-feature-state": "https://github.com/mapbox/mapbox-gl-native/issues/15895"
}

View File

@@ -35,8 +35,9 @@ global.expressionType = function (property) {
case 'number':
case 'enum':
return 'NumberType';
case 'image':
return 'ImageType';
case 'string':
case 'image': // TODO: replace once we implement image expressions
return 'StringType';
case 'color':
return `ColorType`;
@@ -66,10 +67,11 @@ global.evaluatedType = function (property) {
return 'bool';
case 'number':
return 'float';
case 'resolvedImage':
return 'expression::Image';
case 'formatted':
return 'expression::Formatted';
case 'string':
case 'image': // TODO: replace once we implement image expressions
return 'std::string';
case 'enum':
return (isLightProperty(property) ? 'Light' : '') + `${camelize(property.name)}Type`;
@@ -168,8 +170,8 @@ global.defaultValue = function (property) {
}
case 'formatted':
case 'string':
case 'image': // TODO: replace once we implement image expressions
return JSON.stringify(property.default || "");
case 'resolvedImage':
return property.default ? `{${JSON.stringify(property.default)}}` : '{}';
case 'enum':
if (property.default === undefined) {
return `${evaluatedType(property)}::Undefined`;
@@ -191,9 +193,9 @@ global.defaultValue = function (property) {
case 'array':
const defaults = (property.default || []).map((e) => defaultValue({ type: property.value, default: e }));
if (property.length) {
return `{{ ${defaults.join(', ')} }}`;
return `{{${defaults.join(', ')}}}`;
} else {
return `{ ${defaults.join(', ')} }`;
return `{${defaults.join(', ')}}`;
}
default:
return property.default;

View File

@@ -192,6 +192,8 @@
"src/mbgl/style/expression/format_expression.cpp",
"src/mbgl/style/expression/formatted.cpp",
"src/mbgl/style/expression/get_covering_stops.cpp",
"src/mbgl/style/expression/image.cpp",
"src/mbgl/style/expression/image_expression.cpp",
"src/mbgl/style/expression/interpolate.cpp",
"src/mbgl/style/expression/is_constant.cpp",
"src/mbgl/style/expression/is_expression.cpp",
@@ -418,6 +420,8 @@
"mbgl/style/expression/format_section_override.hpp": "include/mbgl/style/expression/format_section_override.hpp",
"mbgl/style/expression/formatted.hpp": "include/mbgl/style/expression/formatted.hpp",
"mbgl/style/expression/get_covering_stops.hpp": "include/mbgl/style/expression/get_covering_stops.hpp",
"mbgl/style/expression/image.hpp": "include/mbgl/style/expression/image.hpp",
"mbgl/style/expression/image_expression.hpp": "include/mbgl/style/expression/image_expression.hpp",
"mbgl/style/expression/interpolate.hpp": "include/mbgl/style/expression/interpolate.hpp",
"mbgl/style/expression/interpolator.hpp": "include/mbgl/style/expression/interpolator.hpp",
"mbgl/style/expression/is_constant.hpp": "include/mbgl/style/expression/is_constant.hpp",

View File

@@ -1,15 +1,16 @@
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/annotation/annotation_source.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/annotation/line_annotation_impl.hpp>
#include <mbgl/annotation/fill_annotation_impl.hpp>
#include <mbgl/annotation/line_annotation_impl.hpp>
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/layermanager/layer_manager.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_impl.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_impl.hpp>
#include <boost/function_output_iterator.hpp>
@@ -184,7 +185,8 @@ void AnnotationManager::updateStyle() {
using namespace expression::dsl;
layer->setSourceLayer(PointLayerID);
layer->setIconImage(PropertyExpression<std::string>(concat(vec(literal(SourceID + "."), toString(get("sprite"))))));
layer->setIconImage(PropertyExpression<expression::Image>(
image(concat(vec(literal(SourceID + "."), toString(get("sprite")))))));
layer->setIconAllowOverlap(true);
layer->setIconIgnorePlacement(true);

View File

@@ -29,7 +29,7 @@ std::unique_ptr<Layout> FillExtrusionLayerFactory::createLayout(const LayoutPara
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
using namespace style;
using LayoutType = PatternLayout<FillExtrusionBucket, FillExtrusionLayerProperties, FillExtrusionPattern>;
return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies);
return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters);
}
std::unique_ptr<RenderLayer> FillExtrusionLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {

View File

@@ -30,7 +30,7 @@ FillLayerFactory::createLayout(const LayoutParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
using namespace style;
using LayoutType = PatternLayout<FillBucket, FillLayerProperties, FillPattern>;
return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies);
return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters);
}
std::unique_ptr<RenderLayer> FillLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {

View File

@@ -29,7 +29,7 @@ std::unique_ptr<Layout> LineLayerFactory::createLayout(const LayoutParameters& p
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
using namespace style;
using LayoutType = PatternLayout<LineBucket, LineLayerProperties, LinePattern, LineLayoutProperties::PossiblyEvaluated>;
return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters.imageDependencies);
return std::make_unique<LayoutType>(parameters.bucketParameters, group, std::move(layer), parameters);
}
std::unique_ptr<RenderLayer> LineLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {

View File

@@ -27,11 +27,7 @@ std::unique_ptr<style::Layer> SymbolLayerFactory::createLayer(const std::string&
std::unique_ptr<Layout> SymbolLayerFactory::createLayout(const LayoutParameters& parameters,
std::unique_ptr<GeometryTileLayer> tileLayer,
const std::vector<Immutable<style::LayerProperties>>& group) noexcept {
return std::make_unique<SymbolLayout>(parameters.bucketParameters,
group,
std::move(tileLayer),
parameters.imageDependencies,
parameters.glyphDependencies);
return std::make_unique<SymbolLayout>(parameters.bucketParameters, group, std::move(tileLayer), parameters);
}
std::unique_ptr<RenderLayer> SymbolLayerFactory::createRenderLayer(Immutable<style::Layer::Impl> impl) noexcept {

View File

@@ -38,6 +38,7 @@ public:
const BucketParameters& bucketParameters;
GlyphDependencies& glyphDependencies;
ImageDependencies& imageDependencies;
std::set<std::string>& availableImages;
};
} // namespace mbgl

View File

@@ -1,8 +1,9 @@
#pragma once
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/layout/layout.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layer_properties.hpp>
namespace mbgl {
@@ -32,11 +33,11 @@ public:
PatternLayout(const BucketParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& group,
std::unique_ptr<GeometryTileLayer> sourceLayer_,
ImageDependencies& patternDependencies)
: sourceLayer(std::move(sourceLayer_)),
zoom(parameters.tileID.overscaledZ),
overscaling(parameters.tileID.overscaleFactor()),
hasPattern(false) {
const LayoutParameters& layoutParameters)
: sourceLayer(std::move(sourceLayer_)),
zoom(parameters.tileID.overscaledZ),
overscaling(parameters.tileID.overscaleFactor()),
hasPattern(false) {
assert(!group.empty());
auto leaderLayerProperties = staticImmutableCast<LayerPropertiesType>(group.front());
layout = leaderLayerProperties->layerImpl().layout.evaluate(PropertyEvaluationParameters(zoom));
@@ -47,15 +48,15 @@ public:
const std::string& layerId = layerProperties->baseImpl->id;
const auto& evaluated = style::getEvaluated<LayerPropertiesType>(layerProperties);
const auto patternProperty = evaluated.template get<PatternPropertyType>();
const auto constantPattern = patternProperty.constantOr(Faded<std::basic_string<char> >{ "", ""});
const auto constantPattern = patternProperty.constantOr(Faded<style::expression::Image>{"", ""});
// determine if layer group has any layers that use *-pattern property and add
// constant pattern dependencies.
if (!patternProperty.isConstant()) {
hasPattern = true;
} else if (!constantPattern.to.empty()){
} else if (!constantPattern.to.id().empty()) {
hasPattern = true;
patternDependencies.emplace(constantPattern.to, ImageType::Pattern);
patternDependencies.emplace(constantPattern.from, ImageType::Pattern);
layoutParameters.imageDependencies.emplace(constantPattern.to.id(), ImageType::Pattern);
layoutParameters.imageDependencies.emplace(constantPattern.from.id(), ImageType::Pattern);
}
layerPropertiesMap.emplace(layerId, layerProperties);
}
@@ -77,15 +78,22 @@ public:
if (!patternProperty.isConstant()) {
// For layers with non-data-constant pattern properties, evaluate their expression and add
// the patterns to the dependency vector
const auto min = patternProperty.evaluate(*feature, zoom - 1, PatternPropertyType::defaultValue());
const auto mid = patternProperty.evaluate(*feature, zoom, PatternPropertyType::defaultValue());
const auto max = patternProperty.evaluate(*feature, zoom + 1, PatternPropertyType::defaultValue());
patternDependencies.emplace(min.to, ImageType::Pattern);
patternDependencies.emplace(mid.to, ImageType::Pattern);
patternDependencies.emplace(max.to, ImageType::Pattern);
patternDependencyMap.emplace(layerId, PatternDependency {min.to, mid.to, max.to});
const auto min = patternProperty.evaluate(*feature,
zoom - 1,
layoutParameters.availableImages,
PatternPropertyType::defaultValue());
const auto mid = patternProperty.evaluate(
*feature, zoom, layoutParameters.availableImages, PatternPropertyType::defaultValue());
const auto max = patternProperty.evaluate(*feature,
zoom + 1,
layoutParameters.availableImages,
PatternPropertyType::defaultValue());
layoutParameters.imageDependencies.emplace(min.to.id(), ImageType::Pattern);
layoutParameters.imageDependencies.emplace(mid.to.id(), ImageType::Pattern);
layoutParameters.imageDependencies.emplace(max.to.id(), ImageType::Pattern);
patternDependencyMap.emplace(layerId,
PatternDependency{min.to.id(), mid.to.id(), max.to.id()});
}
}
}

View File

@@ -1,8 +1,9 @@
#pragma once
#include <mbgl/style/expression/image.hpp>
#include <mbgl/text/tagged_string.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/text/tagged_string.hpp>
#include <array>
#include <string>
@@ -29,7 +30,7 @@ public:
std::unique_ptr<GeometryTileFeature> feature;
GeometryCollection geometry;
optional<TaggedString> formattedText;
optional<std::string> icon;
optional<style::expression::Image> icon;
float sortKey = 0.0f;
std::size_t index;
bool allowsVerticalWritingMode = false;

View File

@@ -81,8 +81,7 @@ inline Immutable<style::SymbolLayoutProperties::PossiblyEvaluated> createLayout(
SymbolLayout::SymbolLayout(const BucketParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& layers,
std::unique_ptr<GeometryTileLayer> sourceLayer_,
ImageDependencies& imageDependencies,
GlyphDependencies& glyphDependencies)
const LayoutParameters& layoutParameters)
: bucketLeaderID(layers.front()->baseImpl->id),
sourceLayer(std::move(sourceLayer_)),
overscaling(parameters.tileID.overscaleFactor()),
@@ -141,7 +140,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
ft.index = i;
if (hasText) {
auto formatted = layout->evaluate<TextField>(zoom, ft);
auto formatted = layout->evaluate<TextField>(zoom, ft, layoutParameters.availableImages);
auto textTransform = layout->evaluate<TextTransform>(zoom, ft);
FontStack baseFontStack = layout->evaluate<TextFont>(zoom, ft);
@@ -168,7 +167,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
// Loop through all characters of this text and collect unique codepoints.
for (std::size_t j = 0; j < ft.formattedText->length(); j++) {
const auto& sectionFontStack = formatted.sections[ft.formattedText->getSectionIndex(j)].fontStack;
GlyphIDs& dependencies = glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack];
GlyphIDs& dependencies =
layoutParameters.glyphDependencies[sectionFontStack ? *sectionFontStack : baseFontStack];
char16_t codePoint = ft.formattedText->getCharCodeAt(j);
dependencies.insert(codePoint);
if (canVerticalizeText || (allowVerticalPlacement && ft.formattedText->allowsVerticalWritingMode())) {
@@ -180,8 +180,8 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
}
if (hasIcon) {
ft.icon = layout->evaluate<IconImage>(zoom, ft);
imageDependencies.emplace(*ft.icon, ImageType::Icon);
ft.icon = layout->evaluate<IconImage>(zoom, ft, layoutParameters.availableImages);
layoutParameters.imageDependencies.emplace(ft.icon->id(), ImageType::Icon);
}
if (ft.formattedText || ft.icon) {
@@ -448,14 +448,13 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
// if feature has icon, get sprite atlas position
SymbolContent iconType{SymbolContent::None};
if (feature.icon) {
auto image = imageMap.find(*feature.icon);
auto image = imageMap.find(feature.icon->id());
if (image != imageMap.end()) {
iconType = SymbolContent::IconRGBA;
shapedIcon = PositionedIcon::shapeIcon(
imagePositions.at(*feature.icon),
layout->evaluate<IconOffset>(zoom, feature),
layout->evaluate<IconAnchor>(zoom, feature),
layout->evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
shapedIcon = PositionedIcon::shapeIcon(imagePositions.at(feature.icon->id()),
layout->evaluate<IconOffset>(zoom, feature),
layout->evaluate<IconAnchor>(zoom, feature),
layout->evaluate<IconRotate>(zoom, feature) * util::DEG2RAD);
if (image->second->sdf) {
iconType = SymbolContent::IconSDF;
}

View File

@@ -27,9 +27,8 @@ public:
SymbolLayout(const BucketParameters&,
const std::vector<Immutable<style::LayerProperties>>&,
std::unique_ptr<GeometryTileLayer>,
ImageDependencies&,
GlyphDependencies&);
const LayoutParameters& parameters);
~SymbolLayout() final = default;
void prepareSymbols(const GlyphMap&, const GlyphPositions&,

View File

@@ -1,4 +1,5 @@
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/util/chrono.hpp>
#include <cmath>
@@ -30,7 +31,7 @@ Faded<T> CrossFadedPropertyEvaluator<T>::calculate(const T& min, const T& mid, c
: Faded<T> { max, mid };
}
template class CrossFadedPropertyEvaluator<std::string>;
template class CrossFadedPropertyEvaluator<style::expression::Image>;
template class CrossFadedPropertyEvaluator<std::vector<float>>;
} // namespace mbgl

View File

@@ -26,14 +26,14 @@ public:
ResultType operator()(const style::PropertyExpression<T>& expression) const {
if (useIntegerZoom) { // Compiler will optimize out the unused branch.
if (!expression.isFeatureConstant()) {
if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) {
auto returnExpression = expression;
returnExpression.useIntegerZoom = true;
return ResultType(returnExpression);
}
}
return ResultType(expression.evaluate(floor(parameters.z)));
} else {
if (!expression.isFeatureConstant()) {
if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) {
return ResultType(expression);
}
return ResultType(expression.evaluate(parameters.z));
@@ -63,7 +63,7 @@ public:
}
ResultType operator()(const style::PropertyExpression<T>& expression) const {
if (!expression.isFeatureConstant()) {
if (!expression.isFeatureConstant() || !expression.isRuntimeConstant()) {
return ResultType(expression);
} else {
const T evaluated = expression.evaluate(floor(parameters.z));

View File

@@ -43,6 +43,7 @@ void ImageManager::addImage(Immutable<style::Image::Impl> image_) {
if (requestedImages.find(image_->id) != requestedImages.end()) {
requestedImagesCacheSize += image_->image.bytes();
}
availableImages.emplace(image_->id);
images.emplace(image_->id, std::move(image_));
}
@@ -81,6 +82,7 @@ void ImageManager::removeImage(const std::string& id) {
requestedImages.erase(requestedIt);
}
images.erase(it);
availableImages.erase(id);
updatedImageVersions.erase(id);
}
@@ -169,6 +171,10 @@ void ImageManager::reduceMemoryUseIfCacheSizeExceedsLimit() {
}
}
const std::set<std::string>& ImageManager::getAvailableImages() const {
return availableImages;
}
void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) {
ImageDependencies missingDependencies;

View File

@@ -47,6 +47,7 @@ public:
void notifyIfMissingImageAdded();
void reduceMemoryUse();
void reduceMemoryUseIfCacheSizeExceedsLimit();
const std::set<std::string>& getAvailableImages() const;
ImageVersionMap updatedImageVersions;
@@ -62,6 +63,8 @@ private:
std::map<std::string, std::set<ImageRequestor*>> requestedImages;
std::size_t requestedImagesCacheSize = 0ul;
ImageMap images;
// Mirror of 'ImageMap images;' keys.
std::set<std::string> availableImages;
ImageManagerObserver* observer = nullptr;
};

View File

@@ -105,8 +105,10 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) {
const auto& evaluated = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).evaluated;
const auto& crossfade = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).crossfade;
if (!evaluated.get<BackgroundPattern>().to.empty()) {
optional<ImagePosition> imagePosA = parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().from);
optional<ImagePosition> imagePosB = parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().to);
optional<ImagePosition> imagePosA =
parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().from.id());
optional<ImagePosition> imagePosB =
parameters.patternAtlas.getPattern(evaluated.get<BackgroundPattern>().to.id());
if (!imagePosA || !imagePosB)
return;
@@ -176,8 +178,8 @@ void RenderBackgroundLayer::prepare(const LayerPrepareParameters& params) {
if (!evaluated.get<BackgroundPattern>().to.empty()) {
// Ensures that the pattern bitmap gets copied to atlas bitmap.
// Atlas bitmap is uploaded to atlas texture in upload.
addPatternIfNeeded(evaluated.get<BackgroundPattern>().from, params);
addPatternIfNeeded(evaluated.get<BackgroundPattern>().to, params);
addPatternIfNeeded(evaluated.get<BackgroundPattern>().from.id(), params);
addPatternIfNeeded(evaluated.get<BackgroundPattern>().to.id(), params);
}
}

View File

@@ -1,20 +1,21 @@
#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
#include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/fill_extrusion_program.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/render_pass.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/render_pass.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/programs/fill_extrusion_program.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -171,7 +172,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
}
} else {
// Draw textured extrusions
const auto fillPatternValue = evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<std::basic_string<char> >{"", ""});
const auto fillPatternValue =
evaluated.get<FillExtrusionPattern>().constantOr(mbgl::Faded<expression::Image>{"", ""});
auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) {
for (const RenderTile& tile : *renderTiles) {
const LayerRenderData* renderData = getRenderDataForPass(tile, parameters.pass);
@@ -179,8 +181,8 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
continue;
}
auto& bucket = static_cast<FillExtrusionBucket&>(*renderData->bucket);
optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from);
optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to);
optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from.id());
optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to.id());
draw(
parameters.programs.getFillExtrusionLayerPrograms().fillExtrusionPattern,

View File

@@ -1,21 +1,22 @@
#include <mbgl/renderer/layers/render_fill_layer.hpp>
#include <mbgl/renderer/buckets/fill_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/render_source.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/fill_program.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/programs/fill_program.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/renderer/buckets/fill_bucket.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/renderer/layers/render_fill_layer.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_source.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -171,9 +172,9 @@ void RenderFillLayer::render(PaintParameters& parameters) {
const auto& evaluated = getEvaluated<FillLayerProperties>(renderData->layerProperties);
const auto& crossfade = getCrossfade<FillLayerProperties>(renderData->layerProperties);
const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<std::basic_string<char>>{"", ""});
optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from);
optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to);
const auto& fillPatternValue = evaluated.get<FillPattern>().constantOr(Faded<expression::Image>{"", ""});
optional<ImagePosition> patternPosA = tile.getPattern(fillPatternValue.from.id());
optional<ImagePosition> patternPosB = tile.getPattern(fillPatternValue.to.id());
auto draw = [&] (auto& programInstance,
const auto& drawMode,

View File

@@ -1,20 +1,21 @@
#include <mbgl/renderer/layers/render_line_layer.hpp>
#include <mbgl/renderer/buckets/line_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/render_source.hpp>
#include <mbgl/renderer/upload_parameters.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/line_program.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/programs/line_program.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/renderer/buckets/line_bucket.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/renderer/layers/render_line_layer.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_source.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/upload_parameters.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -168,11 +169,11 @@ void RenderLineLayer::render(PaintParameters& parameters) {
});
} else if (!unevaluated.get<LinePattern>().isUndefined()) {
const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""});
const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<expression::Image>{"", ""});
const Size& texsize = tile.getIconAtlasTexture().size;
optional<ImagePosition> posA = tile.getPattern(linePatternValue.from);
optional<ImagePosition> posB = tile.getPattern(linePatternValue.to);
optional<ImagePosition> posA = tile.getPattern(linePatternValue.from.id());
optional<ImagePosition> posB = tile.getPattern(linePatternValue.to.id());
draw(parameters.programs.getLineLayerPrograms().linePattern,
LinePatternProgram::layoutUniformValues(

View File

@@ -93,16 +93,19 @@ public:
}
template <class Feature>
Faded<T> evaluate(const Feature& feature, float zoom, T defaultValue) const {
Faded<T> evaluate(const Feature& feature,
float zoom,
const std::set<std::string>& availableImages,
T defaultValue) const {
return this->match(
[&] (const Faded<T>& constant_) { return constant_; },
[&] (const style::PropertyExpression<T>& expression) {
if (!expression.isZoomConstant()) {
const T min = expression.evaluate(floor(zoom), feature, defaultValue);
const T max = expression.evaluate(floor(zoom) + 1, feature, defaultValue);
const T min = expression.evaluate(floor(zoom), feature, availableImages, defaultValue);
const T max = expression.evaluate(floor(zoom) + 1, feature, availableImages, defaultValue);
return Faded<T> {min, max};
} else {
const T evaluated = expression.evaluate(feature, defaultValue);
const T evaluated = expression.evaluate(feature, availableImages, defaultValue);
return Faded<T> {evaluated, evaluated};
}
}

View File

@@ -1,13 +1,14 @@
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/case.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/dsl_impl.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/expression/image_expression.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/case.hpp>
#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/util/string.hpp>
#include <cassert>
@@ -46,6 +47,10 @@ std::unique_ptr<Expression> convertTokenStringToFormatExpression(const std::stri
return std::make_unique<FormatExpression>(sections);
}
std::unique_ptr<Expression> convertTokenStringToImageExpression(const std::string& source) {
return std::make_unique<ImageExpression>(convertTokenStringToExpression(source));
}
std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& source) {
std::vector<std::unique_ptr<Expression>> inputs;
@@ -149,11 +154,11 @@ template optional<PropertyExpression<TextTransformType>>
convertFunctionToExpression<TextTransformType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TranslateAnchorType>>
convertFunctionToExpression<TranslateAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<Formatted>>
convertFunctionToExpression<Formatted>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::vector<TextWritingModeType>>>
convertFunctionToExpression<std::vector<TextWritingModeType>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<Image>> convertFunctionToExpression<Image>(const Convertible&, Error&, bool);
// Ad-hoc Converters for double and int64_t. We should replace float with double wholesale,
// and promote the int64_t Converter to general use (and it should check that the input is
@@ -207,35 +212,35 @@ static bool interpolatable(type::Type type) {
static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error, bool convertTokens = false) {
return type.match(
[&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<float>(value, error);
if (!result) {
return nullopt;
}
return literal(double(*result));
},
[&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<bool>(value, error);
if (!result) {
return nullopt;
}
return literal(*result);
},
[&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::StringType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<std::string>(value, error);
if (!result) {
return nullopt;
}
return convertTokens ? convertTokenStringToExpression(*result) : literal(*result);
},
[&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<Color>(value, error);
if (!result) {
return nullopt;
}
return literal(*result);
},
[&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
[&](const type::Array& array) -> optional<std::unique_ptr<Expression>> {
if (!isArray(value)) {
error.message = "value must be an array";
return nullopt;
@@ -277,27 +282,27 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con
}
);
},
[&] (const type::NullType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::NullType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
[&] (const type::ObjectType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::ObjectType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
[&] (const type::ErrorType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::ErrorType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
[&] (const type::ValueType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::ValueType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
[&] (const type::CollatorType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::CollatorType&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
},
[&] (const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<std::string>(value, error);
if (!result) {
return nullopt;
@@ -305,8 +310,15 @@ static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, con
return convertTokens ?
convertTokenStringToFormatExpression(*result) :
literal(Formatted(result->c_str()));
}
);
},
[&](const type::ImageType&) -> optional<std::unique_ptr<Expression>> {
auto result = convert<std::string>(value, error);
if (!result) {
return nullopt;
}
return convertTokens ? std::make_unique<ImageExpression>(convertTokenStringToImageExpression(*result))
: literal(Image(result->c_str()));
});
}
static optional<std::map<double, std::unique_ptr<Expression>>> convertStops(type::Type type,
@@ -749,29 +761,31 @@ optional<std::unique_ptr<Expression>> convertFunctionToExpression(type::Type typ
if (functionType == FunctionType::Identity) {
return type.match(
[&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::StringType&) -> optional<std::unique_ptr<Expression>> {
return string(get(literal(*property)), defaultExpr());
},
[&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
return number(get(literal(*property)), defaultExpr());
},
[&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
return boolean(get(literal(*property)), defaultExpr());
},
[&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
return toColor(get(literal(*property)), defaultExpr());
},
[&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
[&](const type::Array& array) -> optional<std::unique_ptr<Expression>> {
return assertion(array, get(literal(*property)), defaultExpr());
},
[&] (const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
[&](const type::FormattedType&) -> optional<std::unique_ptr<Expression>> {
return toFormatted(get(literal(*property)), defaultExpr());
},
[&] (const auto&) -> optional<std::unique_ptr<Expression>> {
[&](const type::ImageType&) -> optional<std::unique_ptr<Expression>> {
return toImage(get(literal(*property)), defaultExpr());
},
[&](const auto&) -> optional<std::unique_ptr<Expression>> {
assert(false); // No properties use this type.
return nullopt;
}
);
});
}
auto stopsValue = objectMember(value, "stops");

View File

@@ -39,7 +39,8 @@ optional<PropertyValue<T>> Converter<PropertyValue<T>>::operator()(const Convert
} else if (!allowDataExpressions && !(*expression).isFeatureConstant()) {
error.message = "data expressions not supported";
return nullopt;
} else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant()) {
} else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant() ||
!(*expression).isRuntimeConstant()) {
return { std::move(*expression) };
} else if ((*expression).getExpression().getKind() == Kind::Literal) {
optional<T> constant = fromExpressionValue<T>(
@@ -81,6 +82,11 @@ template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<Text
template optional<PropertyValue<TranslateAnchorType>> Converter<PropertyValue<TranslateAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<mbgl::style::expression::Formatted>> Converter<PropertyValue<mbgl::style::expression::Formatted>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<std::vector<TextWritingModeType>>> Converter<PropertyValue<std::vector<TextWritingModeType>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<mbgl::style::expression::Image>>
Converter<PropertyValue<mbgl::style::expression::Image>>::operator()(conversion::Convertible const&,
conversion::Error&,
bool,
bool) const;
} // namespace conversion
} // namespace style

View File

@@ -141,6 +141,11 @@ void stringify(Writer& writer, const expression::Formatted& v) {
stringify(writer, expression::ValueConverter<mbgl::Value>::fromExpressionValue(v));
}
template <class Writer>
void stringify(Writer& writer, const expression::Image& v) {
stringify(writer, expression::ValueConverter<mbgl::Value>::fromExpressionValue(v));
}
template <class Writer>
void stringify(Writer& writer, const Undefined&) {
assert(false); // Should be omitted entirely instead.

View File

@@ -32,18 +32,9 @@ optional<std::string> checkSubtype(const Type& expected, const Type& t) {
},
[&] (const ValueType&) -> optional<std::string> {
if (t.is<ValueType>()) return {};
const Type members[] = {
Null,
Boolean,
Number,
String,
Object,
Color,
Formatted,
Array(Value)
};
const Type members[] = {Null, Boolean, Number, String, Object, Color, Formatted, Image, Array(Value)};
for (const auto& member : members) {
const auto err = checkSubtype(member, t);
if (!err) {

View File

@@ -8,8 +8,22 @@ namespace expression {
EvaluationResult Coalesce::evaluate(const EvaluationContext& params) const {
EvaluationResult result = Null;
std::size_t argsCount = args.size();
optional<Image> requestedImage;
for (const auto& arg : args) {
--argsCount;
result = arg->evaluate(params);
// We need to keep track of the first requested image in a coalesce statement.
// If coalesce can't find a valid image, we return the first requested image.
if (getType() == type::Image && result) {
const auto image = fromExpressionValue<Image>(*result);
if (image && !image->isAvailable()) {
if (!requestedImage) requestedImage = Image(image->id());
if (!argsCount) result = *requestedImage;
continue;
}
}
if (!result || *result != Null) break;
}
return result;

View File

@@ -9,13 +9,12 @@ namespace style {
namespace expression {
EvaluationResult toBoolean(const Value& v) {
return v.match(
[&] (double f) { return static_cast<bool>(f); },
[&] (const std::string& s) { return s.length() > 0; },
[&] (bool b) { return b; },
[&] (const NullValue&) { return false; },
[&] (const auto&) { return true; }
);
return v.match([&](double f) { return static_cast<bool>(f); },
[&](const std::string& s) { return s.length() > 0; },
[&](bool b) { return b; },
[&](const NullValue&) { return false; },
[&](const Image& i) { return i.isAvailable(); },
[&](const auto&) { return true; });
}
EvaluationResult toNumber(const Value& v) {
@@ -86,6 +85,10 @@ EvaluationResult toFormatted(const Value& formattedValue) {
return Formatted(toString(formattedValue).c_str());
}
EvaluationResult toImage(const Value& imageValue) {
return Image(toString(imageValue).c_str());
}
Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> inputs_) :
Expression(Kind::Coercion, std::move(type_)),
inputs(std::move(inputs_))
@@ -102,6 +105,8 @@ Coercion::Coercion(type::Type type_, std::vector<std::unique_ptr<Expression>> in
coerceSingleValue = [] (const Value& v) -> EvaluationResult { return toString(v); };
} else if (t.is<type::FormattedType>()) {
coerceSingleValue = toFormatted;
} else if (t.is<type::ImageType>()) {
coerceSingleValue = toImage;
} else {
assert(false);
}
@@ -115,6 +120,8 @@ mbgl::Value Coercion::serialize() const {
serialized.push_back(inputs[0]->serialize());
serialized.emplace_back(std::unordered_map<std::string, mbgl::Value>());
return serialized;
} else if (getType().is<type::ImageType>()) {
return std::vector<mbgl::Value>{{std::string("image")}, inputs[0]->serialize()};
} else {
return Expression::serialize();
}
@@ -148,11 +155,13 @@ ParseResult Coercion::parse(const Convertible& value, ParsingContext& ctx) {
auto it = types.find(*toString(arrayMember(value, 0)));
assert(it != types.end());
if ((it->second == type::Boolean || it->second == type::String || it->second == type::Formatted) && length != 2) {
if ((it->second == type::Boolean || it->second == type::String || it->second == type::Formatted ||
it->second == type::Image) &&
length != 2) {
ctx.error("Expected one argument.");
return ParseResult();
}
/**
* Special form for error-coalescing coercion expressions "to-number",
* "to-color". Since these coercions can fail at runtime, they accept multiple

View File

@@ -1,14 +1,15 @@
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/dsl_impl.hpp>
#include <mbgl/style/expression/error.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/assertion.hpp>
#include <mbgl/style/expression/coercion.hpp>
#include <mbgl/style/expression/comparison.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/dsl_impl.hpp>
#include <mbgl/style/expression/error.hpp>
#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/expression/image_expression.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mapbox/geojsonvt.hpp>
#include <mbgl/style/conversion/json.hpp>
@@ -122,7 +123,11 @@ std::unique_ptr<Expression> toFormatted(std::unique_ptr<Expression> value,
std::unique_ptr<Expression> def) {
return coercion(type::Formatted, std::move(value), std::move(def));
}
std::unique_ptr<Expression> toImage(std::unique_ptr<Expression> value, std::unique_ptr<Expression> def) {
return coercion(type::Image, std::move(value), std::move(def));
}
std::unique_ptr<Expression> get(const char* value) {
return get(literal(value));
}
@@ -237,6 +242,14 @@ std::unique_ptr<Expression> format(std::unique_ptr<Expression> input) {
return std::make_unique<FormatExpression>(sections);
}
std::unique_ptr<Expression> image(const char* value) {
return std::make_unique<Literal>(Image(value));
}
std::unique_ptr<Expression> image(std::unique_ptr<Expression> expression) {
return std::make_unique<ImageExpression>(std::move(expression));
}
} // namespace dsl
} // namespace expression
} // namespace style

View File

@@ -25,12 +25,22 @@ public:
return optional<mbgl::Value>();
}
};
EvaluationResult Expression::evaluate(optional<float> zoom, const Feature& feature, optional<double> colorRampParameter) const {
EvaluationResult Expression::evaluate(optional<float> zoom,
const Feature& feature,
optional<double> colorRampParameter) const {
GeoJSONFeature f(feature);
return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter));
}
EvaluationResult Expression::evaluate(optional<float> zoom,
const Feature& feature,
optional<double> colorRampParameter,
const std::set<std::string>& availableImages) const {
GeoJSONFeature f(feature);
return this->evaluate(EvaluationContext(zoom, &f, colorRampParameter).withAvailableImages(&availableImages));
}
EvaluationResult Expression::evaluate(optional<mbgl::Value> accumulated, const Feature& feature) const {
GeoJSONFeature f(feature);
return this->evaluate(EvaluationContext(accumulated, &f));

View File

@@ -0,0 +1,67 @@
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/image.hpp>
namespace mbgl {
namespace style {
namespace expression {
Image::Image(std::string imageID_, bool available_) : imageID(std::move(imageID_)), available(available_) {}
Image::Image(std::string imageID_) : Image(std::move(imageID_), false) {}
Image::Image(const char* imageID_) : Image(std::string(imageID_)) {
assert(imageID_);
}
bool Image::operator==(const Image& other) const {
return imageID == other.imageID && available == other.available;
}
mbgl::Value Image::toValue() const {
return mapbox::base::ValueObject{{"name", imageID}, {"available", available}};
}
const std::string& Image::id() const {
return imageID;
}
bool Image::isAvailable() const {
return available;
}
bool Image::empty() const {
return imageID.empty();
}
} // namespace expression
namespace conversion {
using namespace mbgl::style::expression;
optional<Image> Converter<Image>::operator()(const Convertible& value, Error& error) const {
if (isArray(value)) {
Convertible imageParameters = arrayMember(value, 0);
std::size_t imageParametersLength = arrayLength(imageParameters);
if (imageParametersLength < 1) {
error.message = "Image has to contain an ID.";
return nullopt;
}
optional<std::string> imageID = toString(arrayMember(imageParameters, 0));
if (!imageID) {
error.message = "Image has to contain an ID.";
return nullopt;
}
return Image(*imageID, false);
} else if (optional<std::string> result = toString(value)) {
return Image(*result, false);
} else {
error.message = "Image must be plain string or array type.";
return nullopt;
}
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -0,0 +1,68 @@
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/expression/image_expression.hpp>
namespace mbgl {
namespace style {
namespace expression {
ImageExpression::ImageExpression(std::unique_ptr<Expression> imageID_)
: Expression(Kind::ImageExpression, type::Image), imageID(std::move(imageID_)) {
assert(imageID);
}
using namespace mbgl::style::conversion;
ParseResult ImageExpression::parse(const Convertible& value, ParsingContext& ctx) {
std::size_t argsLength = arrayLength(value);
if (argsLength < 2) {
ctx.error("Invalid number of arguments for 'image' expression.");
return ParseResult();
}
// Parse expression that evaluates to image id.
auto imageIDArg = arrayMember(value, 1);
ParseResult imageIDExpr = ctx.parse(imageIDArg, 1, {type::String});
if (!imageIDExpr) {
return ParseResult();
}
return ParseResult(std::make_unique<ImageExpression>(std::move(*imageIDExpr)));
}
void ImageExpression::eachChild(const std::function<void(const Expression&)>& fn) const {
fn(*imageID);
}
bool ImageExpression::operator==(const Expression& e) const {
if (e.getKind() == Kind::ImageExpression) {
auto rhs = static_cast<const ImageExpression*>(&e);
return *imageID == *rhs->imageID;
}
return false;
}
mbgl::Value ImageExpression::serialize() const {
std::vector<mbgl::Value> serialized{{getOperator()}};
serialized.push_back(imageID->serialize());
return serialized;
}
EvaluationResult ImageExpression::evaluate(const EvaluationContext& ctx) const {
auto imageIDResult = imageID->evaluate(ctx);
if (!imageIDResult) {
return imageIDResult.error();
}
optional<std::string> evaluatedImageID = toString(*imageIDResult);
if (!evaluatedImageID) {
return EvaluationError({"Could not evaluate ID for 'image' expression."});
}
bool available = ctx.availableImages && ctx.availableImages->count(*evaluatedImageID);
return Image(*evaluatedImageID, available);
}
} // namespace expression
} // namespace style
} // namespace mbgl

View File

@@ -49,6 +49,19 @@ bool isZoomConstant(const Expression& e) {
return isGlobalPropertyConstant(e, std::array<std::string, 1>{{"zoom"}});
}
bool isRuntimeConstant(const Expression& expression) {
if (expression.getKind() == Kind::ImageExpression) {
return false;
}
bool runtimeConstant = true;
expression.eachChild([&](const Expression& e) {
if (runtimeConstant && !isRuntimeConstant(e)) {
runtimeConstant = false;
}
});
return runtimeConstant;
}
} // namespace expression
} // namespace style

View File

@@ -4,22 +4,23 @@
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/type.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/at.hpp>
#include <mbgl/style/expression/assertion.hpp>
#include <mbgl/style/expression/at.hpp>
#include <mbgl/style/expression/boolean_operator.hpp>
#include <mbgl/style/expression/case.hpp>
#include <mbgl/style/expression/coalesce.hpp>
#include <mbgl/style/expression/coercion.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/comparison.hpp>
#include <mbgl/style/expression/number_format.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/expression/image_expression.hpp>
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/expression/length.hpp>
#include <mbgl/style/expression/let.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/number_format.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/find_zoom_curve.hpp>
@@ -117,7 +118,7 @@ MAPBOX_ETERNAL_CONSTEXPR const auto expressionRegistry =
{"coalesce", Coalesce::parse},
{"collator", CollatorExpression::parse},
{"format", FormatExpression::parse},
{"image", Assertion::parse}, // TODO: replace once we implement image expressions
{"image", ImageExpression::parse},
{"interpolate", parseInterpolate},
{"length", Length::parse},
{"let", Let::parse},
@@ -193,7 +194,8 @@ ParseResult ParsingContext::parse(const Convertible& value, optional<TypeAnnotat
const type::Type actual = (*parsed)->getType();
if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object || expected->is<type::Array>()) && actual == type::Value) {
parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::assert)) };
} else if ((*expected == type::Color || *expected == type::Formatted) && (actual == type::Value || actual == type::String)) {
} else if ((*expected == type::Color || *expected == type::Formatted || *expected == type::Image) &&
(actual == type::Value || actual == type::String)) {
parsed = { annotate(std::move(*parsed), *expected, typeAnnotationOption.value_or(TypeAnnotationOption::coerce)) };
} else {
checkType((*parsed)->getType());
@@ -205,8 +207,9 @@ ParseResult ParsingContext::parse(const Convertible& value, optional<TypeAnnotat
// If an expression's arguments are all constant, we can evaluate
// it immediately and replace it with a literal value in the
// parsed result.
if ((*parsed)->getKind() != Kind::Literal && isConstant(**parsed)) {
// parsed/compiled result. Expressions that expect an image should
// not be resolved here so we can later get the available images.
if ((*parsed)->getKind() != Kind::Literal && (*parsed)->getType() != type::Image && isConstant(**parsed)) {
EvaluationContext params(nullptr);
EvaluationResult evaluated((*parsed)->evaluate(params));
if (!evaluated) {

View File

@@ -8,81 +8,78 @@ namespace style {
namespace expression {
type::Type typeOf(const Value& value) {
return value.match(
[&](bool) -> type::Type { return type::Boolean; },
[&](double) -> type::Type { return type::Number; },
[&](const std::string&) -> type::Type { return type::String; },
[&](const Color&) -> type::Type { return type::Color; },
[&](const Collator&) -> type::Type { return type::Collator; },
[&](const Formatted&) -> type::Type { return type::Formatted; },
[&](const NullValue&) -> type::Type { return type::Null; },
[&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; },
[&](const std::vector<Value>& arr) -> type::Type {
optional<type::Type> itemType;
for (const auto& item : arr) {
const type::Type t = typeOf(item);
if (!itemType) {
itemType = {t};
} else if (*itemType == t) {
continue;
} else {
itemType = {type::Value};
break;
}
}
return value.match([&](bool) -> type::Type { return type::Boolean; },
[&](double) -> type::Type { return type::Number; },
[&](const std::string&) -> type::Type { return type::String; },
[&](const Color&) -> type::Type { return type::Color; },
[&](const Collator&) -> type::Type { return type::Collator; },
[&](const Formatted&) -> type::Type { return type::Formatted; },
[&](const Image&) -> type::Type { return type::Image; },
[&](const NullValue&) -> type::Type { return type::Null; },
[&](const std::unordered_map<std::string, Value>&) -> type::Type { return type::Object; },
[&](const std::vector<Value>& arr) -> type::Type {
optional<type::Type> itemType;
for (const auto& item : arr) {
const type::Type t = typeOf(item);
if (!itemType) {
itemType = {t};
} else if (*itemType == t) {
continue;
} else {
itemType = {type::Value};
break;
}
}
return type::Array(itemType.value_or(type::Value), arr.size());
}
);
return type::Array(itemType.value_or(type::Value), arr.size());
});
}
std::string toString(const Value& value) {
return value.match(
[](const NullValue&) { return std::string(); },
[](const Color& c) { return c.stringify(); }, // avoid quoting
[](const Formatted& f) { return f.toString(); },
[](const std::string& s) { return s; }, // avoid quoting
[](const auto& v_) { return stringify(v_); }
);
return value.match([](const NullValue&) { return std::string(); },
[](const Color& c) { return c.stringify(); }, // avoid quoting
[](const Formatted& f) { return f.toString(); },
[](const Image& i) { return i.id(); },
[](const std::string& s) { return s; }, // avoid quoting
[](const auto& v_) { return stringify(v_); });
}
void writeJSON(rapidjson::Writer<rapidjson::StringBuffer>& writer, const Value& value) {
value.match(
[&] (const NullValue&) { writer.Null(); },
[&] (bool b) { writer.Bool(b); },
[&] (double f) {
// make sure integer values are stringified without trailing ".0".
f == std::floor(f) ? writer.Int(f) : writer.Double(f);
},
[&] (const std::string& s) { writer.String(s); },
[&] (const Color& c) { writer.String(c.stringify()); },
[&] (const Collator&) {
// Collators are excluded from constant folding and there's no Literal parser
// for them so there shouldn't be any way to serialize this value.
assert(false);
},
[&] (const Formatted& f) {
// `stringify` in turns calls ValueConverter::fromExpressionValue below
// Serialization strategy for Formatted objects is to return the constant
// expression that would generate them.
mbgl::style::conversion::stringify(writer, f);
},
[&] (const std::vector<Value>& arr) {
writer.StartArray();
for(const auto& item : arr) {
writeJSON(writer, item);
}
writer.EndArray();
},
[&] (const std::unordered_map<std::string, Value>& obj) {
writer.StartObject();
for(const auto& entry : obj) {
writer.Key(entry.first.c_str());
writeJSON(writer, entry.second);
}
writer.EndObject();
}
);
value.match([&](const NullValue&) { writer.Null(); },
[&](bool b) { writer.Bool(b); },
[&](double f) {
// make sure integer values are stringified without trailing ".0".
f == std::floor(f) ? writer.Int(f) : writer.Double(f);
},
[&](const std::string& s) { writer.String(s); },
[&](const Color& c) { writer.String(c.stringify()); },
[&](const Collator&) {
// Collators are excluded from constant folding and there's no Literal parser
// for them so there shouldn't be any way to serialize this value.
assert(false);
},
[&](const Formatted& f) {
// `stringify` in turns calls ValueConverter::fromExpressionValue below
// Serialization strategy for Formatted objects is to return the constant
// expression that would generate them.
mbgl::style::conversion::stringify(writer, f);
},
[&](const Image& i) { mbgl::style::conversion::stringify(writer, i); },
[&](const std::vector<Value>& arr) {
writer.StartArray();
for (const auto& item : arr) {
writeJSON(writer, item);
}
writer.EndArray();
},
[&](const std::unordered_map<std::string, Value>& obj) {
writer.StartObject();
for (const auto& entry : obj) {
writer.Key(entry.first.c_str());
writeJSON(writer, entry.second);
}
writer.EndObject();
});
}
std::string stringify(const Value& value) {
@@ -129,7 +126,7 @@ Value ValueConverter<mbgl::Value>::toExpressionValue(const mbgl::Value& value) {
mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) {
return value.match(
[&](const Color& color)->mbgl::Value {
[&](const Color& color) -> mbgl::Value {
std::array<double, 4> array = color.toArray();
return std::vector<mbgl::Value>{
std::string("rgba"),
@@ -139,13 +136,13 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
array[3],
};
},
[&](const Collator&)->mbgl::Value {
[&](const Collator&) -> mbgl::Value {
// fromExpressionValue can't be used for Collator values,
// because they have no meaningful representation as an mbgl::Value
assert(false);
return mbgl::Value();
},
[&](const Formatted& formatted)->mbgl::Value {
[&](const Formatted& formatted) -> mbgl::Value {
// Serialization strategy for Formatted objects is to return the constant
// expression that would generate them.
std::vector<mbgl::Value> serialized;
@@ -175,7 +172,8 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
}
return serialized;
},
[&](const std::vector<Value>& values)->mbgl::Value {
[&](const Image& i) -> mbgl::Value { return i.toValue(); },
[&](const std::vector<Value>& values) -> mbgl::Value {
std::vector<mbgl::Value> converted;
converted.reserve(values.size());
for (const Value& v : values) {
@@ -183,7 +181,7 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
}
return converted;
},
[&](const std::unordered_map<std::string, Value>& values)->mbgl::Value {
[&](const std::unordered_map<std::string, Value>& values) -> mbgl::Value {
std::unordered_map<std::string, mbgl::Value> converted;
converted.reserve(values.size());
for(const auto& entry : values) {
@@ -191,8 +189,7 @@ mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value)
}
return converted;
},
[&](const auto& a)->mbgl::Value { return a; }
);
[&](const auto& a) -> mbgl::Value { return a; });
}
Value ValueConverter<float>::toExpressionValue(const float value) {
@@ -302,6 +299,10 @@ template <> type::Type valueTypeToExpressionType<std::string>() { return type::S
template <> type::Type valueTypeToExpressionType<Color>() { return type::Color; }
template <> type::Type valueTypeToExpressionType<Collator>() { return type::Collator; }
template <> type::Type valueTypeToExpressionType<Formatted>() { return type::Formatted; }
template <>
type::Type valueTypeToExpressionType<Image>() {
return type::Image;
}
template <> type::Type valueTypeToExpressionType<std::unordered_map<std::string, Value>>() { return type::Object; }
template <> type::Type valueTypeToExpressionType<std::vector<Value>>() { return type::Array(type::Value); }

View File

@@ -64,7 +64,7 @@ void BackgroundLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringB
// Paint properties
PropertyValue<Color> BackgroundLayer::getDefaultBackgroundColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& BackgroundLayer::getBackgroundColor() const {
@@ -91,7 +91,7 @@ TransitionOptions BackgroundLayer::getBackgroundColorTransition() const {
}
PropertyValue<float> BackgroundLayer::getDefaultBackgroundOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& BackgroundLayer::getBackgroundOpacity() const {
@@ -117,15 +117,15 @@ TransitionOptions BackgroundLayer::getBackgroundOpacityTransition() const {
return impl().paint.template get<BackgroundOpacity>().options;
}
PropertyValue<std::string> BackgroundLayer::getDefaultBackgroundPattern() {
return { "" };
PropertyValue<expression::Image> BackgroundLayer::getDefaultBackgroundPattern() {
return {{}};
}
const PropertyValue<std::string>& BackgroundLayer::getBackgroundPattern() const {
const PropertyValue<expression::Image>& BackgroundLayer::getBackgroundPattern() const {
return impl().paint.template get<BackgroundPattern>().value;
}
void BackgroundLayer::setBackgroundPattern(const PropertyValue<std::string>& value) {
void BackgroundLayer::setBackgroundPattern(const PropertyValue<expression::Image>& value) {
if (value == getBackgroundPattern())
return;
auto impl_ = mutableImpl();
@@ -208,7 +208,8 @@ optional<Error> BackgroundLayer::setPaintProperty(const std::string& name, const
if (property == Property::BackgroundPattern) {
Error error;
optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, false, false);
optional<PropertyValue<expression::Image>> typedValue =
convert<PropertyValue<expression::Image>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -24,8 +24,8 @@ struct BackgroundOpacity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
struct BackgroundPattern : CrossFadedPaintProperty<std::string> {
static std::string defaultValue() { return ""; }
struct BackgroundPattern : CrossFadedPaintProperty<expression::Image> {
static expression::Image defaultValue() { return {}; }
};
class BackgroundPaintProperties : public Properties<

View File

@@ -64,7 +64,7 @@ void CircleLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe
// Paint properties
PropertyValue<float> CircleLayer::getDefaultCircleBlur() {
return { 0 };
return {0};
}
const PropertyValue<float>& CircleLayer::getCircleBlur() const {
@@ -91,7 +91,7 @@ TransitionOptions CircleLayer::getCircleBlurTransition() const {
}
PropertyValue<Color> CircleLayer::getDefaultCircleColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& CircleLayer::getCircleColor() const {
@@ -118,7 +118,7 @@ TransitionOptions CircleLayer::getCircleColorTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& CircleLayer::getCircleOpacity() const {
@@ -145,7 +145,7 @@ TransitionOptions CircleLayer::getCircleOpacityTransition() const {
}
PropertyValue<AlignmentType> CircleLayer::getDefaultCirclePitchAlignment() {
return { AlignmentType::Viewport };
return {AlignmentType::Viewport};
}
const PropertyValue<AlignmentType>& CircleLayer::getCirclePitchAlignment() const {
@@ -172,7 +172,7 @@ TransitionOptions CircleLayer::getCirclePitchAlignmentTransition() const {
}
PropertyValue<CirclePitchScaleType> CircleLayer::getDefaultCirclePitchScale() {
return { CirclePitchScaleType::Map };
return {CirclePitchScaleType::Map};
}
const PropertyValue<CirclePitchScaleType>& CircleLayer::getCirclePitchScale() const {
@@ -199,7 +199,7 @@ TransitionOptions CircleLayer::getCirclePitchScaleTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleRadius() {
return { 5 };
return {5};
}
const PropertyValue<float>& CircleLayer::getCircleRadius() const {
@@ -226,7 +226,7 @@ TransitionOptions CircleLayer::getCircleRadiusTransition() const {
}
PropertyValue<Color> CircleLayer::getDefaultCircleStrokeColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& CircleLayer::getCircleStrokeColor() const {
@@ -253,7 +253,7 @@ TransitionOptions CircleLayer::getCircleStrokeColorTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleStrokeOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& CircleLayer::getCircleStrokeOpacity() const {
@@ -280,7 +280,7 @@ TransitionOptions CircleLayer::getCircleStrokeOpacityTransition() const {
}
PropertyValue<float> CircleLayer::getDefaultCircleStrokeWidth() {
return { 0 };
return {0};
}
const PropertyValue<float>& CircleLayer::getCircleStrokeWidth() const {
@@ -307,7 +307,7 @@ TransitionOptions CircleLayer::getCircleStrokeWidthTransition() const {
}
PropertyValue<std::array<float, 2>> CircleLayer::getDefaultCircleTranslate() {
return { {{ 0, 0 }} };
return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& CircleLayer::getCircleTranslate() const {
@@ -334,7 +334,7 @@ TransitionOptions CircleLayer::getCircleTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> CircleLayer::getDefaultCircleTranslateAnchor() {
return { TranslateAnchorType::Map };
return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& CircleLayer::getCircleTranslateAnchor() const {
@@ -497,7 +497,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::CirclePitchScale) {
Error error;
optional<PropertyValue<CirclePitchScaleType>> typedValue = convert<PropertyValue<CirclePitchScaleType>>(value, error, false, false);
optional<PropertyValue<CirclePitchScaleType>> typedValue =
convert<PropertyValue<CirclePitchScaleType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -509,7 +510,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::CircleTranslate) {
Error error;
optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
optional<PropertyValue<std::array<float, 2>>> typedValue =
convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -521,7 +523,8 @@ optional<Error> CircleLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::CircleTranslateAnchor) {
Error error;
optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
optional<PropertyValue<TranslateAnchorType>> typedValue =
convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -53,7 +53,7 @@ struct CircleStrokeWidth : DataDrivenPaintProperty<float, attributes::stroke_wid
};
struct CircleTranslate : PaintProperty<std::array<float, 2>> {
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct CircleTranslateAnchor : PaintProperty<TranslateAnchorType> {

View File

@@ -64,7 +64,7 @@ void FillExtrusionLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::Stri
// Paint properties
PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionBase() {
return { 0 };
return {0};
}
const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionBase() const {
@@ -91,7 +91,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionBaseTransition() const {
}
PropertyValue<Color> FillExtrusionLayer::getDefaultFillExtrusionColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& FillExtrusionLayer::getFillExtrusionColor() const {
@@ -118,7 +118,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionColorTransition() const {
}
PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionHeight() {
return { 0 };
return {0};
}
const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionHeight() const {
@@ -145,7 +145,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionHeightTransition() const {
}
PropertyValue<float> FillExtrusionLayer::getDefaultFillExtrusionOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& FillExtrusionLayer::getFillExtrusionOpacity() const {
@@ -171,15 +171,15 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionOpacityTransition() const
return impl().paint.template get<FillExtrusionOpacity>().options;
}
PropertyValue<std::string> FillExtrusionLayer::getDefaultFillExtrusionPattern() {
return { "" };
PropertyValue<expression::Image> FillExtrusionLayer::getDefaultFillExtrusionPattern() {
return {{}};
}
const PropertyValue<std::string>& FillExtrusionLayer::getFillExtrusionPattern() const {
const PropertyValue<expression::Image>& FillExtrusionLayer::getFillExtrusionPattern() const {
return impl().paint.template get<FillExtrusionPattern>().value;
}
void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue<std::string>& value) {
void FillExtrusionLayer::setFillExtrusionPattern(const PropertyValue<expression::Image>& value) {
if (value == getFillExtrusionPattern())
return;
auto impl_ = mutableImpl();
@@ -199,7 +199,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionPatternTransition() const
}
PropertyValue<std::array<float, 2>> FillExtrusionLayer::getDefaultFillExtrusionTranslate() {
return { {{ 0, 0 }} };
return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& FillExtrusionLayer::getFillExtrusionTranslate() const {
@@ -226,7 +226,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateTransition() cons
}
PropertyValue<TranslateAnchorType> FillExtrusionLayer::getDefaultFillExtrusionTranslateAnchor() {
return { TranslateAnchorType::Map };
return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& FillExtrusionLayer::getFillExtrusionTranslateAnchor() const {
@@ -253,7 +253,7 @@ TransitionOptions FillExtrusionLayer::getFillExtrusionTranslateAnchorTransition(
}
PropertyValue<bool> FillExtrusionLayer::getDefaultFillExtrusionVerticalGradient() {
return { true };
return {true};
}
const PropertyValue<bool>& FillExtrusionLayer::getFillExtrusionVerticalGradient() const {
@@ -382,7 +382,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co
if (property == Property::FillExtrusionPattern) {
Error error;
optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false);
optional<PropertyValue<expression::Image>> typedValue =
convert<PropertyValue<expression::Image>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -394,7 +395,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co
if (property == Property::FillExtrusionTranslate) {
Error error;
optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
optional<PropertyValue<std::array<float, 2>>> typedValue =
convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -406,7 +408,8 @@ optional<Error> FillExtrusionLayer::setPaintProperty(const std::string& name, co
if (property == Property::FillExtrusionTranslateAnchor) {
Error error;
optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
optional<PropertyValue<TranslateAnchorType>> typedValue =
convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -32,12 +32,12 @@ struct FillExtrusionOpacity : PaintProperty<float> {
static float defaultValue() { return 1; }
};
struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static std::string defaultValue() { return ""; }
struct FillExtrusionPattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static expression::Image defaultValue() { return {}; }
};
struct FillExtrusionTranslate : PaintProperty<std::array<float, 2>> {
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct FillExtrusionTranslateAnchor : PaintProperty<TranslateAnchorType> {

View File

@@ -64,7 +64,7 @@ void FillLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>
// Paint properties
PropertyValue<bool> FillLayer::getDefaultFillAntialias() {
return { true };
return {true};
}
const PropertyValue<bool>& FillLayer::getFillAntialias() const {
@@ -91,7 +91,7 @@ TransitionOptions FillLayer::getFillAntialiasTransition() const {
}
PropertyValue<Color> FillLayer::getDefaultFillColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& FillLayer::getFillColor() const {
@@ -118,7 +118,7 @@ TransitionOptions FillLayer::getFillColorTransition() const {
}
PropertyValue<float> FillLayer::getDefaultFillOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& FillLayer::getFillOpacity() const {
@@ -145,7 +145,7 @@ TransitionOptions FillLayer::getFillOpacityTransition() const {
}
PropertyValue<Color> FillLayer::getDefaultFillOutlineColor() {
return { {} };
return {{}};
}
const PropertyValue<Color>& FillLayer::getFillOutlineColor() const {
@@ -171,15 +171,15 @@ TransitionOptions FillLayer::getFillOutlineColorTransition() const {
return impl().paint.template get<FillOutlineColor>().options;
}
PropertyValue<std::string> FillLayer::getDefaultFillPattern() {
return { "" };
PropertyValue<expression::Image> FillLayer::getDefaultFillPattern() {
return {{}};
}
const PropertyValue<std::string>& FillLayer::getFillPattern() const {
const PropertyValue<expression::Image>& FillLayer::getFillPattern() const {
return impl().paint.template get<FillPattern>().value;
}
void FillLayer::setFillPattern(const PropertyValue<std::string>& value) {
void FillLayer::setFillPattern(const PropertyValue<expression::Image>& value) {
if (value == getFillPattern())
return;
auto impl_ = mutableImpl();
@@ -199,7 +199,7 @@ TransitionOptions FillLayer::getFillPatternTransition() const {
}
PropertyValue<std::array<float, 2>> FillLayer::getDefaultFillTranslate() {
return { {{ 0, 0 }} };
return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& FillLayer::getFillTranslate() const {
@@ -226,7 +226,7 @@ TransitionOptions FillLayer::getFillTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> FillLayer::getDefaultFillTranslateAnchor() {
return { TranslateAnchorType::Map };
return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& FillLayer::getFillTranslateAnchor() const {
@@ -351,7 +351,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::FillPattern) {
Error error;
optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false);
optional<PropertyValue<expression::Image>> typedValue =
convert<PropertyValue<expression::Image>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -363,7 +364,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::FillTranslate) {
Error error;
optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
optional<PropertyValue<std::array<float, 2>>> typedValue =
convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -375,7 +377,8 @@ optional<Error> FillLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::FillTranslateAnchor) {
Error error;
optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
optional<PropertyValue<TranslateAnchorType>> typedValue =
convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -32,12 +32,12 @@ struct FillOutlineColor : DataDrivenPaintProperty<Color, attributes::outline_col
static Color defaultValue() { return {}; }
};
struct FillPattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static std::string defaultValue() { return ""; }
struct FillPattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static expression::Image defaultValue() { return {}; }
};
struct FillTranslate : PaintProperty<std::array<float, 2>> {
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct FillTranslateAnchor : PaintProperty<TranslateAnchorType> {

View File

@@ -93,7 +93,7 @@ TransitionOptions HeatmapLayer::getHeatmapColorTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapIntensity() {
return { 1 };
return {1};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapIntensity() const {
@@ -120,7 +120,7 @@ TransitionOptions HeatmapLayer::getHeatmapIntensityTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapOpacity() const {
@@ -147,7 +147,7 @@ TransitionOptions HeatmapLayer::getHeatmapOpacityTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapRadius() {
return { 30 };
return {30};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapRadius() const {
@@ -174,7 +174,7 @@ TransitionOptions HeatmapLayer::getHeatmapRadiusTransition() const {
}
PropertyValue<float> HeatmapLayer::getDefaultHeatmapWeight() {
return { 1 };
return {1};
}
const PropertyValue<float>& HeatmapLayer::getHeatmapWeight() const {

View File

@@ -64,7 +64,7 @@ void HillshadeLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBu
// Paint properties
PropertyValue<Color> HillshadeLayer::getDefaultHillshadeAccentColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& HillshadeLayer::getHillshadeAccentColor() const {
@@ -91,7 +91,7 @@ TransitionOptions HillshadeLayer::getHillshadeAccentColorTransition() const {
}
PropertyValue<float> HillshadeLayer::getDefaultHillshadeExaggeration() {
return { 0.5 };
return {0.5};
}
const PropertyValue<float>& HillshadeLayer::getHillshadeExaggeration() const {
@@ -118,7 +118,7 @@ TransitionOptions HillshadeLayer::getHillshadeExaggerationTransition() const {
}
PropertyValue<Color> HillshadeLayer::getDefaultHillshadeHighlightColor() {
return { Color::white() };
return {Color::white()};
}
const PropertyValue<Color>& HillshadeLayer::getHillshadeHighlightColor() const {
@@ -145,7 +145,7 @@ TransitionOptions HillshadeLayer::getHillshadeHighlightColorTransition() const {
}
PropertyValue<HillshadeIlluminationAnchorType> HillshadeLayer::getDefaultHillshadeIlluminationAnchor() {
return { HillshadeIlluminationAnchorType::Viewport };
return {HillshadeIlluminationAnchorType::Viewport};
}
const PropertyValue<HillshadeIlluminationAnchorType>& HillshadeLayer::getHillshadeIlluminationAnchor() const {
@@ -172,7 +172,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationAnchorTransition() con
}
PropertyValue<float> HillshadeLayer::getDefaultHillshadeIlluminationDirection() {
return { 335 };
return {335};
}
const PropertyValue<float>& HillshadeLayer::getHillshadeIlluminationDirection() const {
@@ -199,7 +199,7 @@ TransitionOptions HillshadeLayer::getHillshadeIlluminationDirectionTransition()
}
PropertyValue<Color> HillshadeLayer::getDefaultHillshadeShadowColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& HillshadeLayer::getHillshadeShadowColor() const {
@@ -320,7 +320,8 @@ optional<Error> HillshadeLayer::setPaintProperty(const std::string& name, const
if (property == Property::HillshadeIlluminationAnchor) {
Error error;
optional<PropertyValue<HillshadeIlluminationAnchorType>> typedValue = convert<PropertyValue<HillshadeIlluminationAnchorType>>(value, error, false, false);
optional<PropertyValue<HillshadeIlluminationAnchorType>> typedValue =
convert<PropertyValue<HillshadeIlluminationAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -77,6 +77,15 @@ layerCapabilities['heatmap'] = defaults.require('Source')
.set('TileKind', 'Geometry')
.finalize();
layerCapabilities['raster'] = defaults.require('Source').set('TileKind', 'Raster').finalize();
// Splits lines that are over 120 characters at the firts occurance of '='.
const split120Line = line => {
if (line.length > 120) {
return line.replace('=', '=\n ');
}
return line;
};
%>
// static
const LayerTypeInfo* <%- camelize(type) %>Layer::Impl::staticTypeInfo() noexcept {
@@ -155,7 +164,7 @@ void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(const <%- pro
std::string rawValue = R"JSON(<%- JSON.stringify(property.default) %>)JSON";
return *conversion::convertJSON<<%- propertyValueType(property)%>>(rawValue, error);
<% } else { -%>
return { <%- defaultValue(property) %> };
return {<%- defaultValue(property) %>};
<% } -%>
}
@@ -243,7 +252,7 @@ optional<Error> <%- camelize(type) %>Layer::setPaintProperty(const std::string&
%>
if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) {
Error error;
<%- key %>;
<%- split120Line(key) %>;
if (!typedValue) {
return error;
}
@@ -323,7 +332,7 @@ optional<Error> <%- camelize(type) %>Layer::setLayoutProperty(const std::string&
%>
if (<%- properties.map(p => `property == Property::${camelize(p.name)}`).join(' || ') %>) {
Error error;
<%- key %>;
<%- split120Line(key) %>;
if (!typedValue) {
return error;
}

View File

@@ -129,7 +129,7 @@ void LineLayer::setLineRoundLimit(const PropertyValue<float>& value) {
// Paint properties
PropertyValue<float> LineLayer::getDefaultLineBlur() {
return { 0 };
return {0};
}
const PropertyValue<float>& LineLayer::getLineBlur() const {
@@ -156,7 +156,7 @@ TransitionOptions LineLayer::getLineBlurTransition() const {
}
PropertyValue<Color> LineLayer::getDefaultLineColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& LineLayer::getLineColor() const {
@@ -183,7 +183,7 @@ TransitionOptions LineLayer::getLineColorTransition() const {
}
PropertyValue<std::vector<float>> LineLayer::getDefaultLineDasharray() {
return { { } };
return {{}};
}
const PropertyValue<std::vector<float>>& LineLayer::getLineDasharray() const {
@@ -210,7 +210,7 @@ TransitionOptions LineLayer::getLineDasharrayTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineGapWidth() {
return { 0 };
return {0};
}
const PropertyValue<float>& LineLayer::getLineGapWidth() const {
@@ -237,7 +237,7 @@ TransitionOptions LineLayer::getLineGapWidthTransition() const {
}
ColorRampPropertyValue LineLayer::getDefaultLineGradient() {
return { {} };
return {{}};
}
const ColorRampPropertyValue& LineLayer::getLineGradient() const {
@@ -264,7 +264,7 @@ TransitionOptions LineLayer::getLineGradientTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineOffset() {
return { 0 };
return {0};
}
const PropertyValue<float>& LineLayer::getLineOffset() const {
@@ -291,7 +291,7 @@ TransitionOptions LineLayer::getLineOffsetTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& LineLayer::getLineOpacity() const {
@@ -317,15 +317,15 @@ TransitionOptions LineLayer::getLineOpacityTransition() const {
return impl().paint.template get<LineOpacity>().options;
}
PropertyValue<std::string> LineLayer::getDefaultLinePattern() {
return { "" };
PropertyValue<expression::Image> LineLayer::getDefaultLinePattern() {
return {{}};
}
const PropertyValue<std::string>& LineLayer::getLinePattern() const {
const PropertyValue<expression::Image>& LineLayer::getLinePattern() const {
return impl().paint.template get<LinePattern>().value;
}
void LineLayer::setLinePattern(const PropertyValue<std::string>& value) {
void LineLayer::setLinePattern(const PropertyValue<expression::Image>& value) {
if (value == getLinePattern())
return;
auto impl_ = mutableImpl();
@@ -345,7 +345,7 @@ TransitionOptions LineLayer::getLinePatternTransition() const {
}
PropertyValue<std::array<float, 2>> LineLayer::getDefaultLineTranslate() {
return { {{ 0, 0 }} };
return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& LineLayer::getLineTranslate() const {
@@ -372,7 +372,7 @@ TransitionOptions LineLayer::getLineTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> LineLayer::getDefaultLineTranslateAnchor() {
return { TranslateAnchorType::Map };
return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& LineLayer::getLineTranslateAnchor() const {
@@ -399,7 +399,7 @@ TransitionOptions LineLayer::getLineTranslateAnchorTransition() const {
}
PropertyValue<float> LineLayer::getDefaultLineWidth() {
return { 1 };
return {1};
}
const PropertyValue<float>& LineLayer::getLineWidth() const {
@@ -552,7 +552,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LineDasharray) {
Error error;
optional<PropertyValue<std::vector<float>>> typedValue = convert<PropertyValue<std::vector<float>>>(value, error, false, false);
optional<PropertyValue<std::vector<float>>> typedValue =
convert<PropertyValue<std::vector<float>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -576,7 +577,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LinePattern) {
Error error;
optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, false);
optional<PropertyValue<expression::Image>> typedValue =
convert<PropertyValue<expression::Image>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -588,7 +590,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LineTranslate) {
Error error;
optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
optional<PropertyValue<std::array<float, 2>>> typedValue =
convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -600,7 +603,8 @@ optional<Error> LineLayer::setPaintProperty(const std::string& name, const Conve
if (property == Property::LineTranslateAnchor) {
Error error;
optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
optional<PropertyValue<TranslateAnchorType>> typedValue =
convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -45,7 +45,7 @@ struct LineColor : DataDrivenPaintProperty<Color, attributes::color, uniforms::c
};
struct LineDasharray : CrossFadedPaintProperty<std::vector<float>> {
static std::vector<float> defaultValue() { return { }; }
static std::vector<float> defaultValue() { return {}; }
};
struct LineFloorWidth : DataDrivenPaintProperty<float, attributes::floorwidth, uniforms::floorwidth> {
@@ -68,12 +68,12 @@ struct LineOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform
static float defaultValue() { return 1; }
};
struct LinePattern : CrossFadedDataDrivenPaintProperty<std::string, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static std::string defaultValue() { return ""; }
struct LinePattern : CrossFadedDataDrivenPaintProperty<expression::Image, attributes::pattern_to, uniforms::pattern_to, attributes::pattern_from, uniforms::pattern_from> {
static expression::Image defaultValue() { return {}; }
};
struct LineTranslate : PaintProperty<std::array<float, 2>> {
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct LineTranslateAnchor : PaintProperty<TranslateAnchorType> {

View File

@@ -64,7 +64,7 @@ void RasterLayer::Impl::stringifyLayout(rapidjson::Writer<rapidjson::StringBuffe
// Paint properties
PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMax() {
return { 1 };
return {1};
}
const PropertyValue<float>& RasterLayer::getRasterBrightnessMax() const {
@@ -91,7 +91,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMaxTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterBrightnessMin() {
return { 0 };
return {0};
}
const PropertyValue<float>& RasterLayer::getRasterBrightnessMin() const {
@@ -118,7 +118,7 @@ TransitionOptions RasterLayer::getRasterBrightnessMinTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterContrast() {
return { 0 };
return {0};
}
const PropertyValue<float>& RasterLayer::getRasterContrast() const {
@@ -145,7 +145,7 @@ TransitionOptions RasterLayer::getRasterContrastTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterFadeDuration() {
return { 300 };
return {300};
}
const PropertyValue<float>& RasterLayer::getRasterFadeDuration() const {
@@ -172,7 +172,7 @@ TransitionOptions RasterLayer::getRasterFadeDurationTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterHueRotate() {
return { 0 };
return {0};
}
const PropertyValue<float>& RasterLayer::getRasterHueRotate() const {
@@ -199,7 +199,7 @@ TransitionOptions RasterLayer::getRasterHueRotateTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& RasterLayer::getRasterOpacity() const {
@@ -226,7 +226,7 @@ TransitionOptions RasterLayer::getRasterOpacityTransition() const {
}
PropertyValue<RasterResamplingType> RasterLayer::getDefaultRasterResampling() {
return { RasterResamplingType::Linear };
return {RasterResamplingType::Linear};
}
const PropertyValue<RasterResamplingType>& RasterLayer::getRasterResampling() const {
@@ -253,7 +253,7 @@ TransitionOptions RasterLayer::getRasterResamplingTransition() const {
}
PropertyValue<float> RasterLayer::getDefaultRasterSaturation() {
return { 0 };
return {0};
}
const PropertyValue<float>& RasterLayer::getRasterSaturation() const {
@@ -383,7 +383,8 @@ optional<Error> RasterLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::RasterResampling) {
Error error;
optional<PropertyValue<RasterResamplingType>> typedValue = convert<PropertyValue<RasterResamplingType>>(value, error, false, false);
optional<PropertyValue<RasterResamplingType>> typedValue =
convert<PropertyValue<RasterResamplingType>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -109,15 +109,15 @@ void SymbolLayer::setIconIgnorePlacement(const PropertyValue<bool>& value) {
baseImpl = std::move(impl_);
observer->onLayerChanged(*this);
}
PropertyValue<std::string> SymbolLayer::getDefaultIconImage() {
PropertyValue<expression::Image> SymbolLayer::getDefaultIconImage() {
return IconImage::defaultValue();
}
const PropertyValue<std::string>& SymbolLayer::getIconImage() const {
const PropertyValue<expression::Image>& SymbolLayer::getIconImage() const {
return impl().layout.get<IconImage>();
}
void SymbolLayer::setIconImage(const PropertyValue<std::string>& value) {
void SymbolLayer::setIconImage(const PropertyValue<expression::Image>& value) {
if (value == getIconImage())
return;
auto impl_ = mutableImpl();
@@ -721,7 +721,7 @@ void SymbolLayer::setTextWritingMode(const PropertyValue<std::vector<TextWriting
// Paint properties
PropertyValue<Color> SymbolLayer::getDefaultIconColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& SymbolLayer::getIconColor() const {
@@ -748,7 +748,7 @@ TransitionOptions SymbolLayer::getIconColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultIconHaloBlur() {
return { 0 };
return {0};
}
const PropertyValue<float>& SymbolLayer::getIconHaloBlur() const {
@@ -775,7 +775,7 @@ TransitionOptions SymbolLayer::getIconHaloBlurTransition() const {
}
PropertyValue<Color> SymbolLayer::getDefaultIconHaloColor() {
return { {} };
return {{}};
}
const PropertyValue<Color>& SymbolLayer::getIconHaloColor() const {
@@ -802,7 +802,7 @@ TransitionOptions SymbolLayer::getIconHaloColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultIconHaloWidth() {
return { 0 };
return {0};
}
const PropertyValue<float>& SymbolLayer::getIconHaloWidth() const {
@@ -829,7 +829,7 @@ TransitionOptions SymbolLayer::getIconHaloWidthTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultIconOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& SymbolLayer::getIconOpacity() const {
@@ -856,7 +856,7 @@ TransitionOptions SymbolLayer::getIconOpacityTransition() const {
}
PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultIconTranslate() {
return { {{ 0, 0 }} };
return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& SymbolLayer::getIconTranslate() const {
@@ -883,7 +883,7 @@ TransitionOptions SymbolLayer::getIconTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultIconTranslateAnchor() {
return { TranslateAnchorType::Map };
return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& SymbolLayer::getIconTranslateAnchor() const {
@@ -910,7 +910,7 @@ TransitionOptions SymbolLayer::getIconTranslateAnchorTransition() const {
}
PropertyValue<Color> SymbolLayer::getDefaultTextColor() {
return { Color::black() };
return {Color::black()};
}
const PropertyValue<Color>& SymbolLayer::getTextColor() const {
@@ -937,7 +937,7 @@ TransitionOptions SymbolLayer::getTextColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultTextHaloBlur() {
return { 0 };
return {0};
}
const PropertyValue<float>& SymbolLayer::getTextHaloBlur() const {
@@ -964,7 +964,7 @@ TransitionOptions SymbolLayer::getTextHaloBlurTransition() const {
}
PropertyValue<Color> SymbolLayer::getDefaultTextHaloColor() {
return { {} };
return {{}};
}
const PropertyValue<Color>& SymbolLayer::getTextHaloColor() const {
@@ -991,7 +991,7 @@ TransitionOptions SymbolLayer::getTextHaloColorTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultTextHaloWidth() {
return { 0 };
return {0};
}
const PropertyValue<float>& SymbolLayer::getTextHaloWidth() const {
@@ -1018,7 +1018,7 @@ TransitionOptions SymbolLayer::getTextHaloWidthTransition() const {
}
PropertyValue<float> SymbolLayer::getDefaultTextOpacity() {
return { 1 };
return {1};
}
const PropertyValue<float>& SymbolLayer::getTextOpacity() const {
@@ -1045,7 +1045,7 @@ TransitionOptions SymbolLayer::getTextOpacityTransition() const {
}
PropertyValue<std::array<float, 2>> SymbolLayer::getDefaultTextTranslate() {
return { {{ 0, 0 }} };
return {{{0, 0}}};
}
const PropertyValue<std::array<float, 2>>& SymbolLayer::getTextTranslate() const {
@@ -1072,7 +1072,7 @@ TransitionOptions SymbolLayer::getTextTranslateTransition() const {
}
PropertyValue<TranslateAnchorType> SymbolLayer::getDefaultTextTranslateAnchor() {
return { TranslateAnchorType::Map };
return {TranslateAnchorType::Map};
}
const PropertyValue<TranslateAnchorType>& SymbolLayer::getTextTranslateAnchor() const {
@@ -1332,7 +1332,8 @@ optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::IconTranslate || property == Property::TextTranslate) {
Error error;
optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
optional<PropertyValue<std::array<float, 2>>> typedValue =
convert<PropertyValue<std::array<float, 2>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1351,7 +1352,8 @@ optional<Error> SymbolLayer::setPaintProperty(const std::string& name, const Con
if (property == Property::IconTranslateAnchor || property == Property::TextTranslateAnchor) {
Error error;
optional<PropertyValue<TranslateAnchorType>> typedValue = convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
optional<PropertyValue<TranslateAnchorType>> typedValue =
convert<PropertyValue<TranslateAnchorType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1665,7 +1667,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconAnchor || property == Property::TextAnchor) {
Error error;
optional<PropertyValue<SymbolAnchorType>> typedValue = convert<PropertyValue<SymbolAnchorType>>(value, error, true, false);
optional<PropertyValue<SymbolAnchorType>> typedValue =
convert<PropertyValue<SymbolAnchorType>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1684,7 +1687,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconImage) {
Error error;
optional<PropertyValue<std::string>> typedValue = convert<PropertyValue<std::string>>(value, error, true, true);
optional<PropertyValue<expression::Image>> typedValue =
convert<PropertyValue<expression::Image>>(value, error, true, true);
if (!typedValue) {
return error;
}
@@ -1696,7 +1700,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconOffset || property == Property::TextOffset) {
Error error;
optional<PropertyValue<std::array<float, 2>>> typedValue = convert<PropertyValue<std::array<float, 2>>>(value, error, true, false);
optional<PropertyValue<std::array<float, 2>>> typedValue =
convert<PropertyValue<std::array<float, 2>>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1827,7 +1832,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconTextFit) {
Error error;
optional<PropertyValue<IconTextFitType>> typedValue = convert<PropertyValue<IconTextFitType>>(value, error, false, false);
optional<PropertyValue<IconTextFitType>> typedValue =
convert<PropertyValue<IconTextFitType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1839,7 +1845,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::IconTextFitPadding) {
Error error;
optional<PropertyValue<std::array<float, 4>>> typedValue = convert<PropertyValue<std::array<float, 4>>>(value, error, false, false);
optional<PropertyValue<std::array<float, 4>>> typedValue =
convert<PropertyValue<std::array<float, 4>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1851,7 +1858,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::SymbolPlacement) {
Error error;
optional<PropertyValue<SymbolPlacementType>> typedValue = convert<PropertyValue<SymbolPlacementType>>(value, error, false, false);
optional<PropertyValue<SymbolPlacementType>> typedValue =
convert<PropertyValue<SymbolPlacementType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1863,7 +1871,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::SymbolZOrder) {
Error error;
optional<PropertyValue<SymbolZOrderType>> typedValue = convert<PropertyValue<SymbolZOrderType>>(value, error, false, false);
optional<PropertyValue<SymbolZOrderType>> typedValue =
convert<PropertyValue<SymbolZOrderType>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1875,7 +1884,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextField) {
Error error;
optional<PropertyValue<expression::Formatted>> typedValue = convert<PropertyValue<expression::Formatted>>(value, error, true, true);
optional<PropertyValue<expression::Formatted>> typedValue =
convert<PropertyValue<expression::Formatted>>(value, error, true, true);
if (!typedValue) {
return error;
}
@@ -1887,7 +1897,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextFont) {
Error error;
optional<PropertyValue<std::vector<std::string>>> typedValue = convert<PropertyValue<std::vector<std::string>>>(value, error, true, false);
optional<PropertyValue<std::vector<std::string>>> typedValue =
convert<PropertyValue<std::vector<std::string>>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1911,7 +1922,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextTransform) {
Error error;
optional<PropertyValue<TextTransformType>> typedValue = convert<PropertyValue<TextTransformType>>(value, error, true, false);
optional<PropertyValue<TextTransformType>> typedValue =
convert<PropertyValue<TextTransformType>>(value, error, true, false);
if (!typedValue) {
return error;
}
@@ -1923,7 +1935,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextVariableAnchor) {
Error error;
optional<PropertyValue<std::vector<TextVariableAnchorType>>> typedValue = convert<PropertyValue<std::vector<TextVariableAnchorType>>>(value, error, false, false);
optional<PropertyValue<std::vector<TextVariableAnchorType>>> typedValue =
convert<PropertyValue<std::vector<TextVariableAnchorType>>>(value, error, false, false);
if (!typedValue) {
return error;
}
@@ -1935,7 +1948,8 @@ optional<Error> SymbolLayer::setLayoutProperty(const std::string& name, const Co
if (property == Property::TextWritingMode) {
Error error;
optional<PropertyValue<std::vector<TextWritingModeType>>> typedValue = convert<PropertyValue<std::vector<TextWritingModeType>>>(value, error, false, false);
optional<PropertyValue<std::vector<TextWritingModeType>>> typedValue =
convert<PropertyValue<std::vector<TextWritingModeType>>>(value, error, false, false);
if (!typedValue) {
return error;
}

View File

@@ -31,9 +31,9 @@ struct IconIgnorePlacement : LayoutProperty<bool> {
static bool defaultValue() { return false; }
};
struct IconImage : DataDrivenLayoutProperty<std::string> {
struct IconImage : DataDrivenLayoutProperty<expression::Image> {
static constexpr const char *name() { return "icon-image"; }
static std::string defaultValue() { return ""; }
static expression::Image defaultValue() { return {}; }
};
struct IconKeepUpright : LayoutProperty<bool> {
@@ -43,7 +43,7 @@ struct IconKeepUpright : LayoutProperty<bool> {
struct IconOffset : DataDrivenLayoutProperty<std::array<float, 2>> {
static constexpr const char *name() { return "icon-offset"; }
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct IconOptional : LayoutProperty<bool> {
@@ -83,7 +83,7 @@ struct IconTextFit : LayoutProperty<IconTextFitType> {
struct IconTextFitPadding : LayoutProperty<std::array<float, 4>> {
static constexpr const char *name() { return "icon-text-fit-padding"; }
static std::array<float, 4> defaultValue() { return {{ 0, 0, 0, 0 }}; }
static std::array<float, 4> defaultValue() { return {{0, 0, 0, 0}}; }
};
struct SymbolAvoidEdges : LayoutProperty<bool> {
@@ -123,12 +123,12 @@ struct TextAnchor : DataDrivenLayoutProperty<SymbolAnchorType> {
struct TextField : DataDrivenLayoutProperty<expression::Formatted> {
static constexpr const char *name() { return "text-field"; }
static expression::Formatted defaultValue() { return ""; }
static expression::Formatted defaultValue() { return {}; }
};
struct TextFont : DataDrivenLayoutProperty<std::vector<std::string>> {
static constexpr const char *name() { return "text-font"; }
static std::vector<std::string> defaultValue() { return { "Open Sans Regular", "Arial Unicode MS Regular" }; }
static std::vector<std::string> defaultValue() { return {{"Open Sans Regular"}, {"Arial Unicode MS Regular"}}; }
};
struct TextIgnorePlacement : LayoutProperty<bool> {
@@ -168,7 +168,7 @@ struct TextMaxWidth : DataDrivenLayoutProperty<float> {
struct TextOffset : DataDrivenLayoutProperty<std::array<float, 2>> {
static constexpr const char *name() { return "text-offset"; }
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct TextOptional : LayoutProperty<bool> {
@@ -213,12 +213,12 @@ struct TextTransform : DataDrivenLayoutProperty<TextTransformType> {
struct TextVariableAnchor : LayoutProperty<std::vector<TextVariableAnchorType>> {
static constexpr const char *name() { return "text-variable-anchor"; }
static std::vector<TextVariableAnchorType> defaultValue() { return { }; }
static std::vector<TextVariableAnchorType> defaultValue() { return {}; }
};
struct TextWritingMode : LayoutProperty<std::vector<TextWritingModeType>> {
static constexpr const char *name() { return "text-writing-mode"; }
static std::vector<TextWritingModeType> defaultValue() { return { }; }
static std::vector<TextWritingModeType> defaultValue() { return {}; }
};
struct IconColor : DataDrivenPaintProperty<Color, attributes::fill_color, uniforms::fill_color> {
@@ -242,7 +242,7 @@ struct IconOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform
};
struct IconTranslate : PaintProperty<std::array<float, 2>> {
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct IconTranslateAnchor : PaintProperty<TranslateAnchorType> {
@@ -273,7 +273,7 @@ struct TextOpacity : DataDrivenPaintProperty<float, attributes::opacity, uniform
};
struct TextTranslate : PaintProperty<std::array<float, 2>> {
static std::array<float, 2> defaultValue() { return {{ 0, 0 }}; }
static std::array<float, 2> defaultValue() { return {{0, 0}}; }
};
struct TextTranslateAnchor : PaintProperty<TranslateAnchorType> {

View File

@@ -169,8 +169,10 @@ public:
}
template <class T>
static T evaluate(float z, const GeometryTileFeature& feature,
const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) {
static T evaluate(float z,
const GeometryTileFeature& feature,
const PossiblyEvaluatedPropertyValue<T>& v,
const T& defaultValue) {
return v.match(
[&] (const T& t) {
return t;
@@ -180,6 +182,17 @@ public:
});
}
template <class T>
static T evaluate(float z,
const GeometryTileFeature& feature,
const PossiblyEvaluatedPropertyValue<T>& v,
const T& defaultValue,
const std::set<std::string>& availableImages) {
return v.match(
[&](const T& t) { return t; },
[&](const PropertyExpression<T>& t) { return t.evaluate(z, feature, availableImages, defaultValue); });
}
template <class T>
static T evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state,
const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) {
@@ -197,6 +210,11 @@ public:
return evaluate(z, feature, state, this->template get<P>(), P::defaultValue());
}
template <class P>
auto evaluate(float z, const GeometryTileFeature& feature, const std::set<std::string>& availableImages) const {
return evaluate(z, feature, this->template get<P>(), P::defaultValue(), availableImages);
}
Evaluated evaluate(float z, const GeometryTileFeature& feature) const {
return Evaluated {
evaluate<Ps>(z, feature)...

View File

@@ -8,6 +8,7 @@ PropertyExpressionBase::PropertyExpressionBase(std::unique_ptr<expression::Expre
zoomCurve(expression::findZoomCurveChecked(expression.get())) {
isZoomConstant_ = expression::isZoomConstant(*expression);
isFeatureConstant_ = expression::isFeatureConstant(*expression);
isRuntimeConstant_ = expression::isRuntimeConstant(*expression);
}
bool PropertyExpressionBase::isZoomConstant() const noexcept {
@@ -18,19 +19,8 @@ bool PropertyExpressionBase::isFeatureConstant() const noexcept {
return isFeatureConstant_;
}
bool PropertyExpressionBase::canEvaluateWith(const expression::EvaluationContext& context) const noexcept {
if (context.zoom) {
if (context.feature != nullptr) {
return !isFeatureConstant();
}
return !isZoomConstant() && isFeatureConstant();
}
if (context.feature != nullptr) {
return isZoomConstant() && !isFeatureConstant();
}
return true;
bool PropertyExpressionBase::isRuntimeConstant() const noexcept {
return isRuntimeConstant_;
}
float PropertyExpressionBase::interpolationFactor(const Range<float>& inputLevels, const float inputValue) const noexcept {

View File

@@ -182,7 +182,8 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_, bool r
pending = true;
++correlationID;
worker.self().invoke(&GeometryTileWorker::setData, std::move(data_), resetLayers, correlationID);
worker.self().invoke(
&GeometryTileWorker::setData, std::move(data_), imageManager.getAvailableImages(), resetLayers, correlationID);
}
std::unique_ptr<TileRenderData> GeometryTile::createRenderData() {
@@ -212,7 +213,8 @@ void GeometryTile::setLayers(const std::vector<Immutable<LayerProperties>>& laye
}
++correlationID;
worker.self().invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID);
worker.self().invoke(
&GeometryTileWorker::setLayers, std::move(impls), imageManager.getAvailableImages(), correlationID);
}
void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) {

View File

@@ -116,10 +116,14 @@ GeometryTileWorker::~GeometryTileWorker() = default;
completed parse.
*/
void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_, bool resetLayers_, uint64_t correlationID_) {
void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
std::set<std::string> availableImages_,
bool resetLayers_,
uint64_t correlationID_) {
try {
data = std::move(data_);
correlationID = correlationID_;
availableImages = std::move(availableImages_);
if (resetLayers_) layers = nullopt;
switch (state) {
@@ -139,10 +143,13 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
}
}
void GeometryTileWorker::setLayers(std::vector<Immutable<LayerProperties>> layers_, uint64_t correlationID_) {
void GeometryTileWorker::setLayers(std::vector<Immutable<LayerProperties>> layers_,
std::set<std::string> availableImages_,
uint64_t correlationID_) {
try {
layers = std::move(layers_);
correlationID = correlationID_;
availableImages = std::move(availableImages_);
switch (state) {
case Idle:
@@ -365,7 +372,8 @@ void GeometryTileWorker::parse() {
// and either immediately create a bucket if no images/glyphs are used, or the Layout is stored until
// the images/glyphs are available to add the features to the buckets.
if (leaderImpl.getTypeInfo()->layout == LayerTypeInfo::Layout::Required) {
std::unique_ptr<Layout> layout = LayerManager::get()->createLayout({parameters, glyphDependencies, imageDependencies}, std::move(geometryLayer), group);
std::unique_ptr<Layout> layout = LayerManager::get()->createLayout(
{parameters, glyphDependencies, imageDependencies, availableImages}, std::move(geometryLayer), group);
if (layout->hasDependencies()) {
layouts.push_back(std::move(layout));
} else {

View File

@@ -38,8 +38,13 @@ public:
const bool showCollisionBoxes_);
~GeometryTileWorker();
void setLayers(std::vector<Immutable<style::LayerProperties>>, uint64_t correlationID);
void setData(std::unique_ptr<const GeometryTileData>, bool resetLayers, uint64_t correlationID);
void setLayers(std::vector<Immutable<style::LayerProperties>>,
std::set<std::string> availableImages,
uint64_t correlationID);
void setData(std::unique_ptr<const GeometryTileData>,
std::set<std::string> availableImages,
bool resetLayers,
uint64_t correlationID);
void setShowCollisionBoxes(bool showCollisionBoxes_, uint64_t correlationID_);
void onGlyphsAvailable(GlyphMap glyphs);
@@ -96,7 +101,8 @@ private:
ImageMap imageMap;
ImageMap patternMap;
ImageVersionMap versionMap;
std::set<std::string> availableImages;
bool showCollisionBoxes;
bool firstLoad = true;
};

View File

@@ -55,7 +55,7 @@ std::vector<Feature> getTopClusterFeature(QueryTest& test) {
source->loadDescription(*test.fileSource);
auto clusterLayer = std::make_unique<SymbolLayer>("cluster_layer"s, "cluster_source"s);
clusterLayer->setIconImage("test-icon"s);
clusterLayer->setIconImage({"test-icon"s});
clusterLayer->setIconSize(12.0f);
test.map.jumpTo(CameraOptions().withCenter(coordinate).withZoom(0.0));

View File

@@ -0,0 +1,4 @@
[
"image",
"maki-11"
]

View File

@@ -0,0 +1,4 @@
[
"image",
"bicycle-15"
]

View File

@@ -35,7 +35,8 @@ TEST(Expression, IsExpression) {
// TODO: "interpolate-hcl": https://github.com/mapbox/mapbox-gl-native/issues/8720
// TODO: "interpolate-lab": https://github.com/mapbox/mapbox-gl-native/issues/8720
if (name == "interpolate-hcl" || name == "interpolate-lab") {
// TODO: "in": https://github.com/mapbox/mapbox-gl-native/issues/15893
if (name == "interpolate-hcl" || name == "interpolate-lab" || name == "in") {
if (expression::isExpression(conversion::Convertible(expression))) {
ASSERT_TRUE(false) << "Expression name" << name << "is implemented - please update Expression.IsExpression test.";
}

View File

@@ -14,21 +14,17 @@ using namespace mbgl::style::expression::dsl;
using namespace std::string_literals;
static StubGeometryTileFeature oneInteger {
PropertyMap {{ "property", uint64_t(1) }}
};
static const StubGeometryTileFeature oneInteger{PropertyMap{{"property", uint64_t(1)}}};
static StubGeometryTileFeature oneDouble {
PropertyMap {{ "property", 1.0 }}
};
static const StubGeometryTileFeature oneDouble{PropertyMap{{"property", 1.0}}};
static StubGeometryTileFeature oneString {
PropertyMap {{ "property", "1"s }}
};
static const StubGeometryTileFeature oneString{PropertyMap{{"property", "1"s}}};
static StubGeometryTileFeature oneColor {
PropertyMap {{ "color", "red"s }}
};
static const StubGeometryTileFeature oneColor{PropertyMap{{"color", "red"s}}};
static const StubGeometryTileFeature oneImage{PropertyMap{{"image_name", "maki-11"s}}};
static const StubGeometryTileFeature emptyTileFeature{PropertyMap{}};
float evaluate(PropertyValue<float> value, float zoom) {
return value.evaluate(PropertyEvaluator<float>(PropertyEvaluationParameters(zoom), 0));
@@ -171,3 +167,54 @@ TEST(PropertyExpression, FormatSectionOverride) {
EXPECT_TRUE(*override1 != *override4);
}
}
TEST(PropertyExpression, ImageExpression) {
const std::set<std::string> emptySet;
const std::set<std::string> availableImages = {"maki-11", "airport-11", "bicycle-15"};
// evaluation test without available images
{
PropertyExpression<expression::Image> propExpr(image(literal("airport-11")));
auto evaluatedImage = propExpr.evaluate(emptyTileFeature, emptySet, expression::Image());
EXPECT_FALSE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), "airport-11"s);
PropertyExpression<expression::Image> ddPropExpr(image(get(literal("image_name"s))));
evaluatedImage = ddPropExpr.evaluate(oneImage, emptySet, expression::Image());
EXPECT_FALSE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), "maki-11"s);
evaluatedImage = ddPropExpr.evaluate(emptyTileFeature, emptySet, expression::Image());
EXPECT_FALSE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), ""s);
}
// evaluation test with available images
{
PropertyExpression<expression::Image> propExpr(image(literal("airport-11")));
auto evaluatedImage = propExpr.evaluate(emptyTileFeature, availableImages, expression::Image());
EXPECT_TRUE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), "airport-11"s);
PropertyExpression<expression::Image> ddPropExpr(image(get(literal("image_name"s))));
evaluatedImage = ddPropExpr.evaluate(oneImage, availableImages, expression::Image());
EXPECT_TRUE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), "maki-11"s);
evaluatedImage = ddPropExpr.evaluate(emptyTileFeature, availableImages, expression::Image());
EXPECT_FALSE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), ""s);
}
// evaluation with zoom
{
auto expr = step(zoom(), image(literal("airport-11")), 18.0, image(literal("bicycle-15")));
PropertyExpression<expression::Image> propExpr(std::move(expr));
auto evaluatedImage = propExpr.evaluate(0.0, emptyTileFeature, availableImages, expression::Image());
EXPECT_TRUE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), "airport-11"s);
evaluatedImage = propExpr.evaluate(18.0, emptyTileFeature, availableImages, expression::Image());
EXPECT_TRUE(evaluatedImage.isAvailable());
EXPECT_EQ(evaluatedImage.id(), "bicycle-15"s);
}
}

View File

@@ -1,7 +1,7 @@
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/format_expression.hpp>
#include <mbgl/style/style_impl.hpp>
#include <mbgl/style/expression/image.hpp>
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
@@ -16,12 +16,13 @@
#include <mbgl/style/layers/raster_layer_impl.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_layer_observer.hpp>
#include <mbgl/style/style_impl.hpp>
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/stub_layer_observer.hpp>
#include <mbgl/test/util.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/run_loop.hpp>
#include <memory>
@@ -37,7 +38,7 @@ const auto color = Color { 1, 0, 0, 1 };
const auto opacity = 1.0f;
const auto radius = 1.0f;
const auto blur = 1.0f;
const auto pattern = std::string { "foo" };
const auto pattern = PropertyValue<expression::Image>{"foo"};
const auto antialias = false;
const auto translate = std::array<float, 2> {{ 0, 0 }};
const auto translateAnchor = TranslateAnchorType::Map;

View File

@@ -19,11 +19,15 @@ LineString<int16_t> emptyLine;
class SymbolFeatureStub : public SymbolFeature {
public:
SymbolFeatureStub(FeatureIdentifier id_, FeatureType type_, GeometryCollection geometry_,
PropertyMap properties_, optional<std::u16string> text_,
optional<std::string> icon_, std::size_t index_) :
SymbolFeature(std::make_unique<StubGeometryTileFeature>(std::move(id_), type_, std::move(geometry_), std::move(properties_)))
{
SymbolFeatureStub(FeatureIdentifier id_,
FeatureType type_,
GeometryCollection geometry_,
PropertyMap properties_,
optional<std::u16string> text_,
optional<style::expression::Image> icon_,
std::size_t index_)
: SymbolFeature(std::make_unique<StubGeometryTileFeature>(
std::move(id_), type_, std::move(geometry_), std::move(properties_))) {
if (text_) {
formattedText = TaggedString(*text_, SectionOptions(1.0, {}));
}