diff --git a/benchmark/parse/filter.cpp b/benchmark/parse/filter.cpp index 4269f8e1694..24314e85840 100644 --- a/benchmark/parse/filter.cpp +++ b/benchmark/parse/filter.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -17,7 +18,7 @@ typedef std::multimap Properties; style::Filter parse(const char* expression) { rapidjson::GenericDocument, rapidjson::CrtAllocator> doc; doc.Parse<0>(expression); - return style::conversion::convertFilter(doc).get(); + return *style::conversion::convert(doc); } static void Parse_Filter(benchmark::State& state) { diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp index 18326c8dd14..bd7db3adfbb 100644 --- a/include/mbgl/style/conversion.hpp +++ b/include/mbgl/style/conversion.hpp @@ -1,39 +1,34 @@ #pragma once -#include -#include -#include - #include -#include -#include -#include - -#include -#include -#include namespace mbgl { namespace style { namespace conversion { /* - This namespace defines a generic conversion from a templated type `V` representing a JSON object conforming - to a style property from the Mapbox Style Specification, to `PropertyValue`: + The `conversion` namespace defines conversions from a templated type `V` representing a JSON + object conforming to the schema defined by the Mapbox Style Specification, to the various C++ + types that form the C++ model of that domain: - template - Result> convertPropertyValue(const V& value); + * `std::unique_ptr` + * `std::unique_ptr` + * `Filter` + * `PropertyValue` - This is used concretely for conversions from RapidJSON types in mbgl core, and from v8 types in - the node bindings. + A single template function serves as the public interface: - It also defines a convertion from `V` to `Filter`, representing a JSON object conforming to a Style - Specification filter object: + template + Result convert(const V& value); + + Where `T` is one of the above types. If the conversion fails, the `Error` variant of `Result` is + returned, which includes diagnostic text suitable for presentation to a library user. Otherwise, + the `T` variant of `Result` is returned. - template - Result convertFilter(const V& value); + The implementation of `convert` requires that the following are legal expressions for a value `v` + of type `const V&`: - The requirements are that the following are legal expressions for a value `v` of type `const V&`: + * `isUndefined(v)` -- returns a boolean indication whether `v` is undefined or a JSON null * `isArray(v)` -- returns a boolean indicating whether `v` represents a JSON array * `arrayLength(v)` -- called only if `isArray(v)`; returns a size_t length @@ -43,6 +38,9 @@ namespace conversion { * `objectMember(v, name)` -- called only if `isObject(v)`; `name` is `const char *`; return value: * is true when evaluated in a boolean context iff the named member exists * is convertable to a `V` or `V&` when dereferenced + * `eachMember(v, [] (const std::string&, const V&) -> optional {...})` -- called + only if `isObject(v)`; calls the provided lambda once for each key and value of the object; + short-circuits if any call returns an `Error` * `toBool(v)` -- returns `optional`, absence indicating `v` is not a JSON boolean * `toNumber(v)` -- returns `optional`, absence indicating `v` is not a JSON number @@ -51,341 +49,43 @@ namespace conversion { absence indicating `v` is not a boolean, number, or string. Numbers should be converted to unsigned integer, signed integer, or floating point, in descending preference. - If for any reason the conversion fails, the result of `convertPropertyValue` will be the `Error` variant, - which includes explanatory text. + The mbgl core implements these requirements for RapidJSON types, and the node bindings implement + them for v8 types. */ struct Error { const char * message; }; -template -using Result = variant; - -template -struct ConstantConverter {}; - -template -struct ConstantConverter { - Result operator()(const V& value) const { - optional converted = toBool(value); - if (!converted) { - return Error { "value must be a boolean" }; - } - return *converted; - } -}; - -template -struct ConstantConverter { - Result operator()(const V& value) const { - optional converted = toNumber(value); - if (!converted) { - return Error { "value must be a number" }; - } - return *converted; - } -}; - -template -struct ConstantConverter { - Result operator()(const V& value) const { - optional converted = toString(value); - if (!converted) { - return Error { "value must be a string" }; - } - return *converted; - } -}; - -template -struct ConstantConverter::value>> { - Result operator()(const V& value) const { - optional string = toString(value); - if (!string) { - return Error { "value must be a string" }; - } - - const auto result = Enum::toEnum(*string); - if (!result) { - return Error { "value must be a valid enumeration value" }; - } - - return *result; - } -}; - -template -struct ConstantConverter { - Result operator()(const V& value) const { - optional string = toString(value); - if (!string) { - return Error { "value must be a string" }; - } - - optional color = Color::parse(*string); - if (!color) { - return Error { "value must be a valid color" }; - } - - return *color; - } -}; - -template -struct ConstantConverter> { - Result> operator()(const V& value) const { - if (!isArray(value) || arrayLength(value) != 2) { - return Error { "value must be an array of two numbers" }; - } +template +class Result : private variant { +public: + using variant::variant; - optional first = toNumber(arrayMember(value, 0)); - optional second = toNumber(arrayMember(value, 1)); - if (!first || !second) { - return Error { "value must be an array of two numbers" }; - } - - return std::array {{ *first, *second }}; + explicit operator bool() const { + return this->template is(); } -}; - -template -struct ConstantConverter> { - Result> operator()(const V& value) const { - if (!isArray(value) || arrayLength(value) != 4) { - return Error { "value must be an array of four numbers" }; - } - optional first = toNumber(arrayMember(value, 0)); - optional second = toNumber(arrayMember(value, 1)); - optional third = toNumber(arrayMember(value, 2)); - optional fourth = toNumber(arrayMember(value, 3)); - if (!first || !second) { - return Error { "value must be an array of four numbers" }; - } - - return std::array {{ *first, *second, *third, *fourth }}; + T& operator*() { + assert(this->template is()); + return this->template get(); } -}; - -template -struct ConstantConverter> { - Result> operator()(const V& value) const { - if (!isArray(value)) { - return Error { "value must be an array" }; - } - std::vector result; - result.reserve(arrayLength(value)); - - for (std::size_t i = 0; i < arrayLength(value); ++i) { - optional number = toNumber(arrayMember(value, i)); - if (!number) { - return Error { "value must be an array of numbers" }; - } - result.push_back(*number); - } - - return result; + const T& operator*() const { + assert(this->template is()); + return this->template get(); } -}; -template -struct ConstantConverter> { - Result> operator()(const V& value) const { - if (!isArray(value)) { - return Error { "value must be an array" }; - } - - std::vector result; - result.reserve(arrayLength(value)); - - for (std::size_t i = 0; i < arrayLength(value); ++i) { - optional string = toString(arrayMember(value, i)); - if (!string) { - return Error { "value must be an array of strings" }; - } - result.push_back(*string); - } - - return result; + const Error& error() const { + assert(this->template is()); + return this->template get(); } }; -template -Result> convertPropertyValue(const V& value) { - if (!isObject(value)) { - Result constant = ConstantConverter()(value); - if (constant.template is()) { - return constant.template get(); - } - return constant.template get(); - } - - auto stopsValue = objectMember(value, "stops"); - if (!stopsValue) { - return Error { "function value must specify stops" }; - } - - if (!isArray(*stopsValue)) { - return Error { "function stops must be an array" }; - } - - std::vector> stops; - for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) { - const auto& stopValue = arrayMember(*stopsValue, i); - - if (!isArray(stopValue)) { - return Error { "function stop must be an array" }; - } - - if (arrayLength(stopValue) != 2) { - return Error { "function stop must have two elements" }; - } - - optional z = toNumber(arrayMember(stopValue, 0)); - if (!z) { - return Error { "function stop zoom level must be a number" }; - } - - Result v = ConstantConverter()(arrayMember(stopValue, 1)); - if (v.template is()) { - return v.template get(); - } - - stops.emplace_back(*z, v.template get()); - } - - auto baseValue = objectMember(value, "base"); - if (!baseValue) { - return Function(stops, 1.0f); - } - - optional base = toNumber(*baseValue); - if (!base) { - return Error { "function base must be a number"}; - } - - return Function(stops, *base); -} - -Result normalizeFilterValue(const std::string& key, const optional&); - -template -Result convertFilter(const V& value); - -template -Result parseUnaryFilter(const V& value) { - if (arrayLength(value) < 2) { - return Error { "filter expression must have 2 elements" }; - } - - optional key = toString(arrayMember(value, 1)); - if (!key) { - return Error { "filter expression key must be a string" }; - } - - return FilterType { *key }; -} - -template -Result parseBinaryFilter(const V& value) { - if (arrayLength(value) < 3) { - return Error { "filter expression must have 3 elements" }; - } - - optional key = toString(arrayMember(value, 1)); - if (!key) { - return Error { "filter expression key must be a string" }; - } - - Result filterValue = normalizeFilterValue(*key, toValue(arrayMember(value, 2))); - if (filterValue.is()) { - return filterValue.get(); - } - - return FilterType { *key, filterValue.get() }; -} - -template -Result parseSetFilter(const V& value) { - if (arrayLength(value) < 2) { - return Error { "filter expression must at least 2 elements" }; - } - - optional key = toString(arrayMember(value, 1)); - if (!key) { - return Error { "filter expression key must be a string" }; - } - - std::vector values; - for (std::size_t i = 2; i < arrayLength(value); ++i) { - Result filterValue = normalizeFilterValue(*key, toValue(arrayMember(value, i))); - if (filterValue.is()) { - return filterValue.get(); - } - values.push_back(filterValue.get()); - } - - return FilterType { *key, std::move(values) }; -} - -template -Result parseCompoundFilter(const V& value) { - std::vector filters; - for (std::size_t i = 1; i < arrayLength(value); ++i) { - Result element = convertFilter(arrayMember(value, i)); - if (element.is()) { - return element; - } - filters.push_back(element.get()); - } - - return FilterType { std::move(filters) }; -} - -template -Result convertFilter(const V& value) { - if (!isArray(value)) { - return Error { "filter expression must be an array" }; - } - - if (arrayLength(value) < 1) { - return Error { "filter expression must have at least 1 element" }; - } - - optional op = toString(arrayMember(value, 0)); - if (!op) { - return Error { "filter operator must be a string" }; - } - - if (*op == "==") { - return parseBinaryFilter(value); - } else if (*op == "!=") { - return parseBinaryFilter(value); - } else if (*op == ">") { - return parseBinaryFilter(value); - } else if (*op == ">=") { - return parseBinaryFilter(value); - } else if (*op == "<") { - return parseBinaryFilter(value); - } else if (*op == "<=") { - return parseBinaryFilter(value); - } else if (*op == "in") { - return parseSetFilter(value); - } else if (*op == "!in") { - return parseSetFilter(value); - } else if (*op == "all") { - return parseCompoundFilter(value); - } else if (*op == "any") { - return parseCompoundFilter(value); - } else if (*op == "none") { - return parseCompoundFilter(value); - } else if (*op == "has") { - return parseUnaryFilter(value); - } else if (*op == "!has") { - return parseUnaryFilter(value); - } +template +struct Converter; - return Error { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" }; +template +Result convert(const V& value, Args&&...args) { + return Converter()(value, std::forward(args)...); } } // namespace conversion diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp new file mode 100644 index 00000000000..05bf968f4db --- /dev/null +++ b/include/mbgl/style/conversion/constant.hpp @@ -0,0 +1,174 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter { + template + Result operator()(const V& value) const { + optional converted = toBool(value); + if (!converted) { + return Error { "value must be a boolean" }; + } + return *converted; + } +}; + +template <> +struct Converter { + template + Result operator()(const V& value) const { + optional converted = toNumber(value); + if (!converted) { + return Error { "value must be a number" }; + } + return *converted; + } +}; + +template <> +struct Converter { + template + Result operator()(const V& value) const { + optional converted = toString(value); + if (!converted) { + return Error { "value must be a string" }; + } + return *converted; + } +}; + +template +struct Converter::value>> { + template + Result operator()(const V& value) const { + optional string = toString(value); + if (!string) { + return Error { "value must be a string" }; + } + + const auto result = Enum::toEnum(*string); + if (!result) { + return Error { "value must be a valid enumeration value" }; + } + + return *result; + } +}; + +template <> +struct Converter { + template + Result operator()(const V& value) const { + optional string = toString(value); + if (!string) { + return Error { "value must be a string" }; + } + + optional color = Color::parse(*string); + if (!color) { + return Error { "value must be a valid color" }; + } + + return *color; + } +}; + +template <> +struct Converter> { + template + Result> operator()(const V& value) const { + if (!isArray(value) || arrayLength(value) != 2) { + return Error { "value must be an array of two numbers" }; + } + + optional first = toNumber(arrayMember(value, 0)); + optional second = toNumber(arrayMember(value, 1)); + if (!first || !second) { + return Error { "value must be an array of two numbers" }; + } + + return std::array {{ *first, *second }}; + } +}; + +template <> +struct Converter> { + template + Result> operator()(const V& value) const { + if (!isArray(value) || arrayLength(value) != 4) { + return Error { "value must be an array of four numbers" }; + } + + optional first = toNumber(arrayMember(value, 0)); + optional second = toNumber(arrayMember(value, 1)); + optional third = toNumber(arrayMember(value, 2)); + optional fourth = toNumber(arrayMember(value, 3)); + if (!first || !second) { + return Error { "value must be an array of four numbers" }; + } + + return std::array {{ *first, *second, *third, *fourth }}; + } +}; + +template <> +struct Converter> { + template + Result> operator()(const V& value) const { + if (!isArray(value)) { + return Error { "value must be an array" }; + } + + std::vector result; + result.reserve(arrayLength(value)); + + for (std::size_t i = 0; i < arrayLength(value); ++i) { + optional number = toNumber(arrayMember(value, i)); + if (!number) { + return Error { "value must be an array of numbers" }; + } + result.push_back(*number); + } + + return result; + } +}; + +template <> +struct Converter> { + template + Result> operator()(const V& value) const { + if (!isArray(value)) { + return Error { "value must be an array" }; + } + + std::vector result; + result.reserve(arrayLength(value)); + + for (std::size_t i = 0; i < arrayLength(value); ++i) { + optional string = toString(arrayMember(value, i)); + if (!string) { + return Error { "value must be an array of strings" }; + } + result.push_back(*string); + } + + return result; + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp new file mode 100644 index 00000000000..3ab91e5bbc5 --- /dev/null +++ b/include/mbgl/style/conversion/filter.hpp @@ -0,0 +1,150 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter { +public: + template + Result operator()(const V& value) const { + if (!isArray(value)) { + return Error { "filter expression must be an array" }; + } + + if (arrayLength(value) < 1) { + return Error { "filter expression must have at least 1 element" }; + } + + optional op = toString(arrayMember(value, 0)); + if (!op) { + return Error { "filter operator must be a string" }; + } + + if (*op == "==") { + return convertBinaryFilter(value); + } else if (*op == "!=") { + return convertBinaryFilter(value); + } else if (*op == ">") { + return convertBinaryFilter(value); + } else if (*op == ">=") { + return convertBinaryFilter(value); + } else if (*op == "<") { + return convertBinaryFilter(value); + } else if (*op == "<=") { + return convertBinaryFilter(value); + } else if (*op == "in") { + return convertSetFilter(value); + } else if (*op == "!in") { + return convertSetFilter(value); + } else if (*op == "all") { + return convertCompoundFilter(value); + } else if (*op == "any") { + return convertCompoundFilter(value); + } else if (*op == "none") { + return convertCompoundFilter(value); + } else if (*op == "has") { + return convertUnaryFilter(value); + } else if (*op == "!has") { + return convertUnaryFilter(value); + } + + return Error { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" }; + } + +private: + Result normalizeValue(const std::string& key, const optional& value) const { + if (!value) { + return Error { "filter expression value must be a boolean, number, or string" }; + } else if (key != "$type") { + return *value; + } else if (*value == std::string("Point")) { + return Value(uint64_t(FeatureType::Point)); + } else if (*value == std::string("LineString")) { + return Value(uint64_t(FeatureType::LineString)); + } else if (*value == std::string("Polygon")) { + return Value(uint64_t(FeatureType::Polygon)); + } else { + return Error { "value for $type filter must be Point, LineString, or Polygon" }; + } + } + + template + Result convertUnaryFilter(const V& value) const { + if (arrayLength(value) < 2) { + return Error { "filter expression must have 2 elements" }; + } + + optional key = toString(arrayMember(value, 1)); + if (!key) { + return Error { "filter expression key must be a string" }; + } + + return FilterType { *key }; + } + + template + Result convertBinaryFilter(const V& value) const { + if (arrayLength(value) < 3) { + return Error { "filter expression must have 3 elements" }; + } + + optional key = toString(arrayMember(value, 1)); + if (!key) { + return Error { "filter expression key must be a string" }; + } + + Result filterValue = normalizeValue(*key, toValue(arrayMember(value, 2))); + if (!filterValue) { + return filterValue.error(); + } + + return FilterType { *key, *filterValue }; + } + + template + Result convertSetFilter(const V& value) const { + if (arrayLength(value) < 2) { + return Error { "filter expression must at least 2 elements" }; + } + + optional key = toString(arrayMember(value, 1)); + if (!key) { + return Error { "filter expression key must be a string" }; + } + + std::vector values; + for (std::size_t i = 2; i < arrayLength(value); ++i) { + Result filterValue = normalizeValue(*key, toValue(arrayMember(value, i))); + if (!filterValue) { + return filterValue.error(); + } + values.push_back(*filterValue); + } + + return FilterType { *key, std::move(values) }; + } + + template + Result convertCompoundFilter(const V& value) const { + std::vector filters; + for (std::size_t i = 1; i < arrayLength(value); ++i) { + Result element = operator()(arrayMember(value, i)); + if (!element) { + return element.error(); + } + filters.push_back(*element); + } + + return FilterType { std::move(filters) }; + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp new file mode 100644 index 00000000000..f14b5089be9 --- /dev/null +++ b/include/mbgl/style/conversion/function.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +struct Converter> { + template + Result> operator()(const V& value) const { + if (!isObject(value)) { + return Error { "function must be an object" }; + } + + auto stopsValue = objectMember(value, "stops"); + if (!stopsValue) { + return Error { "function value must specify stops" }; + } + + if (!isArray(*stopsValue)) { + return Error { "function stops must be an array" }; + } + + std::vector> stops; + for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) { + const auto& stopValue = arrayMember(*stopsValue, i); + + if (!isArray(stopValue)) { + return Error { "function stop must be an array" }; + } + + if (arrayLength(stopValue) != 2) { + return Error { "function stop must have two elements" }; + } + + optional z = toNumber(arrayMember(stopValue, 0)); + if (!z) { + return Error { "function stop zoom level must be a number" }; + } + + Result v = convert(arrayMember(stopValue, 1)); + if (!v) { + return v.error(); + } + + stops.emplace_back(*z, *v); + } + + auto baseValue = objectMember(value, "base"); + if (!baseValue) { + return Function(stops, 1.0f); + } + + optional base = toNumber(*baseValue); + if (!base) { + return Error { "function base must be a number"}; + } + + return Function(stops, *base); + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/geojson.hpp b/include/mbgl/style/conversion/geojson.hpp new file mode 100644 index 00000000000..ba10b3ecc87 --- /dev/null +++ b/include/mbgl/style/conversion/geojson.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +Result convertGeoJSON(const V& value); + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp new file mode 100644 index 00000000000..0539dcf9adf --- /dev/null +++ b/include/mbgl/style/conversion/layer.hpp @@ -0,0 +1,208 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +optional setLayoutProperty(Layer& layer, const std::string& name, const V& value) { + static const auto setters = makeLayoutPropertySetters(); + auto it = setters.find(name); + if (it == setters.end()) { + return Error { "property not found" }; + } + return it->second(layer, value); +} + +template +optional setPaintProperty(Layer& layer, const std::string& name, const V& value, const optional& klass) { + static const auto setters = makePaintPropertySetters(); + auto it = setters.find(name); + if (it == setters.end()) { + return Error { "property not found" }; + } + return it->second(layer, value, klass); +} + +template +optional setPaintProperties(Layer& layer, const V& value) { + return eachMember(value, [&] (const std::string& paintName, const V& paintValue) -> optional { + if (paintName.compare(0, 5, "paint") != 0) { + return {}; + } + + optional klass; + if (paintName.compare(0, 6, "paint.") == 0) { + klass = paintName.substr(6); + } + + return eachMember(paintValue, [&] (const std::string& k, const V& v) { + return setPaintProperty(layer, k, v, klass); + }); + }); +} + +template <> +struct Converter> { +public: + template + Result> operator()(const V& value) const { + if (!isObject(value)) { + return Error { "layer must be an object" }; + } + + auto idValue = objectMember(value, "id"); + if (!idValue) { + return Error { "layer must have an id" }; + } + + optional id = toString(*idValue); + if (!id) { + return Error { "layer id must be a string" }; + } + + auto typeValue = objectMember(value, "type"); + if (!typeValue) { + return Error { "layer must have a type" }; + } + + optional type = toString(*typeValue); + if (!type) { + return Error { "layer type must be a string" }; + } + + Result> converted; + + if (*type == "fill") { + converted = convertVectorLayer(*id, value); + } else if (*type == "line") { + converted = convertVectorLayer(*id, value); + } else if (*type == "circle") { + converted = convertVectorLayer(*id, value); + } else if (*type == "symbol") { + converted = convertVectorLayer(*id, value); + } else if (*type == "raster") { + converted = convertRasterLayer(*id, value); + } else if (*type == "background") { + converted = convertBackgroundLayer(*id, value); + } else { + return Error { "invalid layer type" }; + } + + if (!converted) { + return converted; + } + + std::unique_ptr layer = std::move(*converted); + + auto minzoomValue = objectMember(value, "minzoom"); + if (minzoomValue) { + optional minzoom = toNumber(*minzoomValue); + if (!minzoom) { + return Error { "minzoom must be numeric" }; + } + layer->setMinZoom(*minzoom); + } + + auto maxzoomValue = objectMember(value, "maxzoom"); + if (maxzoomValue) { + optional maxzoom = toNumber(*maxzoomValue); + if (!maxzoom) { + return Error { "maxzoom must be numeric" }; + } + layer->setMaxZoom(*maxzoom); + } + + auto layoutValue = objectMember(value, "layout"); + if (layoutValue) { + if (!isObject(*layoutValue)) { + return Error { "layout must be an object" }; + } + optional error = eachMember(*layoutValue, [&] (const std::string& k, const V& v) { + return setLayoutProperty(*layer, k, v); + }); + if (error) { + return *error; + } + } + + optional error = setPaintProperties(*layer, value); + if (error) { + return *error; + } + + return std::move(layer); + } + +private: + template + Result> convertVectorLayer(const std::string& id, const V& value) const { + auto sourceValue = objectMember(value, "source"); + if (!sourceValue) { + return Error { "layer must have a source" }; + } + + optional source = toString(*sourceValue); + if (!source) { + return Error { "layer source must be a string" }; + } + + std::unique_ptr layer = std::make_unique(id, *source); + + auto sourceLayerValue = objectMember(value, "source-layer"); + if (sourceLayerValue) { + optional sourceLayer = toString(*sourceLayerValue); + if (!sourceLayer) { + return Error { "layer source-layer must be a string" }; + } + layer->setSourceLayer(*sourceLayer); + } + + auto filterValue = objectMember(value, "filter"); + if (filterValue) { + Result filter = convert(*filterValue); + if (!filter) { + return filter.error(); + } + layer->setFilter(*filter); + } + + return std::move(layer); + } + + template + Result> convertRasterLayer(const std::string& id, const V& value) const { + auto sourceValue = objectMember(value, "source"); + if (!sourceValue) { + return Error { "layer must have a source" }; + } + + optional source = toString(*sourceValue); + if (!source) { + return Error { "layer source must be a string" }; + } + + return std::make_unique(id, *source); + } + + template + Result> convertBackgroundLayer(const std::string& id, const V&) const { + return std::make_unique(id); + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/make_property_setters.hpp b/include/mbgl/style/conversion/make_property_setters.hpp new file mode 100644 index 00000000000..4c0089deafe --- /dev/null +++ b/include/mbgl/style/conversion/make_property_setters.hpp @@ -0,0 +1,133 @@ +// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`. + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +auto makeLayoutPropertySetters() { + std::unordered_map> result; + + result["visibility"] = &setVisibility; + + + result["line-cap"] = makePropertySetter(&LineLayer::setLineCap); + result["line-join"] = makePropertySetter(&LineLayer::setLineJoin); + result["line-miter-limit"] = makePropertySetter(&LineLayer::setLineMiterLimit); + result["line-round-limit"] = makePropertySetter(&LineLayer::setLineRoundLimit); + + result["symbol-placement"] = makePropertySetter(&SymbolLayer::setSymbolPlacement); + result["symbol-spacing"] = makePropertySetter(&SymbolLayer::setSymbolSpacing); + result["symbol-avoid-edges"] = makePropertySetter(&SymbolLayer::setSymbolAvoidEdges); + result["icon-allow-overlap"] = makePropertySetter(&SymbolLayer::setIconAllowOverlap); + result["icon-ignore-placement"] = makePropertySetter(&SymbolLayer::setIconIgnorePlacement); + result["icon-optional"] = makePropertySetter(&SymbolLayer::setIconOptional); + result["icon-rotation-alignment"] = makePropertySetter(&SymbolLayer::setIconRotationAlignment); + result["icon-size"] = makePropertySetter(&SymbolLayer::setIconSize); + result["icon-text-fit"] = makePropertySetter(&SymbolLayer::setIconTextFit); + result["icon-text-fit-padding"] = makePropertySetter(&SymbolLayer::setIconTextFitPadding); + result["icon-image"] = makePropertySetter(&SymbolLayer::setIconImage); + result["icon-rotate"] = makePropertySetter(&SymbolLayer::setIconRotate); + result["icon-padding"] = makePropertySetter(&SymbolLayer::setIconPadding); + result["icon-keep-upright"] = makePropertySetter(&SymbolLayer::setIconKeepUpright); + result["icon-offset"] = makePropertySetter(&SymbolLayer::setIconOffset); + result["text-pitch-alignment"] = makePropertySetter(&SymbolLayer::setTextPitchAlignment); + result["text-rotation-alignment"] = makePropertySetter(&SymbolLayer::setTextRotationAlignment); + result["text-field"] = makePropertySetter(&SymbolLayer::setTextField); + result["text-font"] = makePropertySetter(&SymbolLayer::setTextFont); + result["text-size"] = makePropertySetter(&SymbolLayer::setTextSize); + result["text-max-width"] = makePropertySetter(&SymbolLayer::setTextMaxWidth); + result["text-line-height"] = makePropertySetter(&SymbolLayer::setTextLineHeight); + result["text-letter-spacing"] = makePropertySetter(&SymbolLayer::setTextLetterSpacing); + result["text-justify"] = makePropertySetter(&SymbolLayer::setTextJustify); + result["text-anchor"] = makePropertySetter(&SymbolLayer::setTextAnchor); + result["text-max-angle"] = makePropertySetter(&SymbolLayer::setTextMaxAngle); + result["text-rotate"] = makePropertySetter(&SymbolLayer::setTextRotate); + result["text-padding"] = makePropertySetter(&SymbolLayer::setTextPadding); + result["text-keep-upright"] = makePropertySetter(&SymbolLayer::setTextKeepUpright); + result["text-transform"] = makePropertySetter(&SymbolLayer::setTextTransform); + result["text-offset"] = makePropertySetter(&SymbolLayer::setTextOffset); + result["text-allow-overlap"] = makePropertySetter(&SymbolLayer::setTextAllowOverlap); + result["text-ignore-placement"] = makePropertySetter(&SymbolLayer::setTextIgnorePlacement); + result["text-optional"] = makePropertySetter(&SymbolLayer::setTextOptional); + + + + + return result; +} + +template +auto makePaintPropertySetters() { + std::unordered_map> result; + + result["fill-antialias"] = makePropertySetter(&FillLayer::setFillAntialias); + result["fill-opacity"] = makePropertySetter(&FillLayer::setFillOpacity); + result["fill-color"] = makePropertySetter(&FillLayer::setFillColor); + result["fill-outline-color"] = makePropertySetter(&FillLayer::setFillOutlineColor); + result["fill-translate"] = makePropertySetter(&FillLayer::setFillTranslate); + result["fill-translate-anchor"] = makePropertySetter(&FillLayer::setFillTranslateAnchor); + result["fill-pattern"] = makePropertySetter(&FillLayer::setFillPattern); + + result["line-opacity"] = makePropertySetter(&LineLayer::setLineOpacity); + result["line-color"] = makePropertySetter(&LineLayer::setLineColor); + result["line-translate"] = makePropertySetter(&LineLayer::setLineTranslate); + result["line-translate-anchor"] = makePropertySetter(&LineLayer::setLineTranslateAnchor); + result["line-width"] = makePropertySetter(&LineLayer::setLineWidth); + result["line-gap-width"] = makePropertySetter(&LineLayer::setLineGapWidth); + result["line-offset"] = makePropertySetter(&LineLayer::setLineOffset); + result["line-blur"] = makePropertySetter(&LineLayer::setLineBlur); + result["line-dasharray"] = makePropertySetter(&LineLayer::setLineDasharray); + result["line-pattern"] = makePropertySetter(&LineLayer::setLinePattern); + + result["icon-opacity"] = makePropertySetter(&SymbolLayer::setIconOpacity); + result["icon-color"] = makePropertySetter(&SymbolLayer::setIconColor); + result["icon-halo-color"] = makePropertySetter(&SymbolLayer::setIconHaloColor); + result["icon-halo-width"] = makePropertySetter(&SymbolLayer::setIconHaloWidth); + result["icon-halo-blur"] = makePropertySetter(&SymbolLayer::setIconHaloBlur); + result["icon-translate"] = makePropertySetter(&SymbolLayer::setIconTranslate); + result["icon-translate-anchor"] = makePropertySetter(&SymbolLayer::setIconTranslateAnchor); + result["text-opacity"] = makePropertySetter(&SymbolLayer::setTextOpacity); + result["text-color"] = makePropertySetter(&SymbolLayer::setTextColor); + result["text-halo-color"] = makePropertySetter(&SymbolLayer::setTextHaloColor); + result["text-halo-width"] = makePropertySetter(&SymbolLayer::setTextHaloWidth); + result["text-halo-blur"] = makePropertySetter(&SymbolLayer::setTextHaloBlur); + result["text-translate"] = makePropertySetter(&SymbolLayer::setTextTranslate); + result["text-translate-anchor"] = makePropertySetter(&SymbolLayer::setTextTranslateAnchor); + + result["circle-radius"] = makePropertySetter(&CircleLayer::setCircleRadius); + result["circle-color"] = makePropertySetter(&CircleLayer::setCircleColor); + result["circle-blur"] = makePropertySetter(&CircleLayer::setCircleBlur); + result["circle-opacity"] = makePropertySetter(&CircleLayer::setCircleOpacity); + result["circle-translate"] = makePropertySetter(&CircleLayer::setCircleTranslate); + result["circle-translate-anchor"] = makePropertySetter(&CircleLayer::setCircleTranslateAnchor); + + result["raster-opacity"] = makePropertySetter(&RasterLayer::setRasterOpacity); + result["raster-hue-rotate"] = makePropertySetter(&RasterLayer::setRasterHueRotate); + result["raster-brightness-min"] = makePropertySetter(&RasterLayer::setRasterBrightnessMin); + result["raster-brightness-max"] = makePropertySetter(&RasterLayer::setRasterBrightnessMax); + result["raster-saturation"] = makePropertySetter(&RasterLayer::setRasterSaturation); + result["raster-contrast"] = makePropertySetter(&RasterLayer::setRasterContrast); + result["raster-fade-duration"] = makePropertySetter(&RasterLayer::setRasterFadeDuration); + + result["background-color"] = makePropertySetter(&BackgroundLayer::setBackgroundColor); + result["background-pattern"] = makePropertySetter(&BackgroundLayer::setBackgroundPattern); + result["background-opacity"] = makePropertySetter(&BackgroundLayer::setBackgroundOpacity); + + return result; +} + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/make_property_setters.hpp.ejs b/include/mbgl/style/conversion/make_property_setters.hpp.ejs new file mode 100644 index 00000000000..493c68ea31c --- /dev/null +++ b/include/mbgl/style/conversion/make_property_setters.hpp.ejs @@ -0,0 +1,45 @@ +// This file is generated. Edit make_property_setters.hpp.ejs, then run `make style-code`. + +#include + +<% for (const layer of locals.layers) { -%> +#include _layer.hpp> +<% } -%> + +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +auto makeLayoutPropertySetters() { + std::unordered_map> result; + + result["visibility"] = &setVisibility; + +<% for (const layer of locals.layers) { -%> +<% for (const property of layer.layoutProperties) { -%> + result["<%- property.name %>"] = makePropertySetter(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>); +<% } -%> + +<% } -%> + return result; +} + +template +auto makePaintPropertySetters() { + std::unordered_map> result; + +<% for (const layer of locals.layers) { -%> +<% for (const property of layer.paintProperties) { -%> + result["<%- property.name %>"] = makePropertySetter(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>); +<% } -%> + +<% } -%> + return result; +} + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp new file mode 100644 index 00000000000..38dd9342528 --- /dev/null +++ b/include/mbgl/style/conversion/property_setter.hpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include + +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +using LayoutPropertySetter = std::function (Layer&, const V&)>; + +template +using PaintPropertySetter = std::function (Layer&, const V&, const optional&)>; + +template +auto makePropertySetter(void (L::*setter)(PropertyValue, const Args&...args)) { + return [setter] (Layer& layer, const V& value, const Args&...args) -> optional { + L* typedLayer = layer.as(); + if (!typedLayer) { + return Error { "layer doesn't support this property" }; + } + + Result> typedValue = convert>(value); + if (!typedValue) { + return typedValue.error(); + } + + (typedLayer->*setter)(*typedValue, args...); + return {}; + }; +} + +template +optional setVisibility(Layer& layer, const V& value) { + if (isUndefined(value)) { + layer.setVisibility(VisibilityType::Visible); + return {}; + } + + Result visibility = convert(value); + if (!visibility) { + return visibility.error(); + } + + layer.setVisibility(*visibility); + return {}; +} + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp new file mode 100644 index 00000000000..de95b561557 --- /dev/null +++ b/include/mbgl/style/conversion/property_value.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template +struct Converter> { + template + Result> operator()(const V& value) const { + if (isUndefined(value)) { + return {}; + } else if (isObject(value)) { + Result> function = convert>(value); + if (!function) { + return function.error(); + } + return *function; + } else { + Result constant = convert(value); + if (!constant) { + return constant.error(); + } + return *constant; + } + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp new file mode 100644 index 00000000000..00c6afb9fef --- /dev/null +++ b/include/mbgl/style/conversion/source.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter> { +public: + template + Result> operator()(const V& value, const std::string& id) const { + if (!isObject(value)) { + return Error { "source must be an object" }; + } + + auto typeValue = objectMember(value, "type"); + if (!typeValue) { + return Error { "source must have a type" }; + } + + optional type = toString(*typeValue); + if (!type) { + return Error { "source type must be a string" }; + } + + if (*type == "raster") { + return convertRasterSource(id, value); + } else if (*type == "vector") { + return convertVectorSource(id, value); + } else if (*type == "geojson") { + return convertGeoJSONSource(id, value); + } else { + return Error { "invalid source type" }; + } + } + +private: + // A tile source can either specify a URL to TileJSON, or inline TileJSON. + template + Result> convertURLOrTileset(const V& value) const { + auto urlVal = objectMember(value, "url"); + if (!urlVal) { + Result tileset = convert(value); + if (!tileset) { + return tileset.error(); + } + return *tileset; + } + + optional url = toString(*urlVal); + if (!url) { + return Error { "source url must be a string" }; + } + + return *url; + } + + template + Result> convertRasterSource(const std::string& id, const V& value) const { + Result> urlOrTileset = convertURLOrTileset(value); + if (!urlOrTileset) { + return urlOrTileset.error(); + } + + uint16_t tileSize = util::tileSize; + auto tileSizeValue = objectMember(value, "tileSize"); + if (tileSizeValue) { + optional size = toNumber(*tileSizeValue); + if (!size || *size < 0 || *size > std::numeric_limits::max()) { + return Error { "invalid tileSize" }; + } + tileSize = *size; + } + + return std::make_unique(id, std::move(*urlOrTileset), tileSize); + } + + template + Result> convertVectorSource(const std::string& id, const V& value) const { + Result> urlOrTileset = convertURLOrTileset(value); + if (!urlOrTileset) { + return urlOrTileset.error(); + } + + return std::make_unique(id, std::move(*urlOrTileset)); + } + + template + Result> convertGeoJSONSource(const std::string& id, const V& value) const { + auto dataValue = objectMember(value, "data"); + if (!dataValue) { + return Error { "GeoJSON source must have a data value" }; + } + + auto result = std::make_unique(id); + + if (isObject(*dataValue)) { + Result geoJSON = convertGeoJSON(*dataValue); + if (!geoJSON) { + return geoJSON.error(); + } + result->setGeoJSON(std::move(*geoJSON)); + } else if (toString(*dataValue)) { + result->setURL(*toString(*dataValue)); + } else { + return Error { "GeoJSON data must be a URL or an object" }; + } + + return std::move(result); + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp new file mode 100644 index 00000000000..46425597afb --- /dev/null +++ b/include/mbgl/style/conversion/tileset.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter { +public: + template + Result operator()(const V& value) const { + Tileset result; + + auto tiles = objectMember(value, "tiles"); + if (!tiles) { + return Error { "source must have tiles" }; + } + + if (!isArray(*tiles)) { + return Error { "source tiles must be an array" }; + } + + for (std::size_t i = 0; i < arrayLength(*tiles); i++) { + optional urlTemplate = toString(arrayMember(*tiles, i)); + if (!urlTemplate) { + return Error { "source tiles member must be a string" }; + } + result.tiles.push_back(std::move(*urlTemplate)); + } + + auto minzoomValue = objectMember(value, "minzoom"); + if (minzoomValue) { + optional minzoom = toNumber(*minzoomValue); + if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits::max()) { + return Error { "invalid minzoom" }; + } + result.zoomRange.min = *minzoom; + } + + auto maxzoomValue = objectMember(value, "maxzoom"); + if (maxzoomValue) { + optional maxzoom = toNumber(*maxzoomValue); + if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits::max()) { + return Error { "invalid maxzoom" }; + } + result.zoomRange.max = *maxzoom; + } + + auto attributionValue = objectMember(value, "attribution"); + if (attributionValue) { + optional attribution = toString(*attributionValue); + if (!attribution) { + return Error { "source attribution must be a string" }; + } + result.attribution = std::move(*attribution); + } + + return result; + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp index 1f4a6fdf35b..1eff9eb3dcd 100644 --- a/include/mbgl/style/layer.hpp +++ b/include/mbgl/style/layer.hpp @@ -55,11 +55,6 @@ class Layer : public mbgl::util::noncopyable { float getMaxZoom() const; void setMaxZoom(float) const; - // Create a new layer with the specified `id` and `ref`. All other properties - // are copied from this layer. - std::unique_ptr copy(const std::string& id, - const std::string& ref) const; - // Private implementation class Impl; const std::unique_ptr baseImpl; diff --git a/include/mbgl/style/layers/background_layer.hpp b/include/mbgl/style/layers/background_layer.hpp index 2eb84ee499a..ac97ec2e6de 100644 --- a/include/mbgl/style/layers/background_layer.hpp +++ b/include/mbgl/style/layers/background_layer.hpp @@ -19,13 +19,13 @@ class BackgroundLayer : public Layer { // Paint properties PropertyValue getBackgroundColor() const; - void setBackgroundColor(PropertyValue); + void setBackgroundColor(PropertyValue, const optional& klass = {}); PropertyValue getBackgroundPattern() const; - void setBackgroundPattern(PropertyValue); + void setBackgroundPattern(PropertyValue, const optional& klass = {}); PropertyValue getBackgroundOpacity() const; - void setBackgroundOpacity(PropertyValue); + void setBackgroundOpacity(PropertyValue, const optional& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/circle_layer.hpp b/include/mbgl/style/layers/circle_layer.hpp index 10d281b6ac6..c8d99ab30e4 100644 --- a/include/mbgl/style/layers/circle_layer.hpp +++ b/include/mbgl/style/layers/circle_layer.hpp @@ -13,14 +13,13 @@ namespace style { class CircleLayer : public Layer { public: - CircleLayer(const std::string& layerID); + CircleLayer(const std::string& layerID, const std::string& sourceID); ~CircleLayer() final; // Source - - void setSource(const std::string& sourceID, const std::string& sourceLayer); const std::string& getSourceID() const; const std::string& getSourceLayer() const; + void setSourceLayer(const std::string& sourceLayer); void setFilter(const Filter&); const Filter& getFilter() const; @@ -28,22 +27,22 @@ class CircleLayer : public Layer { // Paint properties PropertyValue getCircleRadius() const; - void setCircleRadius(PropertyValue); + void setCircleRadius(PropertyValue, const optional& klass = {}); PropertyValue getCircleColor() const; - void setCircleColor(PropertyValue); + void setCircleColor(PropertyValue, const optional& klass = {}); PropertyValue getCircleBlur() const; - void setCircleBlur(PropertyValue); + void setCircleBlur(PropertyValue, const optional& klass = {}); PropertyValue getCircleOpacity() const; - void setCircleOpacity(PropertyValue); + void setCircleOpacity(PropertyValue, const optional& klass = {}); PropertyValue> getCircleTranslate() const; - void setCircleTranslate(PropertyValue>); + void setCircleTranslate(PropertyValue>, const optional& klass = {}); PropertyValue getCircleTranslateAnchor() const; - void setCircleTranslateAnchor(PropertyValue); + void setCircleTranslateAnchor(PropertyValue, const optional& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/fill_layer.hpp b/include/mbgl/style/layers/fill_layer.hpp index a14bf4a3906..e70d67f5380 100644 --- a/include/mbgl/style/layers/fill_layer.hpp +++ b/include/mbgl/style/layers/fill_layer.hpp @@ -13,14 +13,13 @@ namespace style { class FillLayer : public Layer { public: - FillLayer(const std::string& layerID); + FillLayer(const std::string& layerID, const std::string& sourceID); ~FillLayer() final; // Source - - void setSource(const std::string& sourceID, const std::string& sourceLayer); const std::string& getSourceID() const; const std::string& getSourceLayer() const; + void setSourceLayer(const std::string& sourceLayer); void setFilter(const Filter&); const Filter& getFilter() const; @@ -28,25 +27,25 @@ class FillLayer : public Layer { // Paint properties PropertyValue getFillAntialias() const; - void setFillAntialias(PropertyValue); + void setFillAntialias(PropertyValue, const optional& klass = {}); PropertyValue getFillOpacity() const; - void setFillOpacity(PropertyValue); + void setFillOpacity(PropertyValue, const optional& klass = {}); PropertyValue getFillColor() const; - void setFillColor(PropertyValue); + void setFillColor(PropertyValue, const optional& klass = {}); PropertyValue getFillOutlineColor() const; - void setFillOutlineColor(PropertyValue); + void setFillOutlineColor(PropertyValue, const optional& klass = {}); PropertyValue> getFillTranslate() const; - void setFillTranslate(PropertyValue>); + void setFillTranslate(PropertyValue>, const optional& klass = {}); PropertyValue getFillTranslateAnchor() const; - void setFillTranslateAnchor(PropertyValue); + void setFillTranslateAnchor(PropertyValue, const optional& klass = {}); PropertyValue getFillPattern() const; - void setFillPattern(PropertyValue); + void setFillPattern(PropertyValue, const optional& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/layer.hpp.ejs b/include/mbgl/style/layers/layer.hpp.ejs index fdf76208929..aaae30287cf 100644 --- a/include/mbgl/style/layers/layer.hpp.ejs +++ b/include/mbgl/style/layers/layer.hpp.ejs @@ -22,24 +22,23 @@ namespace style { class <%- camelize(type) %>Layer : public Layer { public: +<% if (type === 'background') { -%> <%- camelize(type) %>Layer(const std::string& layerID); +<% } else { -%> + <%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID); +<% } -%> ~<%- camelize(type) %>Layer() final; -<% if (type === 'raster') { -%> - // Source - - void setSource(const std::string& sourceID); - const std::string& getSourceID() const; - -<% } else if (type !== 'background') { -%> +<% if (type !== 'background') { -%> // Source - - void setSource(const std::string& sourceID, const std::string& sourceLayer); const std::string& getSourceID() const; +<% if (type !== 'raster') { -%> const std::string& getSourceLayer() const; + void setSourceLayer(const std::string& sourceLayer); void setFilter(const Filter&); const Filter& getFilter() const; +<% } -%> <% } -%> <% if (layoutProperties.length) { -%> @@ -55,7 +54,7 @@ public: <% for (const property of paintProperties) { -%> PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>() const; - void set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>>); + void set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>>, const optional& klass = {}); <% } -%> // Private implementation diff --git a/include/mbgl/style/layers/line_layer.hpp b/include/mbgl/style/layers/line_layer.hpp index fb9e37811a9..abcb425b967 100644 --- a/include/mbgl/style/layers/line_layer.hpp +++ b/include/mbgl/style/layers/line_layer.hpp @@ -15,14 +15,13 @@ namespace style { class LineLayer : public Layer { public: - LineLayer(const std::string& layerID); + LineLayer(const std::string& layerID, const std::string& sourceID); ~LineLayer() final; // Source - - void setSource(const std::string& sourceID, const std::string& sourceLayer); const std::string& getSourceID() const; const std::string& getSourceLayer() const; + void setSourceLayer(const std::string& sourceLayer); void setFilter(const Filter&); const Filter& getFilter() const; @@ -44,34 +43,34 @@ class LineLayer : public Layer { // Paint properties PropertyValue getLineOpacity() const; - void setLineOpacity(PropertyValue); + void setLineOpacity(PropertyValue, const optional& klass = {}); PropertyValue getLineColor() const; - void setLineColor(PropertyValue); + void setLineColor(PropertyValue, const optional& klass = {}); PropertyValue> getLineTranslate() const; - void setLineTranslate(PropertyValue>); + void setLineTranslate(PropertyValue>, const optional& klass = {}); PropertyValue getLineTranslateAnchor() const; - void setLineTranslateAnchor(PropertyValue); + void setLineTranslateAnchor(PropertyValue, const optional& klass = {}); PropertyValue getLineWidth() const; - void setLineWidth(PropertyValue); + void setLineWidth(PropertyValue, const optional& klass = {}); PropertyValue getLineGapWidth() const; - void setLineGapWidth(PropertyValue); + void setLineGapWidth(PropertyValue, const optional& klass = {}); PropertyValue getLineOffset() const; - void setLineOffset(PropertyValue); + void setLineOffset(PropertyValue, const optional& klass = {}); PropertyValue getLineBlur() const; - void setLineBlur(PropertyValue); + void setLineBlur(PropertyValue, const optional& klass = {}); PropertyValue> getLineDasharray() const; - void setLineDasharray(PropertyValue>); + void setLineDasharray(PropertyValue>, const optional& klass = {}); PropertyValue getLinePattern() const; - void setLinePattern(PropertyValue); + void setLinePattern(PropertyValue, const optional& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/raster_layer.hpp b/include/mbgl/style/layers/raster_layer.hpp index 6d0c7dd91cd..dea0c26bf36 100644 --- a/include/mbgl/style/layers/raster_layer.hpp +++ b/include/mbgl/style/layers/raster_layer.hpp @@ -13,36 +13,34 @@ namespace style { class RasterLayer : public Layer { public: - RasterLayer(const std::string& layerID); + RasterLayer(const std::string& layerID, const std::string& sourceID); ~RasterLayer() final; // Source - - void setSource(const std::string& sourceID); const std::string& getSourceID() const; // Paint properties PropertyValue getRasterOpacity() const; - void setRasterOpacity(PropertyValue); + void setRasterOpacity(PropertyValue, const optional& klass = {}); PropertyValue getRasterHueRotate() const; - void setRasterHueRotate(PropertyValue); + void setRasterHueRotate(PropertyValue, const optional& klass = {}); PropertyValue getRasterBrightnessMin() const; - void setRasterBrightnessMin(PropertyValue); + void setRasterBrightnessMin(PropertyValue, const optional& klass = {}); PropertyValue getRasterBrightnessMax() const; - void setRasterBrightnessMax(PropertyValue); + void setRasterBrightnessMax(PropertyValue, const optional& klass = {}); PropertyValue getRasterSaturation() const; - void setRasterSaturation(PropertyValue); + void setRasterSaturation(PropertyValue, const optional& klass = {}); PropertyValue getRasterContrast() const; - void setRasterContrast(PropertyValue); + void setRasterContrast(PropertyValue, const optional& klass = {}); PropertyValue getRasterFadeDuration() const; - void setRasterFadeDuration(PropertyValue); + void setRasterFadeDuration(PropertyValue, const optional& klass = {}); // Private implementation diff --git a/include/mbgl/style/layers/symbol_layer.hpp b/include/mbgl/style/layers/symbol_layer.hpp index 7d98a5ef6bf..77b63d9b91e 100644 --- a/include/mbgl/style/layers/symbol_layer.hpp +++ b/include/mbgl/style/layers/symbol_layer.hpp @@ -15,14 +15,13 @@ namespace style { class SymbolLayer : public Layer { public: - SymbolLayer(const std::string& layerID); + SymbolLayer(const std::string& layerID, const std::string& sourceID); ~SymbolLayer() final; // Source - - void setSource(const std::string& sourceID, const std::string& sourceLayer); const std::string& getSourceID() const; const std::string& getSourceLayer() const; + void setSourceLayer(const std::string& sourceLayer); void setFilter(const Filter&); const Filter& getFilter() const; @@ -134,46 +133,46 @@ class SymbolLayer : public Layer { // Paint properties PropertyValue getIconOpacity() const; - void setIconOpacity(PropertyValue); + void setIconOpacity(PropertyValue, const optional& klass = {}); PropertyValue getIconColor() const; - void setIconColor(PropertyValue); + void setIconColor(PropertyValue, const optional& klass = {}); PropertyValue getIconHaloColor() const; - void setIconHaloColor(PropertyValue); + void setIconHaloColor(PropertyValue, const optional& klass = {}); PropertyValue getIconHaloWidth() const; - void setIconHaloWidth(PropertyValue); + void setIconHaloWidth(PropertyValue, const optional& klass = {}); PropertyValue getIconHaloBlur() const; - void setIconHaloBlur(PropertyValue); + void setIconHaloBlur(PropertyValue, const optional& klass = {}); PropertyValue> getIconTranslate() const; - void setIconTranslate(PropertyValue>); + void setIconTranslate(PropertyValue>, const optional& klass = {}); PropertyValue getIconTranslateAnchor() const; - void setIconTranslateAnchor(PropertyValue); + void setIconTranslateAnchor(PropertyValue, const optional& klass = {}); PropertyValue getTextOpacity() const; - void setTextOpacity(PropertyValue); + void setTextOpacity(PropertyValue, const optional& klass = {}); PropertyValue getTextColor() const; - void setTextColor(PropertyValue); + void setTextColor(PropertyValue, const optional& klass = {}); PropertyValue getTextHaloColor() const; - void setTextHaloColor(PropertyValue); + void setTextHaloColor(PropertyValue, const optional& klass = {}); PropertyValue getTextHaloWidth() const; - void setTextHaloWidth(PropertyValue); + void setTextHaloWidth(PropertyValue, const optional& klass = {}); PropertyValue getTextHaloBlur() const; - void setTextHaloBlur(PropertyValue); + void setTextHaloBlur(PropertyValue, const optional& klass = {}); PropertyValue> getTextTranslate() const; - void setTextTranslate(PropertyValue>); + void setTextTranslate(PropertyValue>, const optional& klass = {}); PropertyValue getTextTranslateAnchor() const; - void setTextTranslateAnchor(PropertyValue); + void setTextTranslateAnchor(PropertyValue, const optional& klass = {}); // Private implementation diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp index 96b9a99606c..3736dd44bc0 100644 --- a/include/mbgl/style/sources/geojson_source.hpp +++ b/include/mbgl/style/sources/geojson_source.hpp @@ -1,26 +1,22 @@ #pragma once #include +#include namespace mbgl { namespace style { class GeoJSONSource : public Source { public: - // Future public API: - // void setData(FeatureCollection&&); - // void setJSON(const std::string& json); - // void loadData(const std::string& url); + GeoJSONSource(const std::string& id); + void setURL(const std::string& url); + void setGeoJSON(GeoJSON&&); // Private implementation class Impl; - - template - GeoJSONSource(Fn&& fn) - : Source(SourceType::GeoJSON, fn(*this)) { - } + Impl* const impl; }; } // namespace style diff --git a/include/mbgl/util/geojson.hpp b/include/mbgl/util/geojson.hpp new file mode 100644 index 00000000000..3fd8c6ac4b7 --- /dev/null +++ b/include/mbgl/util/geojson.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace mapbox { +namespace geojsonvt { +class GeoJSONVT; +} // namespace geojsonvt +} // namespace mapbox + +namespace mbgl { + +class GeoJSON { +public: + GeoJSON(std::unique_ptr); + GeoJSON(GeoJSON&&); + ~GeoJSON(); + + std::unique_ptr impl; +}; + +} // namespace mbgl diff --git a/package.json b/package.json index 592559175ff..4ca0cd119aa 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "express": "^4.11.1", "mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#59e998295d548f208ee3ec10cdd21ff2630e2079", "mapbox-gl-style-spec": "mapbox/mapbox-gl-style-spec#194fc55b6a7dd54c1e2cf2dd9048fbb5e836716d", - "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#9a7de2fb72607be6ffa0040bf3d84651719a45e3", + "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#cb733d358a95d46344c2212f1546ed94022718f7", "node-gyp": "^3.3.1", "request": "^2.72.0", "tape": "^4.5.1" diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index 2aaeb30fab6..bad23cadbe5 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -127,7 +127,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const { case SourceType::GeoJSON: { style::GeoJSONSource::Impl* geojsonSource = static_cast(source->baseImpl.get()); - const variant& urlOrGeoJSON = geojsonSource->getURLOrGeoJSON(); + const variant& urlOrGeoJSON = geojsonSource->getURLOrGeoJSON(); if (urlOrGeoJSON.is()) { result.requiredResourceCount += 1; @@ -190,7 +190,7 @@ void OfflineDownload::activateDownload() { case SourceType::GeoJSON: { style::GeoJSONSource::Impl* geojsonSource = static_cast(source->baseImpl.get()); - const variant& urlOrGeoJSON = geojsonSource->getURLOrGeoJSON(); + const variant& urlOrGeoJSON = geojsonSource->getURLOrGeoJSON(); if (urlOrGeoJSON.is()) { ensureResource(Resource::source(urlOrGeoJSON.get())); diff --git a/platform/node/src/node_conversion.hpp b/platform/node/src/node_conversion.hpp index 03c13b5846d..2418a7a6e45 100644 --- a/platform/node/src/node_conversion.hpp +++ b/platform/node/src/node_conversion.hpp @@ -8,11 +8,17 @@ #include #include +#include namespace mbgl { namespace style { namespace conversion { +inline bool isUndefined(v8::Local value) { + Nan::HandleScope scope; + return value->IsUndefined() || value->IsNull(); +} + inline bool isArray(v8::Local value) { Nan::HandleScope scope; return value->IsArray(); @@ -35,16 +41,31 @@ inline bool isObject(v8::Local value) { inline optional> objectMember(v8::Local value, const char * name) { Nan::EscapableHandleScope scope; - if (!Nan::Has(value.As(), Nan::New(name).ToLocalChecked()).FromJust()) { + if (!Nan::Has(value->ToObject(), Nan::New(name).ToLocalChecked()).FromJust()) { return {}; } - Nan::MaybeLocal result = Nan::Get(value.As(), Nan::New(name).ToLocalChecked()); + Nan::MaybeLocal result = Nan::Get(value->ToObject(), Nan::New(name).ToLocalChecked()); if (result.IsEmpty()) { return {}; } return scope.Escape(result.ToLocalChecked()); } +template +optional eachMember(v8::Local value, Fn&& fn) { + Nan::HandleScope scope; + v8::Local names = value->ToObject()->GetOwnPropertyNames(); + for (uint32_t i = 0; i < names->Length(); ++i) { + v8::Local k = Nan::Get(names, i).ToLocalChecked(); + v8::Local v = Nan::Get(value->ToObject(), k).ToLocalChecked(); + optional result = fn(*Nan::Utf8String(k), v); + if (result) { + return result; + } + } + return {}; +} + inline optional toBool(v8::Local value) { Nan::HandleScope scope; if (!value->IsBoolean()) { diff --git a/platform/node/src/node_geojson.hpp b/platform/node/src/node_geojson.hpp new file mode 100644 index 00000000000..ace4c914264 --- /dev/null +++ b/platform/node/src/node_geojson.hpp @@ -0,0 +1,14 @@ +#include + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +Result convertGeoJSON(const v8::Local&) { + return Error { "not implemented" }; +} + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index e6ee84ee53b..7bcdd9cdda3 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -1,12 +1,14 @@ #include "node_map.hpp" #include "node_request.hpp" #include "node_feature.hpp" -#include "node_style_properties.hpp" +#include "node_conversion.hpp" +#include "node_geojson.hpp" #include #include -#include -#include +#include +#include +#include #include @@ -56,6 +58,8 @@ NAN_MODULE_INIT(NodeMap::Init) { Nan::SetPrototypeMethod(tpl, "release", Release); Nan::SetPrototypeMethod(tpl, "addClass", AddClass); + Nan::SetPrototypeMethod(tpl, "addSource", AddSource); + Nan::SetPrototypeMethod(tpl, "addLayer", AddLayer); Nan::SetPrototypeMethod(tpl, "setLayoutProperty", SetLayoutProperty); Nan::SetPrototypeMethod(tpl, "setPaintProperty", SetPaintProperty); Nan::SetPrototypeMethod(tpl, "setFilter", SetFilter); @@ -483,7 +487,54 @@ NAN_METHOD(NodeMap::AddClass) { info.GetReturnValue().SetUndefined(); } -void NodeMap::setProperty(const Nan::FunctionCallbackInfo& info, const PropertySetters& setters) { +NAN_METHOD(NodeMap::AddSource) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); + if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); + + if (info.Length() != 2) { + return Nan::ThrowTypeError("Two argument required"); + } + + if (!info[0]->IsString()) { + return Nan::ThrowTypeError("First argument must be a string"); + } + + Result> source = convert>(info[1], *Nan::Utf8String(info[0])); + if (!source) { + Nan::ThrowTypeError(source.error().message); + return; + } + + nodeMap->map->addSource(std::move(*source)); +} + +NAN_METHOD(NodeMap::AddLayer) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); + if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); + + if (info.Length() != 1) { + return Nan::ThrowTypeError("One argument required"); + } + + Result> layer = convert>(info[0]); + if (!layer) { + Nan::ThrowTypeError(layer.error().message); + return; + } + + nodeMap->map->addLayer(std::move(*layer)); +} + +NAN_METHOD(NodeMap::SetLayoutProperty) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -504,30 +555,57 @@ void NodeMap::setProperty(const Nan::FunctionCallbackInfo& info, cons return Nan::ThrowTypeError("Second argument must be a string"); } - auto it = setters.find(*Nan::Utf8String(info[1])); - if (it == setters.end()) { - return Nan::ThrowTypeError("property not found"); - } - - if (!it->second(*layer, info[2])) { - return; + mbgl::optional error = setLayoutProperty(*layer, *Nan::Utf8String(info[1]), info[2]); + if (error) { + return Nan::ThrowTypeError(error->message); } nodeMap->map->update(mbgl::Update::RecalculateStyle); info.GetReturnValue().SetUndefined(); } -NAN_METHOD(NodeMap::SetLayoutProperty) { - static const PropertySetters setters = makeLayoutPropertySetters(); - setProperty(info, setters); -} - NAN_METHOD(NodeMap::SetPaintProperty) { - static const PropertySetters setters = makePaintPropertySetters(); - setProperty(info, setters); + using namespace mbgl::style; + using namespace mbgl::style::conversion; + + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); + if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); + + if (info.Length() < 3) { + return Nan::ThrowTypeError("Three arguments required"); + } + + if (!info[0]->IsString()) { + return Nan::ThrowTypeError("First argument must be a string"); + } + + mbgl::style::Layer* layer = nodeMap->map->getLayer(*Nan::Utf8String(info[0])); + if (!layer) { + return Nan::ThrowTypeError("layer not found"); + } + + if (!info[1]->IsString()) { + return Nan::ThrowTypeError("Second argument must be a string"); + } + + mbgl::optional klass; + if (info.Length() == 4 && info[3]->IsString()) { + klass = std::string(*Nan::Utf8String(info[3])); + } + + mbgl::optional error = setPaintProperty(*layer, *Nan::Utf8String(info[1]), info[2], klass); + if (error) { + return Nan::ThrowTypeError(error->message); + } + + nodeMap->map->update(mbgl::Update::RecalculateStyle); + info.GetReturnValue().SetUndefined(); } NAN_METHOD(NodeMap::SetFilter) { + using namespace mbgl::style; + using namespace mbgl::style::conversion; + auto nodeMap = Nan::ObjectWrap::Unwrap(info.Holder()); if (!nodeMap->map) return Nan::ThrowError(releasedMessage()); @@ -544,23 +622,39 @@ NAN_METHOD(NodeMap::SetFilter) { return Nan::ThrowTypeError("layer not found"); } - mbgl::style::Filter filter; + Filter filter; if (!info[1]->IsNull() && !info[1]->IsUndefined()) { - mbgl::style::conversion::Result converted - = mbgl::style::conversion::convertFilter(info[1]); - if (converted.is()) { - Nan::ThrowTypeError(converted.get().message); + Result converted = convert(info[1]); + if (!converted) { + Nan::ThrowTypeError(converted.error().message); return; } - filter = std::move(converted.get()); + filter = std::move(*converted); } - if (!setFilter(*layer, filter)) { + if (layer->is()) { + layer->as()->setFilter(filter); + info.GetReturnValue().SetUndefined(); + return; + } + if (layer->is()) { + layer->as()->setFilter(filter); + info.GetReturnValue().SetUndefined(); + return; + } + if (layer->is()) { + layer->as()->setFilter(filter); + info.GetReturnValue().SetUndefined(); + return; + } + if (layer->is()) { + layer->as()->setFilter(filter); + info.GetReturnValue().SetUndefined(); return; } - info.GetReturnValue().SetUndefined(); + Nan::ThrowTypeError("layer doesn't support filters"); } NAN_METHOD(NodeMap::DumpDebugLogs) { diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp index 58773e33dac..d64d58013da 100644 --- a/platform/node/src/node_map.hpp +++ b/platform/node/src/node_map.hpp @@ -1,7 +1,5 @@ #pragma once -#include "node_style.hpp" - #include #include #include @@ -28,14 +26,14 @@ class NodeMap : public Nan::ObjectWrap, static NAN_METHOD(Render); static NAN_METHOD(Release); static NAN_METHOD(AddClass); + static NAN_METHOD(AddSource); + static NAN_METHOD(AddLayer); static NAN_METHOD(SetLayoutProperty); static NAN_METHOD(SetPaintProperty); static NAN_METHOD(SetFilter); static NAN_METHOD(DumpDebugLogs); static NAN_METHOD(QueryRenderedFeatures); - static void setProperty(const Nan::FunctionCallbackInfo&, const PropertySetters&); - void startRender(RenderOptions options); void renderFinished(); diff --git a/platform/node/src/node_style.hpp b/platform/node/src/node_style.hpp deleted file mode 100644 index 9befd00d10e..00000000000 --- a/platform/node/src/node_style.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "node_conversion.hpp" - -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wshadow" -#include -#pragma GCC diagnostic pop - -#include -#include -#include - -namespace node_mbgl { - -using PropertySetter = std::function&)>; -using PropertySetters = std::unordered_map; - -template -PropertySetter makePropertySetter(void (L::*setter)(mbgl::style::PropertyValue)) { - return [setter] (mbgl::style::Layer& layer, const v8::Local& value) { - L* typedLayer = layer.as(); - if (!typedLayer) { - Nan::ThrowTypeError("layer doesn't support this property"); - return false; - } - - if (value->IsNull() || value->IsUndefined()) { - (typedLayer->*setter)(mbgl::style::PropertyValue()); - return true; - } - - mbgl::style::conversion::Result> typedValue - = mbgl::style::conversion::convertPropertyValue(value); - if (typedValue.template is()) { - Nan::ThrowTypeError(typedValue.template get().message); - return false; - } - - (typedLayer->*setter)(typedValue.template get>()); - return true; - }; -} - -inline bool setVisibility(mbgl::style::Layer& layer, const v8::Local& value) { - if (value->IsNull() || value->IsUndefined()) { - layer.setVisibility(mbgl::style::VisibilityType::Visible); - return true; - } - - if (!value->IsString()) { - Nan::ThrowTypeError("visibility value must be \"visible\" or \"none\""); - return false; - } - - layer.setVisibility(std::string(*Nan::Utf8String(value)) == "none" - ? mbgl::style::VisibilityType::None - : mbgl::style::VisibilityType::Visible); - - return true; -} - -} diff --git a/platform/node/src/node_style_properties.hpp b/platform/node/src/node_style_properties.hpp deleted file mode 100644 index 0e3100207ae..00000000000 --- a/platform/node/src/node_style_properties.hpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "node_style.hpp" - -#include -#include -#include -#include -#include -#include - -namespace node_mbgl { - -inline PropertySetters makeLayoutPropertySetters() { - using namespace mbgl::style; - PropertySetters result; - - result["visibility"] = &setVisibility; - - - result["line-cap"] = makePropertySetter(&LineLayer::setLineCap); - result["line-join"] = makePropertySetter(&LineLayer::setLineJoin); - result["line-miter-limit"] = makePropertySetter(&LineLayer::setLineMiterLimit); - result["line-round-limit"] = makePropertySetter(&LineLayer::setLineRoundLimit); - - result["symbol-placement"] = makePropertySetter(&SymbolLayer::setSymbolPlacement); - result["symbol-spacing"] = makePropertySetter(&SymbolLayer::setSymbolSpacing); - result["symbol-avoid-edges"] = makePropertySetter(&SymbolLayer::setSymbolAvoidEdges); - result["icon-allow-overlap"] = makePropertySetter(&SymbolLayer::setIconAllowOverlap); - result["icon-ignore-placement"] = makePropertySetter(&SymbolLayer::setIconIgnorePlacement); - result["icon-optional"] = makePropertySetter(&SymbolLayer::setIconOptional); - result["icon-rotation-alignment"] = makePropertySetter(&SymbolLayer::setIconRotationAlignment); - result["icon-size"] = makePropertySetter(&SymbolLayer::setIconSize); - result["icon-text-fit"] = makePropertySetter(&SymbolLayer::setIconTextFit); - result["icon-text-fit-padding"] = makePropertySetter(&SymbolLayer::setIconTextFitPadding); - result["icon-image"] = makePropertySetter(&SymbolLayer::setIconImage); - result["icon-rotate"] = makePropertySetter(&SymbolLayer::setIconRotate); - result["icon-padding"] = makePropertySetter(&SymbolLayer::setIconPadding); - result["icon-keep-upright"] = makePropertySetter(&SymbolLayer::setIconKeepUpright); - result["icon-offset"] = makePropertySetter(&SymbolLayer::setIconOffset); - result["text-pitch-alignment"] = makePropertySetter(&SymbolLayer::setTextPitchAlignment); - result["text-rotation-alignment"] = makePropertySetter(&SymbolLayer::setTextRotationAlignment); - result["text-field"] = makePropertySetter(&SymbolLayer::setTextField); - result["text-font"] = makePropertySetter(&SymbolLayer::setTextFont); - result["text-size"] = makePropertySetter(&SymbolLayer::setTextSize); - result["text-max-width"] = makePropertySetter(&SymbolLayer::setTextMaxWidth); - result["text-line-height"] = makePropertySetter(&SymbolLayer::setTextLineHeight); - result["text-letter-spacing"] = makePropertySetter(&SymbolLayer::setTextLetterSpacing); - result["text-justify"] = makePropertySetter(&SymbolLayer::setTextJustify); - result["text-anchor"] = makePropertySetter(&SymbolLayer::setTextAnchor); - result["text-max-angle"] = makePropertySetter(&SymbolLayer::setTextMaxAngle); - result["text-rotate"] = makePropertySetter(&SymbolLayer::setTextRotate); - result["text-padding"] = makePropertySetter(&SymbolLayer::setTextPadding); - result["text-keep-upright"] = makePropertySetter(&SymbolLayer::setTextKeepUpright); - result["text-transform"] = makePropertySetter(&SymbolLayer::setTextTransform); - result["text-offset"] = makePropertySetter(&SymbolLayer::setTextOffset); - result["text-allow-overlap"] = makePropertySetter(&SymbolLayer::setTextAllowOverlap); - result["text-ignore-placement"] = makePropertySetter(&SymbolLayer::setTextIgnorePlacement); - result["text-optional"] = makePropertySetter(&SymbolLayer::setTextOptional); - - - - - return result; -} - -inline PropertySetters makePaintPropertySetters() { - using namespace mbgl::style; - PropertySetters result; - - result["fill-antialias"] = makePropertySetter(&FillLayer::setFillAntialias); - result["fill-opacity"] = makePropertySetter(&FillLayer::setFillOpacity); - result["fill-color"] = makePropertySetter(&FillLayer::setFillColor); - result["fill-outline-color"] = makePropertySetter(&FillLayer::setFillOutlineColor); - result["fill-translate"] = makePropertySetter(&FillLayer::setFillTranslate); - result["fill-translate-anchor"] = makePropertySetter(&FillLayer::setFillTranslateAnchor); - result["fill-pattern"] = makePropertySetter(&FillLayer::setFillPattern); - - result["line-opacity"] = makePropertySetter(&LineLayer::setLineOpacity); - result["line-color"] = makePropertySetter(&LineLayer::setLineColor); - result["line-translate"] = makePropertySetter(&LineLayer::setLineTranslate); - result["line-translate-anchor"] = makePropertySetter(&LineLayer::setLineTranslateAnchor); - result["line-width"] = makePropertySetter(&LineLayer::setLineWidth); - result["line-gap-width"] = makePropertySetter(&LineLayer::setLineGapWidth); - result["line-offset"] = makePropertySetter(&LineLayer::setLineOffset); - result["line-blur"] = makePropertySetter(&LineLayer::setLineBlur); - result["line-dasharray"] = makePropertySetter(&LineLayer::setLineDasharray); - result["line-pattern"] = makePropertySetter(&LineLayer::setLinePattern); - - result["icon-opacity"] = makePropertySetter(&SymbolLayer::setIconOpacity); - result["icon-color"] = makePropertySetter(&SymbolLayer::setIconColor); - result["icon-halo-color"] = makePropertySetter(&SymbolLayer::setIconHaloColor); - result["icon-halo-width"] = makePropertySetter(&SymbolLayer::setIconHaloWidth); - result["icon-halo-blur"] = makePropertySetter(&SymbolLayer::setIconHaloBlur); - result["icon-translate"] = makePropertySetter(&SymbolLayer::setIconTranslate); - result["icon-translate-anchor"] = makePropertySetter(&SymbolLayer::setIconTranslateAnchor); - result["text-opacity"] = makePropertySetter(&SymbolLayer::setTextOpacity); - result["text-color"] = makePropertySetter(&SymbolLayer::setTextColor); - result["text-halo-color"] = makePropertySetter(&SymbolLayer::setTextHaloColor); - result["text-halo-width"] = makePropertySetter(&SymbolLayer::setTextHaloWidth); - result["text-halo-blur"] = makePropertySetter(&SymbolLayer::setTextHaloBlur); - result["text-translate"] = makePropertySetter(&SymbolLayer::setTextTranslate); - result["text-translate-anchor"] = makePropertySetter(&SymbolLayer::setTextTranslateAnchor); - - result["circle-radius"] = makePropertySetter(&CircleLayer::setCircleRadius); - result["circle-color"] = makePropertySetter(&CircleLayer::setCircleColor); - result["circle-blur"] = makePropertySetter(&CircleLayer::setCircleBlur); - result["circle-opacity"] = makePropertySetter(&CircleLayer::setCircleOpacity); - result["circle-translate"] = makePropertySetter(&CircleLayer::setCircleTranslate); - result["circle-translate-anchor"] = makePropertySetter(&CircleLayer::setCircleTranslateAnchor); - - result["raster-opacity"] = makePropertySetter(&RasterLayer::setRasterOpacity); - result["raster-hue-rotate"] = makePropertySetter(&RasterLayer::setRasterHueRotate); - result["raster-brightness-min"] = makePropertySetter(&RasterLayer::setRasterBrightnessMin); - result["raster-brightness-max"] = makePropertySetter(&RasterLayer::setRasterBrightnessMax); - result["raster-saturation"] = makePropertySetter(&RasterLayer::setRasterSaturation); - result["raster-contrast"] = makePropertySetter(&RasterLayer::setRasterContrast); - result["raster-fade-duration"] = makePropertySetter(&RasterLayer::setRasterFadeDuration); - - result["background-color"] = makePropertySetter(&BackgroundLayer::setBackgroundColor); - result["background-pattern"] = makePropertySetter(&BackgroundLayer::setBackgroundPattern); - result["background-opacity"] = makePropertySetter(&BackgroundLayer::setBackgroundOpacity); - - return result; -} - -inline bool setFilter(mbgl::style::Layer& layer, const mbgl::style::Filter& filter) { - using namespace mbgl::style; - - if (layer.is()) { - layer.as()->setFilter(filter); - return true; - } - if (layer.is()) { - layer.as()->setFilter(filter); - return true; - } - if (layer.is()) { - layer.as()->setFilter(filter); - return true; - } - if (layer.is()) { - layer.as()->setFilter(filter); - return true; - } - - Nan::ThrowTypeError("layer doesn't support filters"); - return false; -} - -} diff --git a/platform/node/src/node_style_properties.hpp.ejs b/platform/node/src/node_style_properties.hpp.ejs deleted file mode 100644 index bfd3f74ca5f..00000000000 --- a/platform/node/src/node_style_properties.hpp.ejs +++ /dev/null @@ -1,53 +0,0 @@ -#include "node_style.hpp" - -<% for (const layer of locals.layers) { -%> -#include _layer.hpp> -<% } -%> - -namespace node_mbgl { - -inline PropertySetters makeLayoutPropertySetters() { - using namespace mbgl::style; - PropertySetters result; - - result["visibility"] = &setVisibility; - -<% for (const layer of locals.layers) { -%> -<% for (const property of layer.layoutProperties) { -%> - result["<%- property.name %>"] = makePropertySetter(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>); -<% } -%> - -<% } -%> - return result; -} - -inline PropertySetters makePaintPropertySetters() { - using namespace mbgl::style; - PropertySetters result; - -<% for (const layer of locals.layers) { -%> -<% for (const property of layer.paintProperties) { -%> - result["<%- property.name %>"] = makePropertySetter(&<%- camelize(layer.type) %>Layer::set<%- camelize(property.name) %>); -<% } -%> - -<% } -%> - return result; -} - -inline bool setFilter(mbgl::style::Layer& layer, const mbgl::style::Filter& filter) { - using namespace mbgl::style; - -<% for (const layer of locals.layers) { -%> -<% if (layer.type !== 'raster' && layer.type !== 'background' && layer.type !== 'custom') { -%> - if (layer.is<<%- camelize(layer.type) %>Layer>()) { - layer.as<<%- camelize(layer.type) %>Layer>()->setFilter(filter); - return true; - } -<% } -%> -<% } -%> - - Nan::ThrowTypeError("layer doesn't support filters"); - return false; -} - -} diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js index 7859c65a0e7..642da1174b3 100644 --- a/scripts/generate-style-code.js +++ b/scripts/generate-style-code.js @@ -111,5 +111,5 @@ for (const layer of layers) { fs.writeFileSync(`src/mbgl/style/layers/${layer.type}_layer_properties.cpp`, propertiesCpp(layer)); } -const nodeStyleCpp = ejs.compile(fs.readFileSync('platform/node/src/node_style_properties.hpp.ejs', 'utf8'), {strict: true}); -fs.writeFileSync('platform/node/src/node_style_properties.hpp', nodeStyleCpp({layers: layers})); +const propertySettersHpp = ejs.compile(fs.readFileSync('include/mbgl/style/conversion/make_property_setters.hpp.ejs', 'utf8'), {strict: true}); +fs.writeFileSync('include/mbgl/style/conversion/make_property_setters.hpp', propertySettersHpp({layers: layers})); diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index dd2467e34f4..7e1984a3c80 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -157,9 +157,9 @@ void AnnotationManager::updateStyle(Style& style) { source->baseImpl->enabled = true; style.addSource(std::move(source)); - std::unique_ptr layer = std::make_unique(PointLayerID); + std::unique_ptr layer = std::make_unique(PointLayerID, SourceID); - layer->setSource(SourceID, PointLayerID); + layer->setSourceLayer(PointLayerID); layer->setIconImage({"{sprite}"}); layer->setIconAllowOverlap(true); diff --git a/src/mbgl/annotation/fill_annotation_impl.cpp b/src/mbgl/annotation/fill_annotation_impl.cpp index cbd76ede97f..8146c68a533 100644 --- a/src/mbgl/annotation/fill_annotation_impl.cpp +++ b/src/mbgl/annotation/fill_annotation_impl.cpp @@ -16,9 +16,8 @@ void FillAnnotationImpl::updateStyle(Style& style) const { if (style.getLayer(layerID)) return; - std::unique_ptr layer = std::make_unique(layerID); - layer->setSource(AnnotationManager::SourceID, layerID); - + std::unique_ptr layer = std::make_unique(layerID, AnnotationManager::SourceID); + layer->setSourceLayer(layerID); layer->setFillOpacity(annotation.opacity); layer->setFillColor(annotation.color); layer->setFillOutlineColor(annotation.outlineColor); diff --git a/src/mbgl/annotation/line_annotation_impl.cpp b/src/mbgl/annotation/line_annotation_impl.cpp index e689c3240d8..bc7b8df50e0 100644 --- a/src/mbgl/annotation/line_annotation_impl.cpp +++ b/src/mbgl/annotation/line_annotation_impl.cpp @@ -16,8 +16,8 @@ void LineAnnotationImpl::updateStyle(Style& style) const { if (style.getLayer(layerID)) return; - std::unique_ptr layer = std::make_unique(layerID); - layer->setSource(AnnotationManager::SourceID, layerID); + std::unique_ptr layer = std::make_unique(layerID, AnnotationManager::SourceID); + layer->setSourceLayer(layerID); layer->setLineJoin(LineJoinType::Round); layer->setLineOpacity(annotation.opacity); layer->setLineWidth(annotation.width); diff --git a/src/mbgl/annotation/style_sourced_annotation_impl.cpp b/src/mbgl/annotation/style_sourced_annotation_impl.cpp index d8280146063..d3212da12d8 100644 --- a/src/mbgl/annotation/style_sourced_annotation_impl.cpp +++ b/src/mbgl/annotation/style_sourced_annotation_impl.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -23,13 +24,13 @@ void StyleSourcedAnnotationImpl::updateStyle(Style& style) const { return; if (sourceLayer->is()) { - std::unique_ptr layer = sourceLayer->copy(layerID, ""); - layer->as()->setSource(AnnotationManager::SourceID, layerID); + std::unique_ptr layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID); + layer->as()->setSourceLayer(layerID); layer->as()->setVisibility(VisibilityType::Visible); style.addLayer(std::move(layer), sourceLayer->getID()); } else if (sourceLayer->is()) { - std::unique_ptr layer = sourceLayer->copy(layerID, ""); - layer->as()->setSource(AnnotationManager::SourceID, layerID); + std::unique_ptr layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID); + layer->as()->setSourceLayer(layerID); layer->as()->setVisibility(VisibilityType::Visible); style.addLayer(std::move(layer), sourceLayer->getID()); } diff --git a/src/mbgl/style/conversion.cpp b/src/mbgl/style/conversion.cpp deleted file mode 100644 index e863e285c45..00000000000 --- a/src/mbgl/style/conversion.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -namespace mbgl { -namespace style { -namespace conversion { - -Result normalizeFilterValue(const std::string& key, const optional& value) { - if (!value) { - return Error { "filter expression value must be a boolean, number, or string" }; - } else if (key != "$type") { - return *value; - } else if (*value == std::string("Point")) { - return Value(uint64_t(FeatureType::Point)); - } else if (*value == std::string("LineString")) { - return Value(uint64_t(FeatureType::LineString)); - } else if (*value == std::string("Polygon")) { - return Value(uint64_t(FeatureType::Polygon)); - } else { - return Error { "value for $type filter must be Point, LineString, or Polygon" }; - } -} - -} // namespace conversion -} // namespace style -} // namespace mbgl diff --git a/src/mbgl/style/layer.cpp b/src/mbgl/style/layer.cpp index 342699a2c9b..6eff64ae09b 100644 --- a/src/mbgl/style/layer.cpp +++ b/src/mbgl/style/layer.cpp @@ -38,13 +38,5 @@ void Layer::setMaxZoom(float maxZoom) const { baseImpl->maxZoom = maxZoom; } -std::unique_ptr Layer::copy(const std::string& id, - const std::string& ref) const { - std::unique_ptr result = baseImpl->clone(); - result->baseImpl->id = id; - result->baseImpl->ref = ref; - return result; -} - } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/layer_impl.cpp b/src/mbgl/style/layer_impl.cpp index 74cc80d2531..b345297027b 100644 --- a/src/mbgl/style/layer_impl.cpp +++ b/src/mbgl/style/layer_impl.cpp @@ -3,6 +3,16 @@ namespace mbgl { namespace style { +std::unique_ptr Layer::Impl::copy(const std::string& id_, + const std::string& ref_, + const std::string& source_) const { + std::unique_ptr result = clone(); + result->baseImpl->id = id_; + result->baseImpl->ref = ref_; + result->baseImpl->source = source_; + return result; +} + const std::string& Layer::Impl::bucketName() const { return ref.empty() ? id : ref; } diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp index 34fc6b27358..d2bf866e8e1 100644 --- a/src/mbgl/style/layer_impl.hpp +++ b/src/mbgl/style/layer_impl.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -37,11 +36,17 @@ class Layer::Impl { public: virtual ~Impl() = default; + // Create a new layer with the specified `id`, `ref`, and `sourceID`. All other properties + // are copied from this layer. + std::unique_ptr copy(const std::string& id, + const std::string& ref, + const std::string& sourceID) const; + // Create an identical copy of this layer. virtual std::unique_ptr clone() const = 0; - virtual void parseLayout(const JSValue& value) = 0; - virtual void parsePaints(const JSValue& value) = 0; + // Create a layer, copying all properties except id, ref, and paint properties from this layer. + virtual std::unique_ptr cloneRef(const std::string& id) const = 0; // If the layer has a ref, the ref. Otherwise, the id. const std::string& bucketName() const; diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp index aeb40675030..42cd76d01f3 100644 --- a/src/mbgl/style/layers/background_layer.cpp +++ b/src/mbgl/style/layers/background_layer.cpp @@ -23,6 +23,14 @@ std::unique_ptr BackgroundLayer::Impl::clone() const { return std::make_unique(*this); } +std::unique_ptr BackgroundLayer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = BackgroundPaintProperties(); + return std::move(result); +} + // Layout properties @@ -33,24 +41,24 @@ PropertyValue BackgroundLayer::getBackgroundColor() const { return impl->paint.backgroundColor.get(); } -void BackgroundLayer::setBackgroundColor(PropertyValue value) { - impl->paint.backgroundColor.set(value); +void BackgroundLayer::setBackgroundColor(PropertyValue value, const optional& klass) { + impl->paint.backgroundColor.set(value, klass); } PropertyValue BackgroundLayer::getBackgroundPattern() const { return impl->paint.backgroundPattern.get(); } -void BackgroundLayer::setBackgroundPattern(PropertyValue value) { - impl->paint.backgroundPattern.set(value); +void BackgroundLayer::setBackgroundPattern(PropertyValue value, const optional& klass) { + impl->paint.backgroundPattern.set(value, klass); } PropertyValue BackgroundLayer::getBackgroundOpacity() const { return impl->paint.backgroundOpacity.get(); } -void BackgroundLayer::setBackgroundOpacity(PropertyValue value) { - impl->paint.backgroundOpacity.set(value); +void BackgroundLayer::setBackgroundOpacity(PropertyValue value, const optional& klass) { + impl->paint.backgroundOpacity.set(value, klass); } } // namespace style diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp index 0c09c5d1582..ea389b828e2 100644 --- a/src/mbgl/style/layers/background_layer_impl.cpp +++ b/src/mbgl/style/layers/background_layer_impl.cpp @@ -4,10 +4,6 @@ namespace mbgl { namespace style { -void BackgroundLayer::Impl::parsePaints(const JSValue& layer) { - paint.parse(layer); -} - void BackgroundLayer::Impl::cascade(const CascadeParameters& parameters) { paint.cascade(parameters); } diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp index 19e2a062a41..abbb740f427 100644 --- a/src/mbgl/style/layers/background_layer_impl.hpp +++ b/src/mbgl/style/layers/background_layer_impl.hpp @@ -10,9 +10,7 @@ namespace style { class BackgroundLayer::Impl : public Layer::Impl { public: std::unique_ptr clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; + std::unique_ptr cloneRef(const std::string& id) const override; void cascade(const CascadeParameters&) override; bool recalculate(const CalculationParameters&) override; diff --git a/src/mbgl/style/layers/background_layer_properties.cpp b/src/mbgl/style/layers/background_layer_properties.cpp index a20cedf12ce..558093a2555 100644 --- a/src/mbgl/style/layers/background_layer_properties.cpp +++ b/src/mbgl/style/layers/background_layer_properties.cpp @@ -5,12 +5,6 @@ namespace mbgl { namespace style { -void BackgroundPaintProperties::parse(const JSValue& value) { - backgroundColor.parse("background-color", value); - backgroundPattern.parse("background-pattern", value); - backgroundOpacity.parse("background-opacity", value); -} - void BackgroundPaintProperties::cascade(const CascadeParameters& parameters) { backgroundColor.cascade(parameters); backgroundPattern.cascade(parameters); diff --git a/src/mbgl/style/layers/background_layer_properties.hpp b/src/mbgl/style/layers/background_layer_properties.hpp index 60e4b226846..6c5a7c57cac 100644 --- a/src/mbgl/style/layers/background_layer_properties.hpp +++ b/src/mbgl/style/layers/background_layer_properties.hpp @@ -2,9 +2,9 @@ #pragma once +#include #include #include -#include namespace mbgl { namespace style { @@ -14,7 +14,6 @@ class CalculationParameters; class BackgroundPaintProperties { public: - void parse(const JSValue&); void cascade(const CascadeParameters&); bool recalculate(const CalculationParameters&); diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp index bdfbf629e68..a47d7235486 100644 --- a/src/mbgl/style/layers/circle_layer.cpp +++ b/src/mbgl/style/layers/circle_layer.cpp @@ -6,10 +6,11 @@ namespace mbgl { namespace style { -CircleLayer::CircleLayer(const std::string& layerID) +CircleLayer::CircleLayer(const std::string& layerID, const std::string& sourceID) : Layer(Type::Circle, std::make_unique()) , impl(static_cast(baseImpl.get())) { impl->id = layerID; + impl->source = sourceID; } CircleLayer::CircleLayer(const Impl& other) @@ -23,17 +24,24 @@ std::unique_ptr CircleLayer::Impl::clone() const { return std::make_unique(*this); } -// Source - -void CircleLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { - impl->source = sourceID; - impl->sourceLayer = sourceLayer; +std::unique_ptr CircleLayer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = CirclePaintProperties(); + return std::move(result); } +// Source + const std::string& CircleLayer::getSourceID() const { return impl->source; } +void CircleLayer::setSourceLayer(const std::string& sourceLayer) { + impl->sourceLayer = sourceLayer; +} + const std::string& CircleLayer::getSourceLayer() const { return impl->sourceLayer; } @@ -57,48 +65,48 @@ PropertyValue CircleLayer::getCircleRadius() const { return impl->paint.circleRadius.get(); } -void CircleLayer::setCircleRadius(PropertyValue value) { - impl->paint.circleRadius.set(value); +void CircleLayer::setCircleRadius(PropertyValue value, const optional& klass) { + impl->paint.circleRadius.set(value, klass); } PropertyValue CircleLayer::getCircleColor() const { return impl->paint.circleColor.get(); } -void CircleLayer::setCircleColor(PropertyValue value) { - impl->paint.circleColor.set(value); +void CircleLayer::setCircleColor(PropertyValue value, const optional& klass) { + impl->paint.circleColor.set(value, klass); } PropertyValue CircleLayer::getCircleBlur() const { return impl->paint.circleBlur.get(); } -void CircleLayer::setCircleBlur(PropertyValue value) { - impl->paint.circleBlur.set(value); +void CircleLayer::setCircleBlur(PropertyValue value, const optional& klass) { + impl->paint.circleBlur.set(value, klass); } PropertyValue CircleLayer::getCircleOpacity() const { return impl->paint.circleOpacity.get(); } -void CircleLayer::setCircleOpacity(PropertyValue value) { - impl->paint.circleOpacity.set(value); +void CircleLayer::setCircleOpacity(PropertyValue value, const optional& klass) { + impl->paint.circleOpacity.set(value, klass); } PropertyValue> CircleLayer::getCircleTranslate() const { return impl->paint.circleTranslate.get(); } -void CircleLayer::setCircleTranslate(PropertyValue> value) { - impl->paint.circleTranslate.set(value); +void CircleLayer::setCircleTranslate(PropertyValue> value, const optional& klass) { + impl->paint.circleTranslate.set(value, klass); } PropertyValue CircleLayer::getCircleTranslateAnchor() const { return impl->paint.circleTranslateAnchor.get(); } -void CircleLayer::setCircleTranslateAnchor(PropertyValue value) { - impl->paint.circleTranslateAnchor.set(value); +void CircleLayer::setCircleTranslateAnchor(PropertyValue value, const optional& klass) { + impl->paint.circleTranslateAnchor.set(value, klass); } } // namespace style diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp index d64759e7435..e08d9df1469 100644 --- a/src/mbgl/style/layers/circle_layer_impl.cpp +++ b/src/mbgl/style/layers/circle_layer_impl.cpp @@ -8,10 +8,6 @@ namespace mbgl { namespace style { -void CircleLayer::Impl::parsePaints(const JSValue& layer) { - paint.parse(layer); -} - void CircleLayer::Impl::cascade(const CascadeParameters& parameters) { paint.cascade(parameters); } diff --git a/src/mbgl/style/layers/circle_layer_impl.hpp b/src/mbgl/style/layers/circle_layer_impl.hpp index 463f3ca18d1..555691b6b4f 100644 --- a/src/mbgl/style/layers/circle_layer_impl.hpp +++ b/src/mbgl/style/layers/circle_layer_impl.hpp @@ -10,9 +10,7 @@ namespace style { class CircleLayer::Impl : public Layer::Impl { public: std::unique_ptr clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; + std::unique_ptr cloneRef(const std::string& id) const override; void cascade(const CascadeParameters&) override; bool recalculate(const CalculationParameters&) override; diff --git a/src/mbgl/style/layers/circle_layer_properties.cpp b/src/mbgl/style/layers/circle_layer_properties.cpp index b21df1e2d0d..045c73ba63e 100644 --- a/src/mbgl/style/layers/circle_layer_properties.cpp +++ b/src/mbgl/style/layers/circle_layer_properties.cpp @@ -5,15 +5,6 @@ namespace mbgl { namespace style { -void CirclePaintProperties::parse(const JSValue& value) { - circleRadius.parse("circle-radius", value); - circleColor.parse("circle-color", value); - circleBlur.parse("circle-blur", value); - circleOpacity.parse("circle-opacity", value); - circleTranslate.parse("circle-translate", value); - circleTranslateAnchor.parse("circle-translate-anchor", value); -} - void CirclePaintProperties::cascade(const CascadeParameters& parameters) { circleRadius.cascade(parameters); circleColor.cascade(parameters); diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp index 35c0f1ad519..40d37dc3922 100644 --- a/src/mbgl/style/layers/circle_layer_properties.hpp +++ b/src/mbgl/style/layers/circle_layer_properties.hpp @@ -2,9 +2,9 @@ #pragma once +#include #include #include -#include namespace mbgl { namespace style { @@ -14,7 +14,6 @@ class CalculationParameters; class CirclePaintProperties { public: - void parse(const JSValue&); void cascade(const CascadeParameters&); bool recalculate(const CalculationParameters&); diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp index 214d4ce663a..a0686e353c6 100644 --- a/src/mbgl/style/layers/custom_layer_impl.cpp +++ b/src/mbgl/style/layers/custom_layer_impl.cpp @@ -33,6 +33,11 @@ std::unique_ptr CustomLayer::Impl::clone() const { return std::make_unique(*this); } +std::unique_ptr CustomLayer::Impl::cloneRef(const std::string&) const { + assert(false); + return std::make_unique(*this); +} + void CustomLayer::Impl::initialize() { assert(initializeFn); initializeFn(context); diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp index 00e576b6a3c..ffa892ddf81 100644 --- a/src/mbgl/style/layers/custom_layer_impl.hpp +++ b/src/mbgl/style/layers/custom_layer_impl.hpp @@ -25,9 +25,7 @@ class CustomLayer::Impl : public Layer::Impl { private: std::unique_ptr clone() const override; - - void parseLayout(const JSValue&) final {} - void parsePaints(const JSValue&) final {} + std::unique_ptr cloneRef(const std::string& id) const override; void cascade(const CascadeParameters&) final {} bool recalculate(const CalculationParameters&) final; diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp index 1deaabb5ef0..44894aff335 100644 --- a/src/mbgl/style/layers/fill_layer.cpp +++ b/src/mbgl/style/layers/fill_layer.cpp @@ -6,10 +6,11 @@ namespace mbgl { namespace style { -FillLayer::FillLayer(const std::string& layerID) +FillLayer::FillLayer(const std::string& layerID, const std::string& sourceID) : Layer(Type::Fill, std::make_unique()) , impl(static_cast(baseImpl.get())) { impl->id = layerID; + impl->source = sourceID; } FillLayer::FillLayer(const Impl& other) @@ -23,17 +24,24 @@ std::unique_ptr FillLayer::Impl::clone() const { return std::make_unique(*this); } -// Source - -void FillLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { - impl->source = sourceID; - impl->sourceLayer = sourceLayer; +std::unique_ptr FillLayer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = FillPaintProperties(); + return std::move(result); } +// Source + const std::string& FillLayer::getSourceID() const { return impl->source; } +void FillLayer::setSourceLayer(const std::string& sourceLayer) { + impl->sourceLayer = sourceLayer; +} + const std::string& FillLayer::getSourceLayer() const { return impl->sourceLayer; } @@ -57,56 +65,56 @@ PropertyValue FillLayer::getFillAntialias() const { return impl->paint.fillAntialias.get(); } -void FillLayer::setFillAntialias(PropertyValue value) { - impl->paint.fillAntialias.set(value); +void FillLayer::setFillAntialias(PropertyValue value, const optional& klass) { + impl->paint.fillAntialias.set(value, klass); } PropertyValue FillLayer::getFillOpacity() const { return impl->paint.fillOpacity.get(); } -void FillLayer::setFillOpacity(PropertyValue value) { - impl->paint.fillOpacity.set(value); +void FillLayer::setFillOpacity(PropertyValue value, const optional& klass) { + impl->paint.fillOpacity.set(value, klass); } PropertyValue FillLayer::getFillColor() const { return impl->paint.fillColor.get(); } -void FillLayer::setFillColor(PropertyValue value) { - impl->paint.fillColor.set(value); +void FillLayer::setFillColor(PropertyValue value, const optional& klass) { + impl->paint.fillColor.set(value, klass); } PropertyValue FillLayer::getFillOutlineColor() const { return impl->paint.fillOutlineColor.get(); } -void FillLayer::setFillOutlineColor(PropertyValue value) { - impl->paint.fillOutlineColor.set(value); +void FillLayer::setFillOutlineColor(PropertyValue value, const optional& klass) { + impl->paint.fillOutlineColor.set(value, klass); } PropertyValue> FillLayer::getFillTranslate() const { return impl->paint.fillTranslate.get(); } -void FillLayer::setFillTranslate(PropertyValue> value) { - impl->paint.fillTranslate.set(value); +void FillLayer::setFillTranslate(PropertyValue> value, const optional& klass) { + impl->paint.fillTranslate.set(value, klass); } PropertyValue FillLayer::getFillTranslateAnchor() const { return impl->paint.fillTranslateAnchor.get(); } -void FillLayer::setFillTranslateAnchor(PropertyValue value) { - impl->paint.fillTranslateAnchor.set(value); +void FillLayer::setFillTranslateAnchor(PropertyValue value, const optional& klass) { + impl->paint.fillTranslateAnchor.set(value, klass); } PropertyValue FillLayer::getFillPattern() const { return impl->paint.fillPattern.get(); } -void FillLayer::setFillPattern(PropertyValue value) { - impl->paint.fillPattern.set(value); +void FillLayer::setFillPattern(PropertyValue value, const optional& klass) { + impl->paint.fillPattern.set(value, klass); } } // namespace style diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp index 3d847127c92..29923125144 100644 --- a/src/mbgl/style/layers/fill_layer_impl.cpp +++ b/src/mbgl/style/layers/fill_layer_impl.cpp @@ -8,10 +8,6 @@ namespace mbgl { namespace style { -void FillLayer::Impl::parsePaints(const JSValue& layer) { - paint.parse(layer); -} - void FillLayer::Impl::cascade(const CascadeParameters& parameters) { paint.cascade(parameters); } diff --git a/src/mbgl/style/layers/fill_layer_impl.hpp b/src/mbgl/style/layers/fill_layer_impl.hpp index a37dd76ace2..fc6578ecd19 100644 --- a/src/mbgl/style/layers/fill_layer_impl.hpp +++ b/src/mbgl/style/layers/fill_layer_impl.hpp @@ -10,9 +10,7 @@ namespace style { class FillLayer::Impl : public Layer::Impl { public: std::unique_ptr clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; + std::unique_ptr cloneRef(const std::string& id) const override; void cascade(const CascadeParameters&) override; bool recalculate(const CalculationParameters&) override; diff --git a/src/mbgl/style/layers/fill_layer_properties.cpp b/src/mbgl/style/layers/fill_layer_properties.cpp index a4714689f9c..9a55cbc1452 100644 --- a/src/mbgl/style/layers/fill_layer_properties.cpp +++ b/src/mbgl/style/layers/fill_layer_properties.cpp @@ -5,16 +5,6 @@ namespace mbgl { namespace style { -void FillPaintProperties::parse(const JSValue& value) { - fillAntialias.parse("fill-antialias", value); - fillOpacity.parse("fill-opacity", value); - fillColor.parse("fill-color", value); - fillOutlineColor.parse("fill-outline-color", value); - fillTranslate.parse("fill-translate", value); - fillTranslateAnchor.parse("fill-translate-anchor", value); - fillPattern.parse("fill-pattern", value); -} - void FillPaintProperties::cascade(const CascadeParameters& parameters) { fillAntialias.cascade(parameters); fillOpacity.cascade(parameters); diff --git a/src/mbgl/style/layers/fill_layer_properties.hpp b/src/mbgl/style/layers/fill_layer_properties.hpp index 09aa432d236..82981a9b646 100644 --- a/src/mbgl/style/layers/fill_layer_properties.hpp +++ b/src/mbgl/style/layers/fill_layer_properties.hpp @@ -2,9 +2,9 @@ #pragma once +#include #include #include -#include namespace mbgl { namespace style { @@ -14,7 +14,6 @@ class CalculationParameters; class FillPaintProperties { public: - void parse(const JSValue&); void cascade(const CascadeParameters&); bool recalculate(const CalculationParameters&); diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs index 633d6738045..017691c8ec0 100644 --- a/src/mbgl/style/layers/layer.cpp.ejs +++ b/src/mbgl/style/layers/layer.cpp.ejs @@ -11,11 +11,20 @@ namespace mbgl { namespace style { +<% if (type === 'background') { -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID) : Layer(Type::<%- camelize(type) %>, std::make_unique()) , impl(static_cast(baseImpl.get())) { impl->id = layerID; } +<% } else { -%> +<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID) + : Layer(Type::<%- camelize(type) %>, std::make_unique()) + , impl(static_cast(baseImpl.get())) { + impl->id = layerID; + impl->source = sourceID; +} +<% } -%> <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const Impl& other) : Layer(Type::<%- camelize(type) %>, std::make_unique(other)) @@ -28,28 +37,26 @@ std::unique_ptr <%- camelize(type) %>Layer::Impl::clone() const { return std::make_unique<<%- camelize(type) %>Layer>(*this); } -<% if (type === 'raster') { -%> -// Source - -void <%- camelize(type) %>Layer::setSource(const std::string& sourceID) { - impl->source = sourceID; +std::unique_ptr <%- camelize(type) %>Layer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique<<%- camelize(type) %>Layer>(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = <%- camelize(type) %>PaintProperties(); + return std::move(result); } +<% if (type !== 'background') { -%> +// Source + const std::string& <%- camelize(type) %>Layer::getSourceID() const { return impl->source; } -<% } else if (type !== 'background') { -%> -// Source -void <%- camelize(type) %>Layer::setSource(const std::string& sourceID, const std::string& sourceLayer) { - impl->source = sourceID; +<% if (type !== 'raster') { -%> +void <%- camelize(type) %>Layer::setSourceLayer(const std::string& sourceLayer) { impl->sourceLayer = sourceLayer; } -const std::string& <%- camelize(type) %>Layer::getSourceID() const { - return impl->source; -} - const std::string& <%- camelize(type) %>Layer::getSourceLayer() const { return impl->sourceLayer; } @@ -64,6 +71,7 @@ const Filter& <%- camelize(type) %>Layer::getFilter() const { return impl->filter; } <% } -%> +<% } -%> // Layout properties @@ -83,8 +91,8 @@ PropertyValue<<%- propertyType(property) %>> <%- camelize(type) %>Layer::get<%- return impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.get(); } -void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>> value) { - impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.set(value); +void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>> value, const optional& klass) { + impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.set(value, klass); } <% } -%> diff --git a/src/mbgl/style/layers/layer_properties.cpp.ejs b/src/mbgl/style/layers/layer_properties.cpp.ejs index 8fef8d29c40..b781a4a9d95 100644 --- a/src/mbgl/style/layers/layer_properties.cpp.ejs +++ b/src/mbgl/style/layers/layer_properties.cpp.ejs @@ -11,12 +11,6 @@ namespace mbgl { namespace style { <% if (layoutProperties.length) { -%> -void <%- camelize(type) %>LayoutProperties::parse(const JSValue& value) { -<% for (const property of layoutProperties) { -%> - <%- camelizeWithLeadingLowercase(property.name) %>.parse(<%- JSON.stringify(property.name) %>, value); -<% } -%> -} - void <%- camelize(type) %>LayoutProperties::recalculate(const CalculationParameters& parameters) { <% for (const property of layoutProperties) { -%> <%- camelizeWithLeadingLowercase(property.name) %>.calculate(parameters); @@ -24,12 +18,6 @@ void <%- camelize(type) %>LayoutProperties::recalculate(const CalculationParamet } <% } -%> -void <%- camelize(type) %>PaintProperties::parse(const JSValue& value) { -<% for (const property of paintProperties) { -%> - <%- camelizeWithLeadingLowercase(property.name) %>.parse(<%- JSON.stringify(property.name) %>, value); -<% } -%> -} - void <%- camelize(type) %>PaintProperties::cascade(const CascadeParameters& parameters) { <% for (const property of paintProperties) { -%> <%- camelizeWithLeadingLowercase(property.name) %>.cascade(parameters); diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs index 8ea713e20ac..a485621ac6e 100644 --- a/src/mbgl/style/layers/layer_properties.hpp.ejs +++ b/src/mbgl/style/layers/layer_properties.hpp.ejs @@ -7,9 +7,9 @@ #pragma once +#include #include #include -#include namespace mbgl { namespace style { @@ -20,7 +20,6 @@ class CalculationParameters; <% if (layoutProperties.length) { -%> class <%- camelize(type) %>LayoutProperties { public: - void parse(const JSValue&); void recalculate(const CalculationParameters&); <% for (const property of layoutProperties) { -%> @@ -31,7 +30,6 @@ public: <% } -%> class <%- camelize(type) %>PaintProperties { public: - void parse(const JSValue&); void cascade(const CascadeParameters&); bool recalculate(const CalculationParameters&); diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp index abe326a672e..3ad72cda166 100644 --- a/src/mbgl/style/layers/line_layer.cpp +++ b/src/mbgl/style/layers/line_layer.cpp @@ -6,10 +6,11 @@ namespace mbgl { namespace style { -LineLayer::LineLayer(const std::string& layerID) +LineLayer::LineLayer(const std::string& layerID, const std::string& sourceID) : Layer(Type::Line, std::make_unique()) , impl(static_cast(baseImpl.get())) { impl->id = layerID; + impl->source = sourceID; } LineLayer::LineLayer(const Impl& other) @@ -23,17 +24,24 @@ std::unique_ptr LineLayer::Impl::clone() const { return std::make_unique(*this); } -// Source - -void LineLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { - impl->source = sourceID; - impl->sourceLayer = sourceLayer; +std::unique_ptr LineLayer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = LinePaintProperties(); + return std::move(result); } +// Source + const std::string& LineLayer::getSourceID() const { return impl->source; } +void LineLayer::setSourceLayer(const std::string& sourceLayer) { + impl->sourceLayer = sourceLayer; +} + const std::string& LineLayer::getSourceLayer() const { return impl->sourceLayer; } @@ -85,80 +93,80 @@ PropertyValue LineLayer::getLineOpacity() const { return impl->paint.lineOpacity.get(); } -void LineLayer::setLineOpacity(PropertyValue value) { - impl->paint.lineOpacity.set(value); +void LineLayer::setLineOpacity(PropertyValue value, const optional& klass) { + impl->paint.lineOpacity.set(value, klass); } PropertyValue LineLayer::getLineColor() const { return impl->paint.lineColor.get(); } -void LineLayer::setLineColor(PropertyValue value) { - impl->paint.lineColor.set(value); +void LineLayer::setLineColor(PropertyValue value, const optional& klass) { + impl->paint.lineColor.set(value, klass); } PropertyValue> LineLayer::getLineTranslate() const { return impl->paint.lineTranslate.get(); } -void LineLayer::setLineTranslate(PropertyValue> value) { - impl->paint.lineTranslate.set(value); +void LineLayer::setLineTranslate(PropertyValue> value, const optional& klass) { + impl->paint.lineTranslate.set(value, klass); } PropertyValue LineLayer::getLineTranslateAnchor() const { return impl->paint.lineTranslateAnchor.get(); } -void LineLayer::setLineTranslateAnchor(PropertyValue value) { - impl->paint.lineTranslateAnchor.set(value); +void LineLayer::setLineTranslateAnchor(PropertyValue value, const optional& klass) { + impl->paint.lineTranslateAnchor.set(value, klass); } PropertyValue LineLayer::getLineWidth() const { return impl->paint.lineWidth.get(); } -void LineLayer::setLineWidth(PropertyValue value) { - impl->paint.lineWidth.set(value); +void LineLayer::setLineWidth(PropertyValue value, const optional& klass) { + impl->paint.lineWidth.set(value, klass); } PropertyValue LineLayer::getLineGapWidth() const { return impl->paint.lineGapWidth.get(); } -void LineLayer::setLineGapWidth(PropertyValue value) { - impl->paint.lineGapWidth.set(value); +void LineLayer::setLineGapWidth(PropertyValue value, const optional& klass) { + impl->paint.lineGapWidth.set(value, klass); } PropertyValue LineLayer::getLineOffset() const { return impl->paint.lineOffset.get(); } -void LineLayer::setLineOffset(PropertyValue value) { - impl->paint.lineOffset.set(value); +void LineLayer::setLineOffset(PropertyValue value, const optional& klass) { + impl->paint.lineOffset.set(value, klass); } PropertyValue LineLayer::getLineBlur() const { return impl->paint.lineBlur.get(); } -void LineLayer::setLineBlur(PropertyValue value) { - impl->paint.lineBlur.set(value); +void LineLayer::setLineBlur(PropertyValue value, const optional& klass) { + impl->paint.lineBlur.set(value, klass); } PropertyValue> LineLayer::getLineDasharray() const { return impl->paint.lineDasharray.get(); } -void LineLayer::setLineDasharray(PropertyValue> value) { - impl->paint.lineDasharray.set(value); +void LineLayer::setLineDasharray(PropertyValue> value, const optional& klass) { + impl->paint.lineDasharray.set(value, klass); } PropertyValue LineLayer::getLinePattern() const { return impl->paint.linePattern.get(); } -void LineLayer::setLinePattern(PropertyValue value) { - impl->paint.linePattern.set(value); +void LineLayer::setLinePattern(PropertyValue value, const optional& klass) { + impl->paint.linePattern.set(value, klass); } } // namespace style diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp index 589b129ee6d..3cdd90b7fdf 100644 --- a/src/mbgl/style/layers/line_layer_impl.cpp +++ b/src/mbgl/style/layers/line_layer_impl.cpp @@ -8,14 +8,6 @@ namespace mbgl { namespace style { -void LineLayer::Impl::parseLayout(const JSValue& value) { - layout.parse(value); -} - -void LineLayer::Impl::parsePaints(const JSValue& layer) { - paint.parse(layer); -} - void LineLayer::Impl::cascade(const CascadeParameters& parameters) { paint.cascade(parameters); } diff --git a/src/mbgl/style/layers/line_layer_impl.hpp b/src/mbgl/style/layers/line_layer_impl.hpp index 3356dc2ceb4..e130bc01bcf 100644 --- a/src/mbgl/style/layers/line_layer_impl.hpp +++ b/src/mbgl/style/layers/line_layer_impl.hpp @@ -10,9 +10,7 @@ namespace style { class LineLayer::Impl : public Layer::Impl { public: std::unique_ptr clone() const override; - - void parseLayout(const JSValue&) override; - void parsePaints(const JSValue&) override; + std::unique_ptr cloneRef(const std::string& id) const override; void cascade(const CascadeParameters&) override; bool recalculate(const CalculationParameters&) override; diff --git a/src/mbgl/style/layers/line_layer_properties.cpp b/src/mbgl/style/layers/line_layer_properties.cpp index 7c74f6de04a..2d6092745eb 100644 --- a/src/mbgl/style/layers/line_layer_properties.cpp +++ b/src/mbgl/style/layers/line_layer_properties.cpp @@ -5,13 +5,6 @@ namespace mbgl { namespace style { -void LineLayoutProperties::parse(const JSValue& value) { - lineCap.parse("line-cap", value); - lineJoin.parse("line-join", value); - lineMiterLimit.parse("line-miter-limit", value); - lineRoundLimit.parse("line-round-limit", value); -} - void LineLayoutProperties::recalculate(const CalculationParameters& parameters) { lineCap.calculate(parameters); lineJoin.calculate(parameters); @@ -19,19 +12,6 @@ void LineLayoutProperties::recalculate(const CalculationParameters& parameters) lineRoundLimit.calculate(parameters); } -void LinePaintProperties::parse(const JSValue& value) { - lineOpacity.parse("line-opacity", value); - lineColor.parse("line-color", value); - lineTranslate.parse("line-translate", value); - lineTranslateAnchor.parse("line-translate-anchor", value); - lineWidth.parse("line-width", value); - lineGapWidth.parse("line-gap-width", value); - lineOffset.parse("line-offset", value); - lineBlur.parse("line-blur", value); - lineDasharray.parse("line-dasharray", value); - linePattern.parse("line-pattern", value); -} - void LinePaintProperties::cascade(const CascadeParameters& parameters) { lineOpacity.cascade(parameters); lineColor.cascade(parameters); diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp index c715171c882..e7dbddf4420 100644 --- a/src/mbgl/style/layers/line_layer_properties.hpp +++ b/src/mbgl/style/layers/line_layer_properties.hpp @@ -2,9 +2,9 @@ #pragma once +#include #include #include -#include namespace mbgl { namespace style { @@ -14,7 +14,6 @@ class CalculationParameters; class LineLayoutProperties { public: - void parse(const JSValue&); void recalculate(const CalculationParameters&); LayoutProperty lineCap { LineCapType::Butt }; @@ -25,7 +24,6 @@ class LineLayoutProperties { class LinePaintProperties { public: - void parse(const JSValue&); void cascade(const CascadeParameters&); bool recalculate(const CalculationParameters&); diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp index fb7f08fbe91..d4e121babe7 100644 --- a/src/mbgl/style/layers/raster_layer.cpp +++ b/src/mbgl/style/layers/raster_layer.cpp @@ -6,10 +6,11 @@ namespace mbgl { namespace style { -RasterLayer::RasterLayer(const std::string& layerID) +RasterLayer::RasterLayer(const std::string& layerID, const std::string& sourceID) : Layer(Type::Raster, std::make_unique()) , impl(static_cast(baseImpl.get())) { impl->id = layerID; + impl->source = sourceID; } RasterLayer::RasterLayer(const Impl& other) @@ -23,16 +24,21 @@ std::unique_ptr RasterLayer::Impl::clone() const { return std::make_unique(*this); } -// Source - -void RasterLayer::setSource(const std::string& sourceID) { - impl->source = sourceID; +std::unique_ptr RasterLayer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = RasterPaintProperties(); + return std::move(result); } +// Source + const std::string& RasterLayer::getSourceID() const { return impl->source; } + // Layout properties @@ -42,56 +48,56 @@ PropertyValue RasterLayer::getRasterOpacity() const { return impl->paint.rasterOpacity.get(); } -void RasterLayer::setRasterOpacity(PropertyValue value) { - impl->paint.rasterOpacity.set(value); +void RasterLayer::setRasterOpacity(PropertyValue value, const optional& klass) { + impl->paint.rasterOpacity.set(value, klass); } PropertyValue RasterLayer::getRasterHueRotate() const { return impl->paint.rasterHueRotate.get(); } -void RasterLayer::setRasterHueRotate(PropertyValue value) { - impl->paint.rasterHueRotate.set(value); +void RasterLayer::setRasterHueRotate(PropertyValue value, const optional& klass) { + impl->paint.rasterHueRotate.set(value, klass); } PropertyValue RasterLayer::getRasterBrightnessMin() const { return impl->paint.rasterBrightnessMin.get(); } -void RasterLayer::setRasterBrightnessMin(PropertyValue value) { - impl->paint.rasterBrightnessMin.set(value); +void RasterLayer::setRasterBrightnessMin(PropertyValue value, const optional& klass) { + impl->paint.rasterBrightnessMin.set(value, klass); } PropertyValue RasterLayer::getRasterBrightnessMax() const { return impl->paint.rasterBrightnessMax.get(); } -void RasterLayer::setRasterBrightnessMax(PropertyValue value) { - impl->paint.rasterBrightnessMax.set(value); +void RasterLayer::setRasterBrightnessMax(PropertyValue value, const optional& klass) { + impl->paint.rasterBrightnessMax.set(value, klass); } PropertyValue RasterLayer::getRasterSaturation() const { return impl->paint.rasterSaturation.get(); } -void RasterLayer::setRasterSaturation(PropertyValue value) { - impl->paint.rasterSaturation.set(value); +void RasterLayer::setRasterSaturation(PropertyValue value, const optional& klass) { + impl->paint.rasterSaturation.set(value, klass); } PropertyValue RasterLayer::getRasterContrast() const { return impl->paint.rasterContrast.get(); } -void RasterLayer::setRasterContrast(PropertyValue value) { - impl->paint.rasterContrast.set(value); +void RasterLayer::setRasterContrast(PropertyValue value, const optional& klass) { + impl->paint.rasterContrast.set(value, klass); } PropertyValue RasterLayer::getRasterFadeDuration() const { return impl->paint.rasterFadeDuration.get(); } -void RasterLayer::setRasterFadeDuration(PropertyValue value) { - impl->paint.rasterFadeDuration.set(value); +void RasterLayer::setRasterFadeDuration(PropertyValue value, const optional& klass) { + impl->paint.rasterFadeDuration.set(value, klass); } } // namespace style diff --git a/src/mbgl/style/layers/raster_layer_impl.cpp b/src/mbgl/style/layers/raster_layer_impl.cpp index 4854ec041da..879bfa45594 100644 --- a/src/mbgl/style/layers/raster_layer_impl.cpp +++ b/src/mbgl/style/layers/raster_layer_impl.cpp @@ -4,10 +4,6 @@ namespace mbgl { namespace style { -void RasterLayer::Impl::parsePaints(const JSValue& layer) { - paint.parse(layer); -} - void RasterLayer::Impl::cascade(const CascadeParameters& parameters) { paint.cascade(parameters); } diff --git a/src/mbgl/style/layers/raster_layer_impl.hpp b/src/mbgl/style/layers/raster_layer_impl.hpp index 6812b469a61..a5b396e2ed2 100644 --- a/src/mbgl/style/layers/raster_layer_impl.hpp +++ b/src/mbgl/style/layers/raster_layer_impl.hpp @@ -10,9 +10,7 @@ namespace style { class RasterLayer::Impl : public Layer::Impl { public: std::unique_ptr clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; + std::unique_ptr cloneRef(const std::string& id) const override; void cascade(const CascadeParameters&) override; bool recalculate(const CalculationParameters&) override; diff --git a/src/mbgl/style/layers/raster_layer_properties.cpp b/src/mbgl/style/layers/raster_layer_properties.cpp index 0e6afc5e9c9..68d9d1d35df 100644 --- a/src/mbgl/style/layers/raster_layer_properties.cpp +++ b/src/mbgl/style/layers/raster_layer_properties.cpp @@ -5,16 +5,6 @@ namespace mbgl { namespace style { -void RasterPaintProperties::parse(const JSValue& value) { - rasterOpacity.parse("raster-opacity", value); - rasterHueRotate.parse("raster-hue-rotate", value); - rasterBrightnessMin.parse("raster-brightness-min", value); - rasterBrightnessMax.parse("raster-brightness-max", value); - rasterSaturation.parse("raster-saturation", value); - rasterContrast.parse("raster-contrast", value); - rasterFadeDuration.parse("raster-fade-duration", value); -} - void RasterPaintProperties::cascade(const CascadeParameters& parameters) { rasterOpacity.cascade(parameters); rasterHueRotate.cascade(parameters); diff --git a/src/mbgl/style/layers/raster_layer_properties.hpp b/src/mbgl/style/layers/raster_layer_properties.hpp index 049da873127..ddfb833e128 100644 --- a/src/mbgl/style/layers/raster_layer_properties.hpp +++ b/src/mbgl/style/layers/raster_layer_properties.hpp @@ -2,9 +2,9 @@ #pragma once +#include #include #include -#include namespace mbgl { namespace style { @@ -14,7 +14,6 @@ class CalculationParameters; class RasterPaintProperties { public: - void parse(const JSValue&); void cascade(const CascadeParameters&); bool recalculate(const CalculationParameters&); diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp index 38a898deca8..c26123f0ecc 100644 --- a/src/mbgl/style/layers/symbol_layer.cpp +++ b/src/mbgl/style/layers/symbol_layer.cpp @@ -6,10 +6,11 @@ namespace mbgl { namespace style { -SymbolLayer::SymbolLayer(const std::string& layerID) +SymbolLayer::SymbolLayer(const std::string& layerID, const std::string& sourceID) : Layer(Type::Symbol, std::make_unique()) , impl(static_cast(baseImpl.get())) { impl->id = layerID; + impl->source = sourceID; } SymbolLayer::SymbolLayer(const Impl& other) @@ -23,17 +24,24 @@ std::unique_ptr SymbolLayer::Impl::clone() const { return std::make_unique(*this); } -// Source - -void SymbolLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { - impl->source = sourceID; - impl->sourceLayer = sourceLayer; +std::unique_ptr SymbolLayer::Impl::cloneRef(const std::string& id_) const { + auto result = std::make_unique(*this); + result->impl->id = id_; + result->impl->ref = this->id; + result->impl->paint = SymbolPaintProperties(); + return std::move(result); } +// Source + const std::string& SymbolLayer::getSourceID() const { return impl->source; } +void SymbolLayer::setSourceLayer(const std::string& sourceLayer) { + impl->sourceLayer = sourceLayer; +} + const std::string& SymbolLayer::getSourceLayer() const { return impl->sourceLayer; } @@ -295,112 +303,112 @@ PropertyValue SymbolLayer::getIconOpacity() const { return impl->paint.iconOpacity.get(); } -void SymbolLayer::setIconOpacity(PropertyValue value) { - impl->paint.iconOpacity.set(value); +void SymbolLayer::setIconOpacity(PropertyValue value, const optional& klass) { + impl->paint.iconOpacity.set(value, klass); } PropertyValue SymbolLayer::getIconColor() const { return impl->paint.iconColor.get(); } -void SymbolLayer::setIconColor(PropertyValue value) { - impl->paint.iconColor.set(value); +void SymbolLayer::setIconColor(PropertyValue value, const optional& klass) { + impl->paint.iconColor.set(value, klass); } PropertyValue SymbolLayer::getIconHaloColor() const { return impl->paint.iconHaloColor.get(); } -void SymbolLayer::setIconHaloColor(PropertyValue value) { - impl->paint.iconHaloColor.set(value); +void SymbolLayer::setIconHaloColor(PropertyValue value, const optional& klass) { + impl->paint.iconHaloColor.set(value, klass); } PropertyValue SymbolLayer::getIconHaloWidth() const { return impl->paint.iconHaloWidth.get(); } -void SymbolLayer::setIconHaloWidth(PropertyValue value) { - impl->paint.iconHaloWidth.set(value); +void SymbolLayer::setIconHaloWidth(PropertyValue value, const optional& klass) { + impl->paint.iconHaloWidth.set(value, klass); } PropertyValue SymbolLayer::getIconHaloBlur() const { return impl->paint.iconHaloBlur.get(); } -void SymbolLayer::setIconHaloBlur(PropertyValue value) { - impl->paint.iconHaloBlur.set(value); +void SymbolLayer::setIconHaloBlur(PropertyValue value, const optional& klass) { + impl->paint.iconHaloBlur.set(value, klass); } PropertyValue> SymbolLayer::getIconTranslate() const { return impl->paint.iconTranslate.get(); } -void SymbolLayer::setIconTranslate(PropertyValue> value) { - impl->paint.iconTranslate.set(value); +void SymbolLayer::setIconTranslate(PropertyValue> value, const optional& klass) { + impl->paint.iconTranslate.set(value, klass); } PropertyValue SymbolLayer::getIconTranslateAnchor() const { return impl->paint.iconTranslateAnchor.get(); } -void SymbolLayer::setIconTranslateAnchor(PropertyValue value) { - impl->paint.iconTranslateAnchor.set(value); +void SymbolLayer::setIconTranslateAnchor(PropertyValue value, const optional& klass) { + impl->paint.iconTranslateAnchor.set(value, klass); } PropertyValue SymbolLayer::getTextOpacity() const { return impl->paint.textOpacity.get(); } -void SymbolLayer::setTextOpacity(PropertyValue value) { - impl->paint.textOpacity.set(value); +void SymbolLayer::setTextOpacity(PropertyValue value, const optional& klass) { + impl->paint.textOpacity.set(value, klass); } PropertyValue SymbolLayer::getTextColor() const { return impl->paint.textColor.get(); } -void SymbolLayer::setTextColor(PropertyValue value) { - impl->paint.textColor.set(value); +void SymbolLayer::setTextColor(PropertyValue value, const optional& klass) { + impl->paint.textColor.set(value, klass); } PropertyValue SymbolLayer::getTextHaloColor() const { return impl->paint.textHaloColor.get(); } -void SymbolLayer::setTextHaloColor(PropertyValue value) { - impl->paint.textHaloColor.set(value); +void SymbolLayer::setTextHaloColor(PropertyValue value, const optional& klass) { + impl->paint.textHaloColor.set(value, klass); } PropertyValue SymbolLayer::getTextHaloWidth() const { return impl->paint.textHaloWidth.get(); } -void SymbolLayer::setTextHaloWidth(PropertyValue value) { - impl->paint.textHaloWidth.set(value); +void SymbolLayer::setTextHaloWidth(PropertyValue value, const optional& klass) { + impl->paint.textHaloWidth.set(value, klass); } PropertyValue SymbolLayer::getTextHaloBlur() const { return impl->paint.textHaloBlur.get(); } -void SymbolLayer::setTextHaloBlur(PropertyValue value) { - impl->paint.textHaloBlur.set(value); +void SymbolLayer::setTextHaloBlur(PropertyValue value, const optional& klass) { + impl->paint.textHaloBlur.set(value, klass); } PropertyValue> SymbolLayer::getTextTranslate() const { return impl->paint.textTranslate.get(); } -void SymbolLayer::setTextTranslate(PropertyValue> value) { - impl->paint.textTranslate.set(value); +void SymbolLayer::setTextTranslate(PropertyValue> value, const optional& klass) { + impl->paint.textTranslate.set(value, klass); } PropertyValue SymbolLayer::getTextTranslateAnchor() const { return impl->paint.textTranslateAnchor.get(); } -void SymbolLayer::setTextTranslateAnchor(PropertyValue value) { - impl->paint.textTranslateAnchor.set(value); +void SymbolLayer::setTextTranslateAnchor(PropertyValue value, const optional& klass) { + impl->paint.textTranslateAnchor.set(value, klass); } } // namespace style diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp index eeceb52078c..0243b1dfa56 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.cpp +++ b/src/mbgl/style/layers/symbol_layer_impl.cpp @@ -5,14 +5,6 @@ namespace mbgl { namespace style { -void SymbolLayer::Impl::parseLayout(const JSValue& value) { - layout.parse(value); -} - -void SymbolLayer::Impl::parsePaints(const JSValue& layer) { - paint.parse(layer); -} - void SymbolLayer::Impl::cascade(const CascadeParameters& parameters) { paint.cascade(parameters); } diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp index 9727cc64809..7765d6790e7 100644 --- a/src/mbgl/style/layers/symbol_layer_impl.hpp +++ b/src/mbgl/style/layers/symbol_layer_impl.hpp @@ -13,9 +13,7 @@ namespace style { class SymbolLayer::Impl : public Layer::Impl { public: std::unique_ptr clone() const override; - - void parseLayout(const JSValue&) override; - void parsePaints(const JSValue&) override; + std::unique_ptr cloneRef(const std::string& id) const override; void cascade(const CascadeParameters&) override; bool recalculate(const CalculationParameters&) override; diff --git a/src/mbgl/style/layers/symbol_layer_properties.cpp b/src/mbgl/style/layers/symbol_layer_properties.cpp index d77d10700c0..59a73d3d59d 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.cpp +++ b/src/mbgl/style/layers/symbol_layer_properties.cpp @@ -5,43 +5,6 @@ namespace mbgl { namespace style { -void SymbolLayoutProperties::parse(const JSValue& value) { - symbolPlacement.parse("symbol-placement", value); - symbolSpacing.parse("symbol-spacing", value); - symbolAvoidEdges.parse("symbol-avoid-edges", value); - iconAllowOverlap.parse("icon-allow-overlap", value); - iconIgnorePlacement.parse("icon-ignore-placement", value); - iconOptional.parse("icon-optional", value); - iconRotationAlignment.parse("icon-rotation-alignment", value); - iconSize.parse("icon-size", value); - iconTextFit.parse("icon-text-fit", value); - iconTextFitPadding.parse("icon-text-fit-padding", value); - iconImage.parse("icon-image", value); - iconRotate.parse("icon-rotate", value); - iconPadding.parse("icon-padding", value); - iconKeepUpright.parse("icon-keep-upright", value); - iconOffset.parse("icon-offset", value); - textPitchAlignment.parse("text-pitch-alignment", value); - textRotationAlignment.parse("text-rotation-alignment", value); - textField.parse("text-field", value); - textFont.parse("text-font", value); - textSize.parse("text-size", value); - textMaxWidth.parse("text-max-width", value); - textLineHeight.parse("text-line-height", value); - textLetterSpacing.parse("text-letter-spacing", value); - textJustify.parse("text-justify", value); - textAnchor.parse("text-anchor", value); - textMaxAngle.parse("text-max-angle", value); - textRotate.parse("text-rotate", value); - textPadding.parse("text-padding", value); - textKeepUpright.parse("text-keep-upright", value); - textTransform.parse("text-transform", value); - textOffset.parse("text-offset", value); - textAllowOverlap.parse("text-allow-overlap", value); - textIgnorePlacement.parse("text-ignore-placement", value); - textOptional.parse("text-optional", value); -} - void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters) { symbolPlacement.calculate(parameters); symbolSpacing.calculate(parameters); @@ -79,23 +42,6 @@ void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters textOptional.calculate(parameters); } -void SymbolPaintProperties::parse(const JSValue& value) { - iconOpacity.parse("icon-opacity", value); - iconColor.parse("icon-color", value); - iconHaloColor.parse("icon-halo-color", value); - iconHaloWidth.parse("icon-halo-width", value); - iconHaloBlur.parse("icon-halo-blur", value); - iconTranslate.parse("icon-translate", value); - iconTranslateAnchor.parse("icon-translate-anchor", value); - textOpacity.parse("text-opacity", value); - textColor.parse("text-color", value); - textHaloColor.parse("text-halo-color", value); - textHaloWidth.parse("text-halo-width", value); - textHaloBlur.parse("text-halo-blur", value); - textTranslate.parse("text-translate", value); - textTranslateAnchor.parse("text-translate-anchor", value); -} - void SymbolPaintProperties::cascade(const CascadeParameters& parameters) { iconOpacity.cascade(parameters); iconColor.cascade(parameters); diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp index 1882c03fef8..a269969cb8a 100644 --- a/src/mbgl/style/layers/symbol_layer_properties.hpp +++ b/src/mbgl/style/layers/symbol_layer_properties.hpp @@ -2,9 +2,9 @@ #pragma once +#include #include #include -#include namespace mbgl { namespace style { @@ -14,7 +14,6 @@ class CalculationParameters; class SymbolLayoutProperties { public: - void parse(const JSValue&); void recalculate(const CalculationParameters&); LayoutProperty symbolPlacement { SymbolPlacementType::Point }; @@ -55,7 +54,6 @@ class SymbolLayoutProperties { class SymbolPaintProperties { public: - void parse(const JSValue&); void cascade(const CascadeParameters&); bool recalculate(const CalculationParameters&); diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp index f5045b47fcb..db1a1ebf28f 100644 --- a/src/mbgl/style/layout_property.hpp +++ b/src/mbgl/style/layout_property.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include @@ -25,12 +24,6 @@ class LayoutProperty { currentValue = value_; } - void parse(const char * name, const JSValue& layout) { - if (layout.HasMember(name)) { - currentValue = parseProperty(name, layout[name]); - } - } - void calculate(const CalculationParameters& parameters) { if (currentValue) { PropertyEvaluator evaluator(parameters, defaultValue); diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp index 7bb2e68b80d..b982fe76e22 100644 --- a/src/mbgl/style/paint_property.hpp +++ b/src/mbgl/style/paint_property.hpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -28,47 +27,28 @@ class PaintProperty { } PaintProperty(const PaintProperty& other) - : values(other.values), + : defaultValue(other.defaultValue), + values(other.values), transitions(other.transitions) { } + PaintProperty& operator=(const PaintProperty& other) { + defaultValue = other.defaultValue; + values = other.values; + transitions = other.transitions; + return *this; + } + const PropertyValue& get() const { return values.at(ClassID::Default); } - void set(const PropertyValue& value_) { - values[ClassID::Default] = value_; + void set(const PropertyValue& value_, const optional& klass) { + values[klass ? ClassDictionary::Get().lookup(*klass) : ClassID::Default] = value_; } - void parse(const char* name, const JSValue& layer) { - mbgl::util::erase_if(values, [] (const auto& p) { return p.first != ClassID::Fallback; }); - - std::string transitionName = { name }; - transitionName += "-transition"; - - for (auto it = layer.MemberBegin(); it != layer.MemberEnd(); ++it) { - const std::string paintName { it->name.GetString(), it->name.GetStringLength() }; - if (paintName.compare(0, 5, "paint") != 0) - continue; - - bool isClass = paintName.compare(0, 6, "paint.") == 0; - if (isClass && paintName.length() <= 6) - continue; - - ClassID classID = isClass ? ClassDictionary::Get().lookup(paintName.substr(6)) : ClassID::Default; - - if (it->value.HasMember(name)) { - if (auto v = parseProperty(name, it->value[name])) { - values.emplace(classID, v); - } - } - - if (it->value.HasMember(transitionName.c_str())) { - if (auto v = parseTransitionOptions(name, it->value[transitionName.c_str()])) { - transitions.emplace(classID, *v); - } - } - } + void setTransition(const TransitionOptions& transition, const optional& klass) { + transitions[klass ? ClassDictionary::Get().lookup(*klass) : ClassID::Default] = transition; } void cascade(const CascadeParameters& params) { diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp index eddda5d3f24..41b23c1baea 100644 --- a/src/mbgl/style/parser.cpp +++ b/src/mbgl/style/parser.cpp @@ -1,22 +1,13 @@ #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include +#include +#include #include -#include -#include -#include +#include #include #include @@ -74,54 +65,18 @@ void Parser::parseSources(const JSValue& value) { return; } - JSValue::ConstMemberIterator itr = value.MemberBegin(); - for (; itr != value.MemberEnd(); ++itr) { - const JSValue& nameVal = itr->name; - const JSValue& sourceVal = itr->value; + for (auto it = value.MemberBegin(); it != value.MemberEnd(); ++it) { + std::string id = *conversion::toString(it->name); - if (!sourceVal.HasMember("type")) { - Log::Warning(Event::ParseStyle, "source must have a type"); + conversion::Result> source + = conversion::convert>(it->value, id); + if (!source) { + Log::Warning(Event::ParseStyle, source.error().message); continue; } - const JSValue& typeVal = sourceVal["type"]; - if (!typeVal.IsString()) { - Log::Warning(Event::ParseStyle, "source type must be a string"); - continue; - } - - const auto type = Enum::toEnum({ typeVal.GetString(), typeVal.GetStringLength() }); - if (!type) { - Log::Warning(Event::ParseStyle, "source type must have one of the enum values"); - continue; - } - - const std::string id { nameVal.GetString(), nameVal.GetStringLength() }; - std::unique_ptr source; - - switch (*type) { - case SourceType::Raster: { - source = RasterSource::Impl::parse(id, sourceVal); - break; - } - - case SourceType::Vector: - source = VectorSource::Impl::parse(id, sourceVal); - break; - - case SourceType::GeoJSON: - source = GeoJSONSource::Impl::parse(id, sourceVal); - break; - - default: - Log::Error(Event::ParseStyle, "source type '%s' is not supported", typeVal.GetString()); - continue; - } - - if (source) { - sourcesMap.emplace(id, source.get()); - sources.emplace_back(std::move(source)); - } + sourcesMap.emplace(id, (*source).get()); + sources.emplace_back(std::move(*source)); } } @@ -218,121 +173,18 @@ void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique return; } - layer = reference->copy(id, ref); - layer->baseImpl->parsePaints(value); + layer = reference->baseImpl->cloneRef(id); + conversion::setPaintProperties(*layer, value); } else { - // Otherwise, parse the source/source-layer/filter/render keys to form the bucket. - if (!value.HasMember("type")) { - Log::Warning(Event::ParseStyle, "layer '%s' is missing a type", id.c_str()); - return; - } - - const JSValue& typeVal = value["type"]; - if (!typeVal.IsString()) { - Log::Warning(Event::ParseStyle, "layer '%s' has an invalid type", id.c_str()); - return; - } - - std::string type { typeVal.GetString(), typeVal.GetStringLength() }; - - if (type == "fill") { - layer = std::make_unique(id); - } else if (type == "line") { - layer = std::make_unique(id); - } else if (type == "circle") { - layer = std::make_unique(id); - } else if (type == "symbol") { - layer = std::make_unique(id); - } else if (type == "raster") { - layer = std::make_unique(id); - } else if (type == "background") { - layer = std::make_unique(id); - } else { - Log::Warning(Event::ParseStyle, "unknown type '%s' for layer '%s'", type.c_str(), id.c_str()); + conversion::Result> converted = conversion::convert>(value); + if (!converted) { + Log::Warning(Event::ParseStyle, converted.error().message); return; } - - Layer::Impl* impl = layer->baseImpl.get(); - - if (value.HasMember("source")) { - const JSValue& value_source = value["source"]; - if (value_source.IsString()) { - impl->source = { value_source.GetString(), value_source.GetStringLength() }; - auto source_it = sourcesMap.find(impl->source); - if (source_it == sourcesMap.end()) { - Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", impl->source.c_str(), impl->id.c_str()); - } - } else { - Log::Warning(Event::ParseStyle, "source of layer '%s' must be a string", impl->id.c_str()); - } - } - - if (value.HasMember("source-layer")) { - const JSValue& value_source_layer = value["source-layer"]; - if (value_source_layer.IsString()) { - impl->sourceLayer = { value_source_layer.GetString(), value_source_layer.GetStringLength() }; - } else { - Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", impl->id.c_str()); - } - } - - if (value.HasMember("filter")) { - conversion::Result filter = conversion::convertFilter(value["filter"]); - if (filter.is()) { - impl->filter = filter.get(); - } else { - Log::Warning(Event::ParseStyle, filter.get().message); - } - } - - if (value.HasMember("minzoom")) { - const JSValue& min_zoom = value["minzoom"]; - if (min_zoom.IsNumber()) { - impl->minZoom = min_zoom.GetDouble(); - } else { - Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", impl->id.c_str()); - } - } - - if (value.HasMember("maxzoom")) { - const JSValue& max_zoom = value["maxzoom"]; - if (max_zoom.IsNumber()) { - impl->maxZoom = max_zoom.GetDouble(); - } else { - Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", impl->id.c_str()); - } - } - - if (value.HasMember("layout")) { - parseVisibility(*layer, value["layout"]); - impl->parseLayout(value["layout"]); - } - - impl->parsePaints(value); + layer = std::move(*converted); } } -void Parser::parseVisibility(Layer& layer, const JSValue& value) { - Layer::Impl& impl = *layer.baseImpl; - - if (!value.HasMember("visibility")) { - return; - } - - if (!value["visibility"].IsString()) { - Log::Warning(Event::ParseStyle, "value of 'visibility' must be a string"); - return; - } - - const auto enumValue = Enum::toEnum({ value["visibility"].GetString(), value["visibility"].GetStringLength() }); - if (!enumValue) { - Log::Warning(Event::ParseStyle, "value of 'visibility' must be a valid enumeration value"); - return; - } - - impl.visibility = *enumValue; -} - std::vector Parser::fontStacks() const { std::set result; diff --git a/src/mbgl/style/parser.hpp b/src/mbgl/style/parser.hpp index 30da0dd2b0c..faf80cee931 100644 --- a/src/mbgl/style/parser.hpp +++ b/src/mbgl/style/parser.hpp @@ -34,7 +34,6 @@ class Parser { void parseSources(const JSValue&); void parseLayers(const JSValue&); void parseLayer(const std::string& id, const JSValue&, std::unique_ptr&); - void parseVisibility(Layer&, const JSValue& value); std::unordered_map sourcesMap; std::unordered_map>> layersMap; diff --git a/src/mbgl/style/property_parsing.hpp b/src/mbgl/style/property_parsing.hpp index 0c750ca298e..8c2bd2c0f44 100644 --- a/src/mbgl/style/property_parsing.hpp +++ b/src/mbgl/style/property_parsing.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include @@ -12,12 +12,12 @@ namespace style { template PropertyValue parseProperty(const char* name, const JSValue& value) { - conversion::Result> result = conversion::convertPropertyValue(value); - if (result.template is()) { - Log::Warning(Event::ParseStyle, "%s: %s", name, result.template get().message); + conversion::Result> result = conversion::convert>(value); + if (!result) { + Log::Warning(Event::ParseStyle, "%s: %s", name, result.error().message); return {}; } - return result.template get>(); + return *result; } optional parseTransitionOptions(const char * name, const JSValue&); diff --git a/src/mbgl/style/rapidjson_conversion.hpp b/src/mbgl/style/rapidjson_conversion.hpp index 1d9f88efa3c..ecf044fb64d 100644 --- a/src/mbgl/style/rapidjson_conversion.hpp +++ b/src/mbgl/style/rapidjson_conversion.hpp @@ -2,11 +2,16 @@ #include #include +#include namespace mbgl { namespace style { namespace conversion { +inline bool isUndefined(const JSValue& value) { + return value.IsNull(); +} + inline bool isArray(const JSValue& value) { return value.IsArray(); } @@ -30,6 +35,17 @@ inline const JSValue* objectMember(const JSValue& value, const char * name) { return &value[name]; } +template +optional eachMember(const JSValue& value, Fn&& fn) { + for (auto it = value.MemberBegin(); it != value.MemberEnd(); ++it) { + optional result = fn({it->name.GetString(), it->name.GetStringLength()}, it->value); + if (result) { + return result; + } + } + return {}; +} + inline optional toBool(const JSValue& value) { if (!value.IsBool()) { return {}; diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp index b5932581ddb..a3eec4f4efc 100644 --- a/src/mbgl/style/sources/geojson_source.cpp +++ b/src/mbgl/style/sources/geojson_source.cpp @@ -4,5 +4,18 @@ namespace mbgl { namespace style { +GeoJSONSource::GeoJSONSource(const std::string& id) + : Source(SourceType::GeoJSON, std::make_unique(std::move(id), *this)) + , impl(static_cast(baseImpl.get())) { +} + +void GeoJSONSource::setURL(const std::string& url) { + impl->setURL(url); +} + +void GeoJSONSource::setGeoJSON(GeoJSON&& geoJSON) { + impl->setGeoJSON(std::move(geoJSON)); +} + } // namespace style } // namespace mbgl diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp index f58e0fc62b2..b9744d193aa 100644 --- a/src/mbgl/style/sources/geojson_source_impl.cpp +++ b/src/mbgl/style/sources/geojson_source_impl.cpp @@ -1,9 +1,10 @@ #include #include -#include +#include #include #include #include +#include #include #include @@ -12,56 +13,38 @@ #include +using namespace mapbox::geojsonvt; + namespace mbgl { namespace style { - -std::unique_ptr GeoJSONSource::Impl::parseGeoJSON(const JSValue& value) { - using namespace mapbox::geojsonvt; - +namespace conversion { +template <> +Result convertGeoJSON(const JSValue& value) { Options options; options.buffer = util::EXTENT / util::tileSize * 128; options.extent = util::EXTENT; try { - return std::make_unique(Convert::convert(value, 0), options); + return GeoJSON { std::make_unique(Convert::convert(value, 0), options) }; } catch (const std::exception& ex) { - Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", ex.what()); - // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for - // tiles to load. - return std::make_unique(std::vector{}, options); + return Error { ex.what() }; } } +} // namespace conversion -std::unique_ptr GeoJSONSource::Impl::parse(const std::string& id, const JSValue& value) { - // We should probably split this up to have URLs in the url property, and actual data - // in the data property. Until then, we're going to detect the content based on the - // object type. - if (!value.HasMember("data")) { - Log::Error(Event::ParseStyle, "GeoJSON source must have a data value"); - return nullptr; - } - - const JSValue& dataVal = value["data"]; - if (dataVal.IsString()) { - return std::make_unique([&] (Source& base) { - return std::make_unique(id, base, std::string(dataVal.GetString(), dataVal.GetStringLength())); - }); - } else if (dataVal.IsObject()) { - return std::make_unique([&] (Source& base) { - return std::make_unique(id, base, parseGeoJSON(dataVal)); - }); - } else { - Log::Error(Event::ParseStyle, "GeoJSON data must be a URL or an object"); - return nullptr; - } +GeoJSONSource::Impl::Impl(std::string id_, Source& base_) + : Source::Impl(SourceType::GeoJSON, std::move(id_), base_) { } -GeoJSONSource::Impl::Impl(std::string id_, Source& base_, variant urlOrGeoJSON_) - : Source::Impl(SourceType::GeoJSON, std::move(id_), base_), - urlOrGeoJSON(std::move(urlOrGeoJSON_)) { +GeoJSONSource::Impl::~Impl() = default; + +void GeoJSONSource::Impl::setURL(std::string url) { + urlOrGeoJSON = std::move(url); } -GeoJSONSource::Impl::~Impl() = default; +void GeoJSONSource::Impl::setGeoJSON(GeoJSON&& geoJSON) { + urlOrGeoJSON = std::move(geoJSON); +} void GeoJSONSource::Impl::load(FileSource& fileSource) { if (urlOrGeoJSON.is()) { @@ -94,9 +77,17 @@ void GeoJSONSource::Impl::load(FileSource& fileSource) { invalidateTiles(); - urlOrGeoJSON = parseGeoJSON(d); - loaded = true; + conversion::Result geoJSON = conversion::convertGeoJSON(d); + if (!geoJSON) { + Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", geoJSON.error().message); + // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for + // tiles to load. + urlOrGeoJSON = GeoJSON { std::make_unique(std::vector()) }; + } else { + urlOrGeoJSON = std::move(*geoJSON); + } + loaded = true; observer->onSourceLoaded(base); } }); @@ -104,13 +95,13 @@ void GeoJSONSource::Impl::load(FileSource& fileSource) { Range GeoJSONSource::Impl::getZoomRange() { assert(loaded); - return { 0, urlOrGeoJSON.get()->options.maxZoom }; + return { 0, urlOrGeoJSON.get().impl->options.maxZoom }; } std::unique_ptr GeoJSONSource::Impl::createTile(const OverscaledTileID& tileID, - const UpdateParameters& parameters) { + const UpdateParameters& parameters) { assert(loaded); - return std::make_unique(tileID, base.getID(), parameters, *urlOrGeoJSON.get()); + return std::make_unique(tileID, base.getID(), parameters, *urlOrGeoJSON.get().impl); } } // namespace style diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp index 350045b27c7..e6e01c06e9d 100644 --- a/src/mbgl/style/sources/geojson_source_impl.hpp +++ b/src/mbgl/style/sources/geojson_source_impl.hpp @@ -2,15 +2,8 @@ #include #include -#include #include -namespace mapbox { -namespace geojsonvt { -class GeoJSONVT; -} // namespace geojsonvt -} // namespace mapbox - namespace mbgl { class AsyncRequest; @@ -19,15 +12,12 @@ namespace style { class GeoJSONSource::Impl : public Source::Impl { public: - using GeoJSON = std::unique_ptr; - - static std::unique_ptr parse(const std::string& id, const JSValue&); - static GeoJSON parseGeoJSON(const JSValue&); - - Impl(std::string id, Source&, - variant urlOrGeoJSON); + Impl(std::string id, Source&); ~Impl() final; + void setURL(std::string); + void setGeoJSON(GeoJSON&&); + void load(FileSource&) final; uint16_t getTileSize() const final { diff --git a/src/mbgl/style/sources/raster_source_impl.cpp b/src/mbgl/style/sources/raster_source_impl.cpp index a6e19b47570..b7276512608 100644 --- a/src/mbgl/style/sources/raster_source_impl.cpp +++ b/src/mbgl/style/sources/raster_source_impl.cpp @@ -1,30 +1,9 @@ #include #include -#include namespace mbgl { namespace style { -std::unique_ptr RasterSource::Impl::parse(std::string id, const JSValue& value) { - optional> urlOrTileset = TileSourceImpl::parseURLOrTileset(value); - if (!urlOrTileset) { - return nullptr; - } - - uint16_t tileSize = util::tileSize; - if (value.HasMember("tileSize")) { - const JSValue& tileSizeVal = value["tileSize"]; - if (tileSizeVal.IsNumber() && tileSizeVal.GetUint64() <= std::numeric_limits::max()) { - tileSize = tileSizeVal.GetUint64(); - } else { - Log::Error(Event::ParseStyle, "invalid tileSize"); - return nullptr; - } - } - - return std::make_unique(std::move(id), std::move(*urlOrTileset), tileSize); -} - RasterSource::Impl::Impl(std::string id_, Source& base_, variant urlOrTileset_, uint16_t tileSize_) diff --git a/src/mbgl/style/sources/raster_source_impl.hpp b/src/mbgl/style/sources/raster_source_impl.hpp index 2222b130820..6f34a050bbe 100644 --- a/src/mbgl/style/sources/raster_source_impl.hpp +++ b/src/mbgl/style/sources/raster_source_impl.hpp @@ -8,8 +8,6 @@ namespace style { class RasterSource::Impl : public TileSourceImpl { public: - static std::unique_ptr parse(std::string id, const JSValue&); - Impl(std::string id, Source&, variant, uint16_t tileSize); private: diff --git a/src/mbgl/style/sources/vector_source_impl.cpp b/src/mbgl/style/sources/vector_source_impl.cpp index 28e14f3e16d..efe8afbbeaf 100644 --- a/src/mbgl/style/sources/vector_source_impl.cpp +++ b/src/mbgl/style/sources/vector_source_impl.cpp @@ -4,14 +4,6 @@ namespace mbgl { namespace style { -std::unique_ptr VectorSource::Impl::parse(std::string id, const JSValue& value) { - optional> urlOrTileset = TileSourceImpl::parseURLOrTileset(value); - if (!urlOrTileset) { - return nullptr; - } - return std::make_unique(std::move(id), std::move(*urlOrTileset)); -} - VectorSource::Impl::Impl(std::string id_, Source& base_, variant urlOrTileset_) : TileSourceImpl(SourceType::Vector, std::move(id_), base_, std::move(urlOrTileset_), util::tileSize) { } diff --git a/src/mbgl/style/sources/vector_source_impl.hpp b/src/mbgl/style/sources/vector_source_impl.hpp index 4a6703e5c0b..6726fa69559 100644 --- a/src/mbgl/style/sources/vector_source_impl.hpp +++ b/src/mbgl/style/sources/vector_source_impl.hpp @@ -8,8 +8,6 @@ namespace style { class VectorSource::Impl : public TileSourceImpl { public: - static std::unique_ptr parse(std::string id, const JSValue&); - Impl(std::string id, Source&, variant); private: diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index cb48790c9ff..9073894cc2e 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -141,6 +141,8 @@ Layer* Style::getLayer(const std::string& id) const { } void Style::addLayer(std::unique_ptr layer, optional before) { + // TODO: verify source + if (SymbolLayer* symbolLayer = layer->as()) { if (!symbolLayer->impl->spriteAtlas) { symbolLayer->impl->spriteAtlas = spriteAtlas.get(); diff --git a/src/mbgl/style/tile_source_impl.cpp b/src/mbgl/style/tile_source_impl.cpp index 634ef398088..3999a88a07c 100644 --- a/src/mbgl/style/tile_source_impl.cpp +++ b/src/mbgl/style/tile_source_impl.cpp @@ -1,10 +1,10 @@ #include #include -#include +#include +#include #include #include #include -#include #include #include @@ -14,73 +14,6 @@ namespace mbgl { namespace style { -namespace { - -void parseTileJSONMember(const JSValue& value, std::vector& target, const char* name) { - if (!value.HasMember(name)) { - return; - } - - const JSValue& property = value[name]; - if (!property.IsArray()) { - return; - } - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) { - if (!property[i].IsString()) { - return; - } - } - - for (rapidjson::SizeType i = 0; i < property.Size(); i++) { - target.emplace_back(std::string(property[i].GetString(), property[i].GetStringLength())); - } -} - -void parseTileJSONMember(const JSValue& value, std::string& target, const char* name) { - if (!value.HasMember(name)) { - return; - } - - const JSValue& property = value[name]; - if (!property.IsString()) { - return; - } - - target = { property.GetString(), property.GetStringLength() }; -} - -void parseTileJSONMember(const JSValue& value, uint8_t& target, const char* name) { - if (!value.HasMember(name)) { - return; - } - - const JSValue& property = value[name]; - if (!property.IsUint()) { - return; - } - - unsigned int uint = property.GetUint(); - if (uint > std::numeric_limits::max()) { - return; - } - - target = uint; -} - -Tileset parseTileJSON(const JSValue& value) { - Tileset result; - - parseTileJSONMember(value, result.tiles, "tiles"); - parseTileJSONMember(value, result.zoomRange.min, "minzoom"); - parseTileJSONMember(value, result.zoomRange.max, "maxzoom"); - parseTileJSONMember(value, result.attribution, "attribution"); - - return result; -} - -} // end namespace - Tileset TileSourceImpl::parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) { rapidjson::GenericDocument, rapidjson::CrtAllocator> document; document.Parse<0>(json.c_str()); @@ -91,30 +24,19 @@ Tileset TileSourceImpl::parseTileJSON(const std::string& json, const std::string throw std::runtime_error(message.str()); } - Tileset result = mbgl::style::parseTileJSON(document); + conversion::Result result = conversion::convert(document); + if (!result) { + throw std::runtime_error(result.error().message); + } // TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with. if (util::mapbox::isMapboxURL(sourceURL)) { - for (auto& url : result.tiles) { + for (auto& url : (*result).tiles) { url = util::mapbox::canonicalizeTileURL(url, type, tileSize); } } - return result; -} - -optional> TileSourceImpl::parseURLOrTileset(const JSValue& value) { - if (!value.HasMember("url")) { - return { mbgl::style::parseTileJSON(value) }; - } - - const JSValue& urlVal = value["url"]; - if (!urlVal.IsString()) { - Log::Error(Event::ParseStyle, "source url must be a string"); - return {}; - } - - return { std::string(urlVal.GetString(), urlVal.GetStringLength()) }; + return *result; } TileSourceImpl::TileSourceImpl(SourceType type_, std::string id_, Source& base_, diff --git a/src/mbgl/style/tile_source_impl.hpp b/src/mbgl/style/tile_source_impl.hpp index 1ceb1188db2..8f420a15d5a 100644 --- a/src/mbgl/style/tile_source_impl.hpp +++ b/src/mbgl/style/tile_source_impl.hpp @@ -4,7 +4,6 @@ #include #include #include -#include namespace mbgl { @@ -18,8 +17,6 @@ namespace style { */ class TileSourceImpl : public Source::Impl { public: - // A tile source can either specify a URL to TileJSON, or inline TileJSON. - static optional> parseURLOrTileset(const JSValue&); static Tileset parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize); TileSourceImpl(SourceType, std::string id, Source&, diff --git a/src/mbgl/util/geojson.cpp b/src/mbgl/util/geojson.cpp new file mode 100644 index 00000000000..a17d01f9339 --- /dev/null +++ b/src/mbgl/util/geojson.cpp @@ -0,0 +1,11 @@ +#include + +#include + +namespace mbgl { + +GeoJSON::GeoJSON(std::unique_ptr impl_) : impl(std::move(impl_)) {} +GeoJSON::GeoJSON(GeoJSON&&) = default; +GeoJSON::~GeoJSON() = default; + +} // namespace mbgl diff --git a/test/fixtures/style_parser/circle-blur.info.json b/test/fixtures/style_parser/circle-blur.info.json index 60306e20c8f..40c4632c0ef 100644 --- a/test/fixtures/style_parser/circle-blur.info.json +++ b/test/fixtures/style_parser/circle-blur.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "circle-blur: value must be a number"] + [1, "WARNING", "ParseStyle", "value must be a number"] ] } } diff --git a/test/fixtures/style_parser/circle-blur.style.json b/test/fixtures/style_parser/circle-blur.style.json index 8140ad5e47c..9c82142c21f 100644 --- a/test/fixtures/style_parser/circle-blur.style.json +++ b/test/fixtures/style_parser/circle-blur.style.json @@ -12,7 +12,7 @@ "type": "circle", "source": "mapbox", "paint": { - "circle-blur": null + "circle-blur": "no" } }] } diff --git a/test/fixtures/style_parser/circle-color.info.json b/test/fixtures/style_parser/circle-color.info.json index 9d569ad53df..0dfa6371b7d 100644 --- a/test/fixtures/style_parser/circle-color.info.json +++ b/test/fixtures/style_parser/circle-color.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "circle-color: value must be a string"] + [1, "WARNING", "ParseStyle", "value must be a string"] ] } } diff --git a/test/fixtures/style_parser/circle-color.style.json b/test/fixtures/style_parser/circle-color.style.json index 44c32f99cea..e9c508304b1 100644 --- a/test/fixtures/style_parser/circle-color.style.json +++ b/test/fixtures/style_parser/circle-color.style.json @@ -12,7 +12,7 @@ "type": "circle", "source": "mapbox", "paint": { - "circle-color": null + "circle-color": 1 } }] } diff --git a/test/fixtures/style_parser/circle-opacity.info.json b/test/fixtures/style_parser/circle-opacity.info.json index bb77cebd1e1..40c4632c0ef 100644 --- a/test/fixtures/style_parser/circle-opacity.info.json +++ b/test/fixtures/style_parser/circle-opacity.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "circle-opacity: value must be a number"] + [1, "WARNING", "ParseStyle", "value must be a number"] ] } } diff --git a/test/fixtures/style_parser/circle-opacity.style.json b/test/fixtures/style_parser/circle-opacity.style.json index 601e81a51b1..a993182b1b7 100644 --- a/test/fixtures/style_parser/circle-opacity.style.json +++ b/test/fixtures/style_parser/circle-opacity.style.json @@ -12,7 +12,7 @@ "type": "circle", "source": "mapbox", "paint": { - "circle-opacity": null + "circle-opacity": "no" } }] } diff --git a/test/fixtures/style_parser/circle-radius.info.json b/test/fixtures/style_parser/circle-radius.info.json index 285e962d74d..40c4632c0ef 100644 --- a/test/fixtures/style_parser/circle-radius.info.json +++ b/test/fixtures/style_parser/circle-radius.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "circle-radius: value must be a number"] + [1, "WARNING", "ParseStyle", "value must be a number"] ] } } diff --git a/test/fixtures/style_parser/circle-radius.style.json b/test/fixtures/style_parser/circle-radius.style.json index a7fb28b2d38..f12cebff970 100644 --- a/test/fixtures/style_parser/circle-radius.style.json +++ b/test/fixtures/style_parser/circle-radius.style.json @@ -12,7 +12,7 @@ "type": "circle", "source": "mapbox", "paint": { - "circle-radius": null + "circle-radius": "no" } }] } diff --git a/test/fixtures/style_parser/function-numeric.info.json b/test/fixtures/style_parser/function-numeric.info.json index 906cccf1064..7dd5a695610 100644 --- a/test/fixtures/style_parser/function-numeric.info.json +++ b/test/fixtures/style_parser/function-numeric.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "line-width: function stop must be an array"] + [1, "WARNING", "ParseStyle", "function stop must be an array"] ] } } diff --git a/test/fixtures/style_parser/function-type.info.json b/test/fixtures/style_parser/function-type.info.json index 8a844bf7c10..c9e26537f7b 100644 --- a/test/fixtures/style_parser/function-type.info.json +++ b/test/fixtures/style_parser/function-type.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "line-width: function value must specify stops"] + [1, "WARNING", "ParseStyle", "function value must specify stops"] ] } } diff --git a/test/fixtures/style_parser/geojson-invalid-data.info.json b/test/fixtures/style_parser/geojson-invalid-data.info.json index ec4a7e2b750..86f1ef6edda 100644 --- a/test/fixtures/style_parser/geojson-invalid-data.info.json +++ b/test/fixtures/style_parser/geojson-invalid-data.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "ERROR", "ParseStyle", "GeoJSON data must be a URL or an object"] + [1, "WARNING", "ParseStyle", "GeoJSON data must be a URL or an object"] ] } } diff --git a/test/fixtures/style_parser/geojson-missing-data.info.json b/test/fixtures/style_parser/geojson-missing-data.info.json index 2c4806c3cfe..594d01d19df 100644 --- a/test/fixtures/style_parser/geojson-missing-data.info.json +++ b/test/fixtures/style_parser/geojson-missing-data.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "ERROR", "ParseStyle", "GeoJSON source must have a data value"] + [1, "WARNING", "ParseStyle", "GeoJSON source must have a data value"] ] } } diff --git a/test/fixtures/style_parser/line-opacity.info.json b/test/fixtures/style_parser/line-opacity.info.json index 63af59e280b..40c4632c0ef 100644 --- a/test/fixtures/style_parser/line-opacity.info.json +++ b/test/fixtures/style_parser/line-opacity.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "line-opacity: value must be a number"] + [1, "WARNING", "ParseStyle", "value must be a number"] ] } } diff --git a/test/fixtures/style_parser/line-opacity.style.json b/test/fixtures/style_parser/line-opacity.style.json index 712b2b6f500..7d29fb312ae 100644 --- a/test/fixtures/style_parser/line-opacity.style.json +++ b/test/fixtures/style_parser/line-opacity.style.json @@ -16,7 +16,7 @@ "paint": { "line-color": "#008", "line-width": 0.9, - "line-opacity": null + "line-opacity": "no" } }] } diff --git a/test/fixtures/style_parser/line-translate.info.json b/test/fixtures/style_parser/line-translate.info.json index a23e17012e5..16df094290d 100644 --- a/test/fixtures/style_parser/line-translate.info.json +++ b/test/fixtures/style_parser/line-translate.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "line-translate: value must be an array of two numbers"] + [1, "WARNING", "ParseStyle", "value must be an array of two numbers"] ] } } diff --git a/test/fixtures/style_parser/line-translate.style.json b/test/fixtures/style_parser/line-translate.style.json index a32b2d8ee46..4890a8b6df0 100644 --- a/test/fixtures/style_parser/line-translate.style.json +++ b/test/fixtures/style_parser/line-translate.style.json @@ -12,7 +12,7 @@ "type": "line", "source": "mapbox", "paint": { - "line-translate": null + "line-translate": "no" } }] } diff --git a/test/fixtures/style_parser/line-width.info.json b/test/fixtures/style_parser/line-width.info.json index 9e549a02288..40c4632c0ef 100644 --- a/test/fixtures/style_parser/line-width.info.json +++ b/test/fixtures/style_parser/line-width.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "line-width: value must be a number"] + [1, "WARNING", "ParseStyle", "value must be a number"] ] } } diff --git a/test/fixtures/style_parser/line-width.style.json b/test/fixtures/style_parser/line-width.style.json index e5fe6fa8e1f..1f677460c45 100644 --- a/test/fixtures/style_parser/line-width.style.json +++ b/test/fixtures/style_parser/line-width.style.json @@ -14,7 +14,7 @@ "source-layer": "waterway", "filter": ["in", "type", "river", "canal"], "paint": { - "line-width": null + "line-width": "no" } }] } diff --git a/test/fixtures/style_parser/stop-zoom-value.info.json b/test/fixtures/style_parser/stop-zoom-value.info.json index 3abf1867a4c..386dce9d297 100644 --- a/test/fixtures/style_parser/stop-zoom-value.info.json +++ b/test/fixtures/style_parser/stop-zoom-value.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "fill-opacity: function stop must have two elements"] + [1, "WARNING", "ParseStyle", "function stop must have two elements"] ] } } diff --git a/test/fixtures/style_parser/stops-array.info.json b/test/fixtures/style_parser/stops-array.info.json index b82f5a97d7c..ed66513fee5 100644 --- a/test/fixtures/style_parser/stops-array.info.json +++ b/test/fixtures/style_parser/stops-array.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "line-width: function stops must be an array"] + [1, "WARNING", "ParseStyle", "function stops must be an array"] ] } } diff --git a/test/fixtures/style_parser/text-size.info.json b/test/fixtures/style_parser/text-size.info.json index b412c6beed9..40c4632c0ef 100644 --- a/test/fixtures/style_parser/text-size.info.json +++ b/test/fixtures/style_parser/text-size.info.json @@ -1,7 +1,7 @@ { "default": { "log": [ - [1, "WARNING", "ParseStyle", "text-size: value must be a number"] + [1, "WARNING", "ParseStyle", "value must be a number"] ] } } diff --git a/test/fixtures/style_parser/text-size.style.json b/test/fixtures/style_parser/text-size.style.json index ee6a6c39e40..dafa87d63b7 100644 --- a/test/fixtures/style_parser/text-size.style.json +++ b/test/fixtures/style_parser/text-size.style.json @@ -14,7 +14,7 @@ "source-layer": "country_label", "filter": ["==", "$type", "Point"], "layout": { - "text-size": null + "text-size": "no" } }] } diff --git a/test/style/filter.cpp b/test/style/filter.cpp index fd763896a6c..2d26a8eb610 100644 --- a/test/style/filter.cpp +++ b/test/style/filter.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -17,7 +18,7 @@ typedef std::multimap Properties; Filter parse(const char * expression) { rapidjson::GenericDocument, rapidjson::CrtAllocator> doc; doc.Parse<0>(expression); - return conversion::convertFilter(doc).get(); + return *conversion::convert(doc); } bool evaluate(const Filter& filter, const Properties& properties, FeatureType type = FeatureType::Unknown) { diff --git a/test/style/source.cpp b/test/style/source.cpp index d31474712ef..59b2524e177 100644 --- a/test/style/source.cpp +++ b/test/style/source.cpp @@ -276,8 +276,8 @@ TEST(Source, VectorTileCorrupt) { }; // Need to have at least one layer that uses the source. - auto layer = std::make_unique("id"); - layer->setSource("source", "water"); + auto layer = std::make_unique("id", "source"); + layer->setSourceLayer("water"); test.style.addLayer(std::move(layer)); Tileset tileset; diff --git a/test/style/style_layer.cpp b/test/style/style_layer.cpp index 3274131966d..9c6a6e924a2 100644 --- a/test/style/style_layer.cpp +++ b/test/style/style_layer.cpp @@ -55,12 +55,12 @@ const auto duration = PropertyValue { 1.0f }; TEST(Layer, Clone) { testClone("background"); - testClone("circle"); + testClone("circle", "source"); testClone("custom", [](void*){}, [](void*, const CustomLayerRenderParameters&){}, [](void*){}, nullptr), - testClone("fill"); - testClone("line"); - testClone("raster"); - testClone("symbol"); + testClone("fill", "source"); + testClone("line", "source"); + testClone("raster", "source"); + testClone("symbol", "source"); } TEST(Layer, BackgroundProperties) { @@ -80,7 +80,7 @@ TEST(Layer, BackgroundProperties) { } TEST(Layer, CircleProperties) { - auto layer = std::make_unique("circle"); + auto layer = std::make_unique("circle", "source"); EXPECT_TRUE(layer->is()); // Paint properties @@ -105,7 +105,7 @@ TEST(Layer, CircleProperties) { } TEST(Layer, FillProperties) { - auto layer = std::make_unique("fill"); + auto layer = std::make_unique("fill", "source"); EXPECT_TRUE(layer->is()); // Paint properties @@ -133,7 +133,7 @@ TEST(Layer, FillProperties) { } TEST(Layer, LineProperties) { - auto layer = std::make_unique("line"); + auto layer = std::make_unique("line", "source"); EXPECT_TRUE(layer->is()); // Layout properties @@ -184,7 +184,7 @@ TEST(Layer, LineProperties) { } TEST(Layer, RasterProperties) { - auto layer = std::make_unique("raster"); + auto layer = std::make_unique("raster", "source"); EXPECT_TRUE(layer->is()); // Paint properties diff --git a/test/text/quads.cpp b/test/text/quads.cpp index 6fdd769fc39..2dd6a68cadb 100644 --- a/test/text/quads.cpp +++ b/test/text/quads.cpp @@ -4,14 +4,13 @@ #include #include #include -#include -#include +#include using namespace mbgl; using namespace mbgl::style; TEST(getIconQuads, normal) { - auto layer = std::make_unique("symbol"); + SymbolLayoutProperties layout; Anchor anchor(2.0, 3.0, 0.0, 0.5f, 0); SpriteAtlasElement image = { Rect( 0, 0, 15, 11 ), @@ -22,7 +21,7 @@ TEST(getIconQuads, normal) { GeometryCoordinates line; Shaping shapedText; - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads.size(), 1u); ASSERT_EQ(quads[0].anchorPoint.x, 2); @@ -58,8 +57,8 @@ TEST(getIconQuads, style) { // none { - auto layer = std::make_unique("symbol"); - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads.size(), 1u); ASSERT_EQ(quads[0].anchorPoint.x, 0); @@ -79,10 +78,10 @@ TEST(getIconQuads, style) { // width { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(24.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Width); - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(24.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Width); + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -60); ASSERT_EQ(quads[0].tl.y, 0); @@ -96,10 +95,10 @@ TEST(getIconQuads, style) { // width x textSize { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(12.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Width); - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(12.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Width); + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -30); ASSERT_EQ(quads[0].tl.y, -5); @@ -113,14 +112,14 @@ TEST(getIconQuads, style) { // width x textSize + padding { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(12.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Width); - layer->impl->layout.iconTextFitPadding.value[0] = 5.0f; - layer->impl->layout.iconTextFitPadding.value[1] = 10.0f; - layer->impl->layout.iconTextFitPadding.value[2] = 5.0f; - layer->impl->layout.iconTextFitPadding.value[3] = 10.0f; - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(12.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Width); + layout.iconTextFitPadding.value[0] = 5.0f; + layout.iconTextFitPadding.value[1] = 10.0f; + layout.iconTextFitPadding.value[2] = 5.0f; + layout.iconTextFitPadding.value[3] = 10.0f; + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -40); ASSERT_EQ(quads[0].tl.y, -10); @@ -134,10 +133,10 @@ TEST(getIconQuads, style) { // height { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(24.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Height); - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(24.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Height); + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -30); ASSERT_EQ(quads[0].tl.y, -10); @@ -151,10 +150,10 @@ TEST(getIconQuads, style) { // height x textSize { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(12.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Height); - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(12.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Height); + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -20); ASSERT_EQ(quads[0].tl.y, -5); @@ -168,14 +167,14 @@ TEST(getIconQuads, style) { // height x textSize + padding { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(12.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Height); - layer->impl->layout.iconTextFitPadding.value[0] = 5.0f; - layer->impl->layout.iconTextFitPadding.value[1] = 10.0f; - layer->impl->layout.iconTextFitPadding.value[2] = 5.0f; - layer->impl->layout.iconTextFitPadding.value[3] = 10.0f; - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(12.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Height); + layout.iconTextFitPadding.value[0] = 5.0f; + layout.iconTextFitPadding.value[1] = 10.0f; + layout.iconTextFitPadding.value[2] = 5.0f; + layout.iconTextFitPadding.value[3] = 10.0f; + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -30); ASSERT_EQ(quads[0].tl.y, -10); @@ -189,10 +188,10 @@ TEST(getIconQuads, style) { // both { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(24.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Both); - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(24.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Both); + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -60); ASSERT_EQ(quads[0].tl.y, -10); @@ -206,10 +205,10 @@ TEST(getIconQuads, style) { // both x textSize { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(12.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Both); - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(12.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Both); + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -30); ASSERT_EQ(quads[0].tl.y, -5); @@ -223,14 +222,14 @@ TEST(getIconQuads, style) { // both x textSize + padding { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(12.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Both); - layer->impl->layout.iconTextFitPadding.value[0] = 5.0f; - layer->impl->layout.iconTextFitPadding.value[1] = 10.0f; - layer->impl->layout.iconTextFitPadding.value[2] = 5.0f; - layer->impl->layout.iconTextFitPadding.value[3] = 10.0f; - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(12.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Both); + layout.iconTextFitPadding.value[0] = 5.0f; + layout.iconTextFitPadding.value[1] = 10.0f; + layout.iconTextFitPadding.value[2] = 5.0f; + layout.iconTextFitPadding.value[3] = 10.0f; + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -40); ASSERT_EQ(quads[0].tl.y, -10); @@ -244,14 +243,14 @@ TEST(getIconQuads, style) { // both x textSize + padding t/r/b/l { - auto layer = std::make_unique("symbol"); - layer->impl->layout.textSize = LayoutProperty(12.0f); - layer->impl->layout.iconTextFit = LayoutProperty(IconTextFitType::Both); - layer->impl->layout.iconTextFitPadding.value[0] = 0.0f; - layer->impl->layout.iconTextFitPadding.value[1] = 5.0f; - layer->impl->layout.iconTextFitPadding.value[2] = 10.0f; - layer->impl->layout.iconTextFitPadding.value[3] = 15.0f; - SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layer->impl->layout, false, shapedText); + SymbolLayoutProperties layout; + layout.textSize = LayoutProperty(12.0f); + layout.iconTextFit = LayoutProperty(IconTextFitType::Both); + layout.iconTextFitPadding.value[0] = 0.0f; + layout.iconTextFitPadding.value[1] = 5.0f; + layout.iconTextFitPadding.value[2] = 10.0f; + layout.iconTextFitPadding.value[3] = 15.0f; + SymbolQuads quads = getIconQuads(anchor, shapedIcon, line, layout, false, shapedText); ASSERT_EQ(quads[0].tl.x, -45); ASSERT_EQ(quads[0].tl.y, -5);