|
|
|
|
@@ -1,17 +1,11 @@
|
|
|
|
|
#include <mbgl/style/property_parsing.hpp>
|
|
|
|
|
#include <mbgl/style/property_transition.hpp>
|
|
|
|
|
#include <mbgl/style/function.hpp>
|
|
|
|
|
|
|
|
|
|
#include <mbgl/platform/log.hpp>
|
|
|
|
|
|
|
|
|
|
#include <csscolorparser/csscolorparser.hpp>
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
namespace mbgl {
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<bool> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<bool> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsBool()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a boolean", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -21,7 +15,7 @@ optional<bool> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<float> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<float> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsNumber()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -31,7 +25,7 @@ optional<float> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<std::string> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<std::string> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -41,7 +35,7 @@ optional<std::string> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<Color> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<Color> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -64,7 +58,7 @@ MBGL_DEFINE_ENUM_CLASS(TranslateAnchorTypeClass, TranslateAnchorType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<TranslateAnchorType> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<TranslateAnchorType> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -79,7 +73,7 @@ MBGL_DEFINE_ENUM_CLASS(RotateAnchorTypeClass, RotateAnchorType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<RotateAnchorType> parseProperty<RotateAnchorType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<RotateAnchorType> parseConstant<RotateAnchorType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -95,7 +89,7 @@ MBGL_DEFINE_ENUM_CLASS(LineCapTypeClass, LineCapType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<LineCapType> parseProperty<LineCapType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<LineCapType> parseConstant<LineCapType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -113,7 +107,7 @@ MBGL_DEFINE_ENUM_CLASS(LineJoinTypeClass, LineJoinType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<LineJoinType> parseProperty<LineJoinType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<LineJoinType> parseConstant<LineJoinType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -128,7 +122,7 @@ MBGL_DEFINE_ENUM_CLASS(SymbolPlacementTypeClass, SymbolPlacementType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<SymbolPlacementType> parseProperty<SymbolPlacementType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<SymbolPlacementType> parseConstant<SymbolPlacementType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -150,7 +144,7 @@ MBGL_DEFINE_ENUM_CLASS(TextAnchorTypeClass, TextAnchorType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<TextAnchorType> parseProperty<TextAnchorType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<TextAnchorType> parseConstant<TextAnchorType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -166,7 +160,7 @@ MBGL_DEFINE_ENUM_CLASS(TextJustifyTypeClass, TextJustifyType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<TextJustifyType> parseProperty<TextJustifyType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<TextJustifyType> parseConstant<TextJustifyType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -182,7 +176,7 @@ MBGL_DEFINE_ENUM_CLASS(TextTransformTypeClass, TextTransformType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<TextTransformType> parseProperty<TextTransformType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<TextTransformType> parseConstant<TextTransformType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -197,7 +191,7 @@ MBGL_DEFINE_ENUM_CLASS(RotationAlignmentTypeClass, RotationAlignmentType, {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<RotationAlignmentType> parseProperty<RotationAlignmentType>(const char* name, const JSValue& value) {
|
|
|
|
|
optional<RotationAlignmentType> parseConstant<RotationAlignmentType>(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsString()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -207,7 +201,7 @@ optional<RotationAlignmentType> parseProperty<RotationAlignmentType>(const char*
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<std::array<float, 2>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<std::array<float, 2>> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (value.IsArray() && value.Size() == 2 &&
|
|
|
|
|
value[rapidjson::SizeType(0)].IsNumber() &&
|
|
|
|
|
value[rapidjson::SizeType(1)].IsNumber()) {
|
|
|
|
|
@@ -222,7 +216,7 @@ optional<std::array<float, 2>> parseProperty(const char* name, const JSValue& va
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<std::vector<float>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<std::vector<float>> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsArray()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -245,7 +239,7 @@ optional<std::vector<float>> parseProperty(const char* name, const JSValue& valu
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<std::vector<std::string>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
optional<std::vector<std::string>> parseConstant(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsArray()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of strings", name);
|
|
|
|
|
return {};
|
|
|
|
|
@@ -267,8 +261,7 @@ optional<std::vector<std::string>> parseProperty(const char* name, const JSValue
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <>
|
|
|
|
|
optional<PropertyTransition> parseProperty(const char *, const JSValue& value) {
|
|
|
|
|
optional<PropertyTransition> parsePropertyTransition(const char *, const JSValue& value) {
|
|
|
|
|
PropertyTransition transition;
|
|
|
|
|
if (value.IsObject()) {
|
|
|
|
|
bool parsed = false;
|
|
|
|
|
@@ -287,146 +280,4 @@ optional<PropertyTransition> parseProperty(const char *, const JSValue& value) {
|
|
|
|
|
return transition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- Function ---
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
optional<std::vector<std::pair<float, T>>> parseStops(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsArray()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<float, T>> stops;
|
|
|
|
|
|
|
|
|
|
for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
|
|
|
|
|
const JSValue& stop = value[i];
|
|
|
|
|
|
|
|
|
|
if (!stop.IsArray()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stop.Size() != 2) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const JSValue& z = stop[rapidjson::SizeType(0)];
|
|
|
|
|
if (!z.IsNumber()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optional<T> v = parseProperty<T>(name, stop[rapidjson::SizeType(1)]);
|
|
|
|
|
if (!v) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stops.emplace_back(z.GetDouble(), *v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stops;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
optional<Function<T>> parseFunction(const char* name, const JSValue& value) {
|
|
|
|
|
if (!value.IsObject()) {
|
|
|
|
|
auto constant = parseProperty<T>(name, value);
|
|
|
|
|
if (!constant) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
return { Function<T>(*constant) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!value.HasMember("stops")) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "function must specify a function type");
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float base = 1.0f;
|
|
|
|
|
|
|
|
|
|
if (value.HasMember("base")) {
|
|
|
|
|
const JSValue& value_base = value["base"];
|
|
|
|
|
|
|
|
|
|
if (!value_base.IsNumber()) {
|
|
|
|
|
Log::Warning(Event::ParseStyle, "base must be numeric");
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
base = value_base.GetDouble();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto stops = parseStops<T>(name, value["stops"]);
|
|
|
|
|
|
|
|
|
|
if (!stops) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { Function<T>(*stops, base) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<std::array<float, 2>>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<std::array<float, 2>>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<std::string>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<std::string>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<TranslateAnchorType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<TranslateAnchorType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<RotateAnchorType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<RotateAnchorType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<LineCapType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<LineCapType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<LineJoinType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<LineJoinType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<SymbolPlacementType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<SymbolPlacementType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<TextAnchorType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<TextAnchorType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<TextJustifyType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<TextJustifyType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<TextTransformType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<TextTransformType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<RotationAlignmentType>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<RotationAlignmentType>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <> optional<Function<bool>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<bool>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<> optional<Function<float>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<float>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<> optional<Function<Color>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<Color>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<> optional<Function<std::vector<float>>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<std::vector<float>>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<> optional<Function<std::vector<std::string>>> parseProperty(const char* name, const JSValue& value) {
|
|
|
|
|
return parseFunction<std::vector<std::string>>(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace mbgl
|
|
|
|
|
|