diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-04-25 13:15:44 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-06-02 14:51:39 -0700 |
commit | a43940afb2208c61b487bfd8729bbde1bd674794 (patch) | |
tree | 53d192ea899be1d88f99aeef3d1b3255f9cb5104 | |
parent | 27baa34d44f0006c05ba7c417bf11e184b0bd22b (diff) | |
download | qtlocation-mapboxgl-a43940afb2208c61b487bfd8729bbde1bd674794.tar.gz |
[core] Runtime style layer API
105 files changed, 3110 insertions, 1098 deletions
@@ -296,6 +296,9 @@ tidy: compdb #### Miscellaneous targets ##################################################### +style-code: + node scripts/generate-style-code.js + clean: -find ./deps/gyp -name "*.pyc" -exec rm {} \; -rm -rf ./build \ diff --git a/include/mbgl/layer/background_layer.hpp b/include/mbgl/layer/background_layer.hpp new file mode 100644 index 0000000000..79f24990e6 --- /dev/null +++ b/include/mbgl/layer/background_layer.hpp @@ -0,0 +1,39 @@ +// This file is generated. Do not edit. + +#pragma once + +#include <mbgl/style/layer.hpp> + +namespace mbgl { + +class BackgroundLayer : public Layer { +public: + BackgroundLayer(const std::string& layerID); + ~BackgroundLayer() final; + + // Paint properties + + Function<Color> getBackgroundColor() const; + void setBackgroundColor(Function<Color>); + + Function<std::string> getBackgroundPattern() const; + void setBackgroundPattern(Function<std::string>); + + Function<float> getBackgroundOpacity() const; + void setBackgroundOpacity(Function<float>); + + // Private implementation + + class Impl; + Impl* const impl; + + BackgroundLayer(const Impl&); + BackgroundLayer(const BackgroundLayer&) = delete; +}; + +template <> +inline bool Layer::is<BackgroundLayer>() const { + return type == Type::Background; +} + +} // namespace mbgl diff --git a/include/mbgl/layer/circle_layer.hpp b/include/mbgl/layer/circle_layer.hpp new file mode 100644 index 0000000000..14b9da895f --- /dev/null +++ b/include/mbgl/layer/circle_layer.hpp @@ -0,0 +1,54 @@ +// This file is generated. Do not edit. + +#pragma once + +#include <mbgl/style/layer.hpp> + +namespace mbgl { + +class CircleLayer : public Layer { +public: + CircleLayer(const std::string& layerID); + ~CircleLayer() final; + + // Source + + void setSource(const std::string& sourceID, const std::string& sourceLayer); + const std::string& getSourceID() const; + const std::string& getSourceLayer() const; + + // Paint properties + + Function<float> getCircleRadius() const; + void setCircleRadius(Function<float>); + + Function<Color> getCircleColor() const; + void setCircleColor(Function<Color>); + + Function<float> getCircleBlur() const; + void setCircleBlur(Function<float>); + + Function<float> getCircleOpacity() const; + void setCircleOpacity(Function<float>); + + Function<std::array<float, 2>> getCircleTranslate() const; + void setCircleTranslate(Function<std::array<float, 2>>); + + Function<TranslateAnchorType> getCircleTranslateAnchor() const; + void setCircleTranslateAnchor(Function<TranslateAnchorType>); + + // Private implementation + + class Impl; + Impl* const impl; + + CircleLayer(const Impl&); + CircleLayer(const CircleLayer&) = delete; +}; + +template <> +inline bool Layer::is<CircleLayer>() const { + return type == Type::Circle; +} + +} // namespace mbgl diff --git a/include/mbgl/layer/custom_layer.hpp b/include/mbgl/layer/custom_layer.hpp new file mode 100644 index 0000000000..81e91ddf50 --- /dev/null +++ b/include/mbgl/layer/custom_layer.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include <mbgl/style/layer.hpp> + +namespace mbgl { + +class CustomLayer : public Layer { +public: + CustomLayer(const std::string& id, + CustomLayerInitializeFunction, + CustomLayerRenderFunction, + CustomLayerDeinitializeFunction, + void* context); + ~CustomLayer() final; + + // Private implementation + + class Impl; + Impl* impl; + + CustomLayer(const Impl&); + CustomLayer(const CustomLayer&) = delete; +}; + +template <> +inline bool Layer::is<CustomLayer>() const { + return type == Type::Custom; +} + +} // namespace mbgl diff --git a/include/mbgl/layer/fill_layer.hpp b/include/mbgl/layer/fill_layer.hpp new file mode 100644 index 0000000000..dc0752f9e2 --- /dev/null +++ b/include/mbgl/layer/fill_layer.hpp @@ -0,0 +1,57 @@ +// This file is generated. Do not edit. + +#pragma once + +#include <mbgl/style/layer.hpp> + +namespace mbgl { + +class FillLayer : public Layer { +public: + FillLayer(const std::string& layerID); + ~FillLayer() final; + + // Source + + void setSource(const std::string& sourceID, const std::string& sourceLayer); + const std::string& getSourceID() const; + const std::string& getSourceLayer() const; + + // Paint properties + + Function<bool> getFillAntialias() const; + void setFillAntialias(Function<bool>); + + Function<float> getFillOpacity() const; + void setFillOpacity(Function<float>); + + Function<Color> getFillColor() const; + void setFillColor(Function<Color>); + + Function<Color> getFillOutlineColor() const; + void setFillOutlineColor(Function<Color>); + + Function<std::array<float, 2>> getFillTranslate() const; + void setFillTranslate(Function<std::array<float, 2>>); + + Function<TranslateAnchorType> getFillTranslateAnchor() const; + void setFillTranslateAnchor(Function<TranslateAnchorType>); + + Function<std::string> getFillPattern() const; + void setFillPattern(Function<std::string>); + + // Private implementation + + class Impl; + Impl* const impl; + + FillLayer(const Impl&); + FillLayer(const FillLayer&) = delete; +}; + +template <> +inline bool Layer::is<FillLayer>() const { + return type == Type::Fill; +} + +} // namespace mbgl diff --git a/include/mbgl/layer/line_layer.hpp b/include/mbgl/layer/line_layer.hpp new file mode 100644 index 0000000000..0f898d3c69 --- /dev/null +++ b/include/mbgl/layer/line_layer.hpp @@ -0,0 +1,82 @@ +// This file is generated. Do not edit. + +#pragma once + +#include <mbgl/style/layer.hpp> + +#include <vector> + +namespace mbgl { + +class LineLayer : public Layer { +public: + LineLayer(const std::string& layerID); + ~LineLayer() final; + + // Source + + void setSource(const std::string& sourceID, const std::string& sourceLayer); + const std::string& getSourceID() const; + const std::string& getSourceLayer() const; + + // Layout properties + + Function<LineCapType> getLineCap() const; + void setLineCap(Function<LineCapType>); + + Function<LineJoinType> getLineJoin() const; + void setLineJoin(Function<LineJoinType>); + + Function<float> getLineMiterLimit() const; + void setLineMiterLimit(Function<float>); + + Function<float> getLineRoundLimit() const; + void setLineRoundLimit(Function<float>); + + // Paint properties + + Function<float> getLineOpacity() const; + void setLineOpacity(Function<float>); + + Function<Color> getLineColor() const; + void setLineColor(Function<Color>); + + Function<std::array<float, 2>> getLineTranslate() const; + void setLineTranslate(Function<std::array<float, 2>>); + + Function<TranslateAnchorType> getLineTranslateAnchor() const; + void setLineTranslateAnchor(Function<TranslateAnchorType>); + + Function<float> getLineWidth() const; + void setLineWidth(Function<float>); + + Function<float> getLineGapWidth() const; + void setLineGapWidth(Function<float>); + + Function<float> getLineOffset() const; + void setLineOffset(Function<float>); + + Function<float> getLineBlur() const; + void setLineBlur(Function<float>); + + Function<std::vector<float>> getLineDasharray() const; + void setLineDasharray(Function<std::vector<float>>); + + Function<std::string> getLinePattern() const; + void setLinePattern(Function<std::string>); + + // Private implementation + + class Impl; + Impl* const impl; + + LineLayer(const Impl&); + LineLayer(const LineLayer&) = delete; +}; + +template <> +inline bool Layer::is<LineLayer>() const { + return type == Type::Line; +} + +} // namespace mbgl diff --git a/include/mbgl/layer/raster_layer.hpp b/include/mbgl/layer/raster_layer.hpp new file mode 100644 index 0000000000..9dc27a274a --- /dev/null +++ b/include/mbgl/layer/raster_layer.hpp @@ -0,0 +1,56 @@ +// This file is generated. Do not edit. + +#pragma once + +#include <mbgl/style/layer.hpp> + +namespace mbgl { + +class RasterLayer : public Layer { +public: + RasterLayer(const std::string& layerID); + ~RasterLayer() final; + + // Source + + void setSource(const std::string& sourceID); + const std::string& getSourceID() const; + + // Paint properties + + Function<float> getRasterOpacity() const; + void setRasterOpacity(Function<float>); + + Function<float> getRasterHueRotate() const; + void setRasterHueRotate(Function<float>); + + Function<float> getRasterBrightnessMin() const; + void setRasterBrightnessMin(Function<float>); + + Function<float> getRasterBrightnessMax() const; + void setRasterBrightnessMax(Function<float>); + + Function<float> getRasterSaturation() const; + void setRasterSaturation(Function<float>); + + Function<float> getRasterContrast() const; + void setRasterContrast(Function<float>); + + Function<float> getRasterFadeDuration() const; + void setRasterFadeDuration(Function<float>); + + // Private implementation + + class Impl; + Impl* const impl; + + RasterLayer(const Impl&); + RasterLayer(const RasterLayer&) = delete; +}; + +template <> +inline bool Layer::is<RasterLayer>() const { + return type == Type::Raster; +} + +} // namespace mbgl diff --git a/include/mbgl/layer/symbol_layer.hpp b/include/mbgl/layer/symbol_layer.hpp new file mode 100644 index 0000000000..f9b2956390 --- /dev/null +++ b/include/mbgl/layer/symbol_layer.hpp @@ -0,0 +1,175 @@ +// This file is generated. Do not edit. + +#pragma once + +#include <mbgl/style/layer.hpp> + +#include <vector> + +namespace mbgl { + +class SymbolLayer : public Layer { +public: + SymbolLayer(const std::string& layerID); + ~SymbolLayer() final; + + // Source + + void setSource(const std::string& sourceID, const std::string& sourceLayer); + const std::string& getSourceID() const; + const std::string& getSourceLayer() const; + + // Layout properties + + Function<SymbolPlacementType> getSymbolPlacement() const; + void setSymbolPlacement(Function<SymbolPlacementType>); + + Function<float> getSymbolSpacing() const; + void setSymbolSpacing(Function<float>); + + Function<bool> getSymbolAvoidEdges() const; + void setSymbolAvoidEdges(Function<bool>); + + Function<bool> getIconAllowOverlap() const; + void setIconAllowOverlap(Function<bool>); + + Function<bool> getIconIgnorePlacement() const; + void setIconIgnorePlacement(Function<bool>); + + Function<bool> getIconOptional() const; + void setIconOptional(Function<bool>); + + Function<RotationAlignmentType> getIconRotationAlignment() const; + void setIconRotationAlignment(Function<RotationAlignmentType>); + + Function<float> getIconSize() const; + void setIconSize(Function<float>); + + Function<std::string> getIconImage() const; + void setIconImage(Function<std::string>); + + Function<float> getIconRotate() const; + void setIconRotate(Function<float>); + + Function<float> getIconPadding() const; + void setIconPadding(Function<float>); + + Function<bool> getIconKeepUpright() const; + void setIconKeepUpright(Function<bool>); + + Function<std::array<float, 2>> getIconOffset() const; + void setIconOffset(Function<std::array<float, 2>>); + + Function<RotationAlignmentType> getTextRotationAlignment() const; + void setTextRotationAlignment(Function<RotationAlignmentType>); + + Function<std::string> getTextField() const; + void setTextField(Function<std::string>); + + Function<std::vector<std::string>> getTextFont() const; + void setTextFont(Function<std::vector<std::string>>); + + Function<float> getTextSize() const; + void setTextSize(Function<float>); + + Function<float> getTextMaxWidth() const; + void setTextMaxWidth(Function<float>); + + Function<float> getTextLineHeight() const; + void setTextLineHeight(Function<float>); + + Function<float> getTextLetterSpacing() const; + void setTextLetterSpacing(Function<float>); + + Function<TextJustifyType> getTextJustify() const; + void setTextJustify(Function<TextJustifyType>); + + Function<TextAnchorType> getTextAnchor() const; + void setTextAnchor(Function<TextAnchorType>); + + Function<float> getTextMaxAngle() const; + void setTextMaxAngle(Function<float>); + + Function<float> getTextRotate() const; + void setTextRotate(Function<float>); + + Function<float> getTextPadding() const; + void setTextPadding(Function<float>); + + Function<bool> getTextKeepUpright() const; + void setTextKeepUpright(Function<bool>); + + Function<TextTransformType> getTextTransform() const; + void setTextTransform(Function<TextTransformType>); + + Function<std::array<float, 2>> getTextOffset() const; + void setTextOffset(Function<std::array<float, 2>>); + + Function<bool> getTextAllowOverlap() const; + void setTextAllowOverlap(Function<bool>); + + Function<bool> getTextIgnorePlacement() const; + void setTextIgnorePlacement(Function<bool>); + + Function<bool> getTextOptional() const; + void setTextOptional(Function<bool>); + + // Paint properties + + Function<float> getIconOpacity() const; + void setIconOpacity(Function<float>); + + Function<Color> getIconColor() const; + void setIconColor(Function<Color>); + + Function<Color> getIconHaloColor() const; + void setIconHaloColor(Function<Color>); + + Function<float> getIconHaloWidth() const; + void setIconHaloWidth(Function<float>); + + Function<float> getIconHaloBlur() const; + void setIconHaloBlur(Function<float>); + + Function<std::array<float, 2>> getIconTranslate() const; + void setIconTranslate(Function<std::array<float, 2>>); + + Function<TranslateAnchorType> getIconTranslateAnchor() const; + void setIconTranslateAnchor(Function<TranslateAnchorType>); + + Function<float> getTextOpacity() const; + void setTextOpacity(Function<float>); + + Function<Color> getTextColor() const; + void setTextColor(Function<Color>); + + Function<Color> getTextHaloColor() const; + void setTextHaloColor(Function<Color>); + + Function<float> getTextHaloWidth() const; + void setTextHaloWidth(Function<float>); + + Function<float> getTextHaloBlur() const; + void setTextHaloBlur(Function<float>); + + Function<std::array<float, 2>> getTextTranslate() const; + void setTextTranslate(Function<std::array<float, 2>>); + + Function<TranslateAnchorType> getTextTranslateAnchor() const; + void setTextTranslateAnchor(Function<TranslateAnchorType>); + + // Private implementation + + class Impl; + Impl* const impl; + + SymbolLayer(const Impl&); + SymbolLayer(const SymbolLayer&) = delete; +}; + +template <> +inline bool Layer::is<SymbolLayer>() const { + return type == Type::Symbol; +} + +} // namespace mbgl diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp new file mode 100644 index 0000000000..e6c33a9784 --- /dev/null +++ b/include/mbgl/style/layer.hpp @@ -0,0 +1,78 @@ +#ifndef MBGL_LAYER +#define MBGL_LAYER + +#include <mbgl/util/noncopyable.hpp> +#include <mbgl/style/types.hpp> + +#include <memory> + +namespace mbgl { + +/** + * The runtime representation of a [layer](https://www.mapbox.com/mapbox-gl-style-spec/#layers) from the Mapbox Style + * Specification. + * + * `Layer` is an abstract base class; concrete derived classes are provided for each layer type. `Layer` contains + * functionality that is common to all layer types: + * + * * Runtime type information: type predicates and casting + * * Accessors for properties common to all layer types: ID, visibility, etc. + * * Cloning and copying + * + * All other functionality lives in the derived classes. To instantiate a layer, create an instance of the desired + * type, passing the ID: + * + * auto circleLayer = std::make_unique<CircleLayer>("my-circle-layer"); + */ +class Layer : public mbgl::util::noncopyable { +public: + virtual ~Layer(); + + // Check whether this layer is of the given subtype. + template <class T> + bool is() const; + + // Dynamically cast this layer to the given subtype. + template <class T> + T* as() { + return is<T>() ? reinterpret_cast<T*>(this) : nullptr; + } + + template <class T> + const T* as() const { + return is<T>() ? reinterpret_cast<const T*>(this) : nullptr; + } + + const std::string& getID() const; + + // Visibility + VisibilityType getVisibility() const; + void setVisibility(VisibilityType); + + // Create a new layer with the specified `id` and `ref`. All other properties + // are copied from this layer. + std::unique_ptr<Layer> copy(const std::string& id, + const std::string& ref) const; + + // Private implementation + class Impl; + const std::unique_ptr<Impl> baseImpl; + +protected: + enum class Type { + Fill, + Line, + Circle, + Symbol, + Raster, + Background, + Custom, + }; + + const Type type; + Layer(Type, std::unique_ptr<Impl>); +}; + +} // namespace mbgl + +#endif diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index 9b03ab8a2d..a852a09a14 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -5,6 +5,7 @@ #include <string> #include <array> #include <vector> +#include <utility> namespace mbgl { @@ -20,6 +21,26 @@ struct FontStackHash { std::size_t operator()(const FontStack&) const; }; +template <typename T> +class Function { +public: + using Stop = std::pair<float, T>; + using Stops = std::vector<Stop>; + + Function(const T& constant) + : stops({{ 0, constant }}) {} + + explicit Function(const Stops& stops_, float base_) + : base(base_), stops(stops_) {} + + float getBase() const { return base; } + const std::vector<std::pair<float, T>>& getStops() const { return stops; } + +private: + float base = 1; + std::vector<std::pair<float, T>> stops; +}; + // ------------------------------------------------------------------------------------------------- enum class SourceType : uint8_t { diff --git a/package.json b/package.json index 4c94cdd391..4fc0da158d 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,11 @@ }, "devDependencies": { "aws-sdk": "^2.3.5", + "csscolorparser": "^1.0.2", + "ejs": "^2.4.1", "express": "^4.11.1", "mapbox-gl-shaders": "mapbox/mapbox-gl-shaders#e032997109c0ead5394ff64f2f0ea6b0f8efdc3f", + "mapbox-gl-style-spec": "^8.5.1", "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#f45fd7aba98650c7f3bf778c9cbbfd3b548a4ee8", "node-gyp": "^3.3.1", "request": "^2.72.0", diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index d694235149..76a9c38c8b 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -4,7 +4,6 @@ #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/style/style_parser.hpp> -#include <mbgl/layer/symbol_layer.hpp> #include <mbgl/text/glyph.hpp> #include <mbgl/util/tile_cover.hpp> #include <mbgl/util/mapbox.hpp> diff --git a/scripts/generate-style-code.js b/scripts/generate-style-code.js new file mode 100644 index 0000000000..2904a1429a --- /dev/null +++ b/scripts/generate-style-code.js @@ -0,0 +1,346 @@ +'use strict'; + +const fs = require('fs'); +const ejs = require('ejs'); +const spec = require('mapbox-gl-style-spec').latest; +var parseCSSColor = require('csscolorparser').parseCSSColor; + +global.camelize = function (str) { + return str.replace(/(?:^|-)(.)/g, function (_, x) { + return x.toUpperCase(); + }); +} + +global.camelizeWithLeadingLowercase = function (str) { + return str.replace(/-(.)/g, function (_, x) { + return x.toUpperCase(); + }); +} + +global.propertyType = function (property) { + if (/-translate-anchor$/.test(property.name)) { + return 'TranslateAnchorType'; + } + if (/-rotation-alignment$/.test(property.name)) { + return 'RotationAlignmentType'; + } + switch (property.type) { + case 'boolean': + return 'bool'; + case 'number': + return 'float'; + case 'string': + return 'std::string'; + case 'enum': + return `${camelize(property.name)}Type`; + case 'color': + return `Color`; + case 'array': + if (property.length) { + return `std::array<${propertyType({type: property.value})}, ${property.length}>`; + } else { + return `std::vector<${propertyType({type: property.value})}>`; + } + default: throw new Error(`unknown type for ${property.name}`) + } +} + +global.defaultValue = function (property) { + switch (property.type) { + case 'number': + return property.default; + case 'string': + return JSON.stringify(property.default || ""); + case 'enum': + return `${propertyType(property)}::${camelize(property.default)}`; + case 'color': + return `{{ ${parseCSSColor(property.default).join(', ')} }}` + case 'array': + const defaults = (property.default || []).map((e) => defaultValue({ type: property.value, default: e })); + if (property.length) { + return `{{ ${defaults.join(', ')} }}`; + } else { + return `{ ${defaults.join(', ')} }`; + } + default: + return property.default; + } +} + +const layerHpp = ejs.compile(`<% + const type = locals.type; + const layoutProperties = locals.layoutProperties; + const paintProperties = locals.paintProperties; +-%> +// This file is generated. Do not edit. + +#pragma once + +#include <mbgl/style/layer.hpp> +<% if (type === 'line' || type === 'symbol') { %> +#include <vector> +<% } -%> + +namespace mbgl { + +class <%- camelize(type) %>Layer : public Layer { +public: + <%- camelize(type) %>Layer(const std::string& layerID); + ~<%- camelize(type) %>Layer() final; + +<% if (type === 'raster') { -%> + // Source + + void setSource(const std::string& sourceID); + const std::string& getSourceID() const; + +<% } else if (type !== 'background') { -%> + // Source + + void setSource(const std::string& sourceID, const std::string& sourceLayer); + const std::string& getSourceID() const; + const std::string& getSourceLayer() const; + +<% } -%> +<% if (layoutProperties.length) { -%> + // Layout properties + +<% for (const property of layoutProperties) { -%> + Function<<%- propertyType(property) %>> get<%- camelize(property.name) %>() const; + void set<%- camelize(property.name) %>(Function<<%- propertyType(property) %>>); + +<% } -%> +<% } -%> + // Paint properties + +<% for (const property of paintProperties) { -%> + Function<<%- propertyType(property) %>> get<%- camelize(property.name) %>() const; + void set<%- camelize(property.name) %>(Function<<%- propertyType(property) %>>); + +<% } -%> + // Private implementation + + class Impl; + Impl* const impl; + + <%- camelize(type) %>Layer(const Impl&); + <%- camelize(type) %>Layer(const <%- camelize(type) %>Layer&) = delete; +}; + +template <> +inline bool Layer::is<<%- camelize(type) %>Layer>() const { + return type == Type::<%- camelize(type) %>; +} + +} // namespace mbgl +`, {strict: true}); + +const layerCpp = ejs.compile(`<% + const type = locals.type; + const layoutProperties = locals.layoutProperties; + const paintProperties = locals.paintProperties; +-%> +// This file is generated. Edit scripts/generate-style-code.js, then run \`make style-code\`. + +#include <mbgl/layer/<%- type %>_layer.hpp> +#include <mbgl/layer/<%- type %>_layer_impl.hpp> + +namespace mbgl { + +<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID) + : Layer(Type::<%- camelize(type) %>, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; +} + +<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const Impl& other) + : Layer(Type::<%- camelize(type) %>, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { +} + +<%- camelize(type) %>Layer::~<%- camelize(type) %>Layer() = default; + +std::unique_ptr<Layer> <%- 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; +} + +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; + 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; +} +<% } -%> + +// Layout properties + +<% for (const property of layoutProperties) { -%> +Function<<%- propertyType(property) %>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const { + return *impl->layout.<%- camelizeWithLeadingLowercase(property.name) %>.parsedValue; +} + +void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(Function<<%- propertyType(property) %>> value) { + impl->layout.<%- camelizeWithLeadingLowercase(property.name) %>.parsedValue = value; +} +<% } -%> + +// Paint properties +<% for (const property of paintProperties) { %> +Function<<%- propertyType(property) %>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const { + return impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.values.at(ClassID::Default); +} + +void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(Function<<%- propertyType(property) %>> value) { + impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.values.emplace(ClassID::Default, value); +} +<% } -%> + +} // namespace mbgl +`, {strict: true}); + +const propertiesHpp = ejs.compile(`<% + const type = locals.type; + const layoutProperties = locals.layoutProperties; + const paintProperties = locals.paintProperties; +-%> +// This file is generated. Edit scripts/generate-style-code.js, then run \`make style-code\`. + +#pragma once + +#include <mbgl/style/layout_property.hpp> +#include <mbgl/style/paint_property.hpp> +#include <mbgl/util/rapidjson.hpp> + +namespace mbgl { + +class StyleCascadeParameters; +class StyleCalculationParameters; + +<% if (layoutProperties.length) { -%> +class <%- camelize(type) %>LayoutProperties { +public: + void parse(const JSValue&); + void recalculate(const StyleCalculationParameters&); + +<% for (const property of layoutProperties) { -%> + LayoutProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> }; +<% } -%> +}; + +<% } -%> +class <%- camelize(type) %>PaintProperties { +public: + void parse(const JSValue&); + void cascade(const StyleCascadeParameters&); + bool recalculate(const StyleCalculationParameters&); + +<% for (const property of paintProperties) { -%> +<% if (/-pattern$/.test(property.name) || property.name === 'line-dasharray') { -%> + PaintProperty<<%- propertyType(property) %>, CrossFadedFunctionEvaluator> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> }; +<% } else if (property.name === 'fill-outline-color') { -%> + PaintProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { {{ 0, 0, 0, -1 }} }; +<% } else { -%> + PaintProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> }; +<% } -%> +<% } -%> +}; + +} // namespace mbgl +`, {strict: true}); + +const propertiesCpp = ejs.compile(`<% + const type = locals.type; + const layoutProperties = locals.layoutProperties; + const paintProperties = locals.paintProperties; +-%> +// This file is generated. Edit scripts/generate-style-code.js, then run \`make style-code\`. + +#include <mbgl/layer/<%- type %>_layer_properties.hpp> + +namespace mbgl { + +<% 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 StyleCalculationParameters& parameters) { +<% for (const property of layoutProperties) { -%> + <%- camelizeWithLeadingLowercase(property.name) %>.calculate(parameters); +<% } -%> +} + +<% } -%> +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 StyleCascadeParameters& parameters) { +<% for (const property of paintProperties) { -%> + <%- camelizeWithLeadingLowercase(property.name) %>.cascade(parameters); +<% } -%> +} + +bool <%- camelize(type) %>PaintProperties::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = false; + +<% for (const property of paintProperties) { -%> + hasTransitions |= <%- camelizeWithLeadingLowercase(property.name) %>.calculate(parameters); +<% } -%> + + return hasTransitions; +} + +} // namespace mbgl +`, {strict: true}); + +for (const type of spec.layer.type.values) { + const layoutProperties = Object.keys(spec[`layout_${type}`]).reduce((memo, name) => { + if (name !== 'visibility') { + spec[`layout_${type}`][name].name = name; + memo.push(spec[`layout_${type}`][name]); + } + return memo; + }, []); + + const paintProperties = Object.keys(spec[`paint_${type}`]).reduce((memo, name) => { + spec[`paint_${type}`][name].name = name; + memo.push(spec[`paint_${type}`][name]); + return memo; + }, []); + + const layer = { + type: type, + layoutProperties: layoutProperties, + paintProperties: paintProperties, + }; + + fs.writeFileSync(`include/mbgl/layer/${type}_layer.hpp`, layerHpp(layer)); + fs.writeFileSync(`src/mbgl/layer/${type}_layer.cpp`, layerCpp(layer)); + + fs.writeFileSync(`src/mbgl/layer/${type}_layer_properties.hpp`, propertiesHpp(layer)); + fs.writeFileSync(`src/mbgl/layer/${type}_layer_properties.cpp`, propertiesCpp(layer)); +} diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index 4d7059f80f..09442b165c 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -7,6 +7,7 @@ #include <mbgl/source/source.hpp> #include <mbgl/style/style.hpp> #include <mbgl/layer/symbol_layer.hpp> +#include <mbgl/layer/symbol_layer_impl.hpp> #include <boost/function_output_iterator.hpp> @@ -108,13 +109,13 @@ void AnnotationManager::updateStyle(Style& style) { source->enabled = true; style.addSource(std::move(source)); - std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(); - layer->id = PointLayerID; - layer->source = SourceID; - layer->sourceLayer = PointLayerID; - layer->layout.iconImage = std::string("{sprite}"); - layer->layout.iconAllowOverlap = true; - layer->spriteAtlas = &spriteAtlas; + std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(PointLayerID); + + layer->setSource(SourceID, PointLayerID); + layer->setIconImage({"{sprite}"}); + layer->setIconAllowOverlap(true); + + layer->impl->spriteAtlas = &spriteAtlas; style.addLayer(std::move(layer)); } diff --git a/src/mbgl/annotation/fill_annotation_impl.cpp b/src/mbgl/annotation/fill_annotation_impl.cpp index 093f53fb91..17bdd9c38e 100644 --- a/src/mbgl/annotation/fill_annotation_impl.cpp +++ b/src/mbgl/annotation/fill_annotation_impl.cpp @@ -16,15 +16,12 @@ void FillAnnotationImpl::updateStyle(Style& style) const { if (style.getLayer(layerID)) return; - std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>(); + std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>(layerID); + layer->setSource(AnnotationManager::SourceID, layerID); - layer->paint.fillOpacity = annotation.opacity; - layer->paint.fillColor = annotation.color; - layer->paint.fillOutlineColor = annotation.outlineColor; - - layer->id = layerID; - layer->source = AnnotationManager::SourceID; - layer->sourceLayer = layer->id; + layer->setFillOpacity(annotation.opacity); + layer->setFillColor(annotation.color); + layer->setFillOutlineColor(annotation.outlineColor); style.addLayer(std::move(layer), AnnotationManager::PointLayerID); } diff --git a/src/mbgl/annotation/line_annotation_impl.cpp b/src/mbgl/annotation/line_annotation_impl.cpp index 5bcc142a5b..11febc7de7 100644 --- a/src/mbgl/annotation/line_annotation_impl.cpp +++ b/src/mbgl/annotation/line_annotation_impl.cpp @@ -16,16 +16,12 @@ void LineAnnotationImpl::updateStyle(Style& style) const { if (style.getLayer(layerID)) return; - std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>(); - layer->layout.lineJoin = LineJoinType::Round; - - layer->paint.lineOpacity = annotation.opacity; - layer->paint.lineWidth = annotation.width; - layer->paint.lineColor = annotation.color; - - layer->id = layerID; - layer->source = AnnotationManager::SourceID; - layer->sourceLayer = layer->id; + std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>(layerID); + layer->setSource(AnnotationManager::SourceID, layerID); + layer->setLineJoin(LineJoinType::Round); + layer->setLineOpacity(annotation.opacity); + layer->setLineWidth(annotation.width); + layer->setLineColor(annotation.color); style.addLayer(std::move(layer), AnnotationManager::PointLayerID); } diff --git a/src/mbgl/annotation/style_sourced_annotation_impl.cpp b/src/mbgl/annotation/style_sourced_annotation_impl.cpp index ae92d917aa..e1e11a664a 100644 --- a/src/mbgl/annotation/style_sourced_annotation_impl.cpp +++ b/src/mbgl/annotation/style_sourced_annotation_impl.cpp @@ -1,7 +1,9 @@ #include <mbgl/annotation/style_sourced_annotation_impl.hpp> #include <mbgl/annotation/annotation_manager.hpp> #include <mbgl/style/style.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/layer/line_layer.hpp> +#include <mbgl/layer/fill_layer.hpp> namespace mbgl { @@ -16,19 +18,21 @@ void StyleSourcedAnnotationImpl::updateStyle(Style& style) const { if (style.getLayer(layerID)) return; - const StyleLayer* sourceLayer = style.getLayer(annotation.layerID); + const Layer* sourceLayer = style.getLayer(annotation.layerID); if (!sourceLayer) return; - std::unique_ptr<StyleLayer> layer = sourceLayer->clone(); - - layer->id = layerID; - layer->ref = ""; - layer->source = AnnotationManager::SourceID; - layer->sourceLayer = layer->id; - layer->visibility = VisibilityType::Visible; - - style.addLayer(std::move(layer), sourceLayer->id); + if (sourceLayer->is<LineLayer>()) { + std::unique_ptr<Layer> layer = sourceLayer->copy(layerID, ""); + layer->as<LineLayer>()->setSource(AnnotationManager::SourceID, layerID); + layer->as<LineLayer>()->setVisibility(VisibilityType::Visible); + style.addLayer(std::move(layer), sourceLayer->getID()); + } else if (sourceLayer->is<FillLayer>()) { + std::unique_ptr<Layer> layer = sourceLayer->copy(layerID, ""); + layer->as<FillLayer>()->setSource(AnnotationManager::SourceID, layerID); + layer->as<FillLayer>()->setVisibility(VisibilityType::Visible); + style.addLayer(std::move(layer), sourceLayer->getID()); + } } const ShapeAnnotationGeometry& StyleSourcedAnnotationImpl::geometry() const { diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index ab451bcd6a..e72aa344fa 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -1,6 +1,7 @@ #include <mbgl/geometry/feature_index.hpp> #include <mbgl/style/style.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/style/layer.hpp> +#include <mbgl/layer/layer_impl.hpp> #include <mbgl/layer/symbol_layer.hpp> #include <mbgl/text/collision_tile.hpp> #include <mbgl/util/constants.hpp> @@ -116,7 +117,7 @@ void FeatureIndex::addFeature( auto styleLayer = style.getLayer(layerID); if (!styleLayer || (!styleLayer->is<SymbolLayer>() && - !styleLayer->queryIntersectsGeometry(queryGeometry, geometryTileFeature->getGeometries(), bearing, pixelsToTileUnits))) { + !styleLayer->baseImpl->queryIntersectsGeometry(queryGeometry, geometryTileFeature->getGeometries(), bearing, pixelsToTileUnits))) { continue; } diff --git a/src/mbgl/layer/background_layer.cpp b/src/mbgl/layer/background_layer.cpp index e2879f786e..8d097344fc 100644 --- a/src/mbgl/layer/background_layer.cpp +++ b/src/mbgl/layer/background_layer.cpp @@ -1,38 +1,55 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + #include <mbgl/layer/background_layer.hpp> -#include <mbgl/renderer/bucket.hpp> +#include <mbgl/layer/background_layer_impl.hpp> namespace mbgl { -std::unique_ptr<StyleLayer> BackgroundLayer::clone() const { - return std::make_unique<BackgroundLayer>(*this); +BackgroundLayer::BackgroundLayer(const std::string& layerID) + : Layer(Type::Background, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; } -void BackgroundLayer::parsePaints(const JSValue& layer) { - paint.backgroundOpacity.parse("background-opacity", layer); - paint.backgroundColor.parse("background-color", layer); - paint.backgroundPattern.parse("background-pattern", layer); +BackgroundLayer::BackgroundLayer(const Impl& other) + : Layer(Type::Background, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { } -void BackgroundLayer::cascade(const StyleCascadeParameters& parameters) { - paint.backgroundOpacity.cascade(parameters); - paint.backgroundColor.cascade(parameters); - paint.backgroundPattern.cascade(parameters); +BackgroundLayer::~BackgroundLayer() = default; + +std::unique_ptr<Layer> BackgroundLayer::Impl::clone() const { + return std::make_unique<BackgroundLayer>(*this); } -bool BackgroundLayer::recalculate(const StyleCalculationParameters& parameters) { - bool hasTransitions = false; - hasTransitions |= paint.backgroundOpacity.calculate(parameters); - hasTransitions |= paint.backgroundColor.calculate(parameters); - hasTransitions |= paint.backgroundPattern.calculate(parameters); +// Layout properties - passes = paint.backgroundOpacity > 0 ? RenderPass::Translucent : RenderPass::None; - return hasTransitions; +// Paint properties + +Function<Color> BackgroundLayer::getBackgroundColor() const { + return impl->paint.backgroundColor.values.at(ClassID::Default); +} + +void BackgroundLayer::setBackgroundColor(Function<Color> value) { + impl->paint.backgroundColor.values.emplace(ClassID::Default, value); +} + +Function<std::string> BackgroundLayer::getBackgroundPattern() const { + return impl->paint.backgroundPattern.values.at(ClassID::Default); +} + +void BackgroundLayer::setBackgroundPattern(Function<std::string> value) { + impl->paint.backgroundPattern.values.emplace(ClassID::Default, value); +} + +Function<float> BackgroundLayer::getBackgroundOpacity() const { + return impl->paint.backgroundOpacity.values.at(ClassID::Default); } -std::unique_ptr<Bucket> BackgroundLayer::createBucket(StyleBucketParameters&) const { - return nullptr; +void BackgroundLayer::setBackgroundOpacity(Function<float> value) { + impl->paint.backgroundOpacity.values.emplace(ClassID::Default, value); } } // namespace mbgl diff --git a/src/mbgl/layer/background_layer.hpp b/src/mbgl/layer/background_layer.hpp deleted file mode 100644 index 39142a3bd3..0000000000 --- a/src/mbgl/layer/background_layer.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include <mbgl/style/style_layer.hpp> -#include <mbgl/style/paint_property.hpp> - -namespace mbgl { - -class BackgroundPaintProperties { -public: - PaintProperty<float> backgroundOpacity { 1.0f }; - PaintProperty<Color> backgroundColor { {{ 0, 0, 0, 1 }} }; - PaintProperty<std::string, CrossFadedFunctionEvaluator> backgroundPattern { "" }; -}; - -class BackgroundLayer : public StyleLayer { -public: - BackgroundLayer() : StyleLayer(Type::Background) {} - std::unique_ptr<StyleLayer> clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; - - void cascade(const StyleCascadeParameters&) override; - bool recalculate(const StyleCalculationParameters&) override; - - std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; - - BackgroundPaintProperties paint; -}; - -template <> -inline bool StyleLayer::is<BackgroundLayer>() const { - return type == Type::Background; -} - -} // namespace mbgl diff --git a/src/mbgl/layer/background_layer_impl.cpp b/src/mbgl/layer/background_layer_impl.cpp new file mode 100644 index 0000000000..626c8fc805 --- /dev/null +++ b/src/mbgl/layer/background_layer_impl.cpp @@ -0,0 +1,26 @@ +#include <mbgl/layer/background_layer_impl.hpp> +#include <mbgl/renderer/bucket.hpp> + +namespace mbgl { + +void BackgroundLayer::Impl::parsePaints(const JSValue& layer) { + paint.parse(layer); +} + +void BackgroundLayer::Impl::cascade(const StyleCascadeParameters& parameters) { + paint.cascade(parameters); +} + +bool BackgroundLayer::Impl::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = paint.recalculate(parameters); + + passes = paint.backgroundOpacity > 0 ? RenderPass::Translucent : RenderPass::None; + + return hasTransitions; +} + +std::unique_ptr<Bucket> BackgroundLayer::Impl::createBucket(StyleBucketParameters&) const { + return nullptr; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/background_layer_impl.hpp b/src/mbgl/layer/background_layer_impl.hpp new file mode 100644 index 0000000000..6af31dd921 --- /dev/null +++ b/src/mbgl/layer/background_layer_impl.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/background_layer.hpp> +#include <mbgl/layer/background_layer_properties.hpp> + +namespace mbgl { + +class BackgroundLayer::Impl : public Layer::Impl { +public: + std::unique_ptr<Layer> clone() const override; + + void parseLayout(const JSValue&) override {}; + void parsePaints(const JSValue&) override; + + void cascade(const StyleCascadeParameters&) override; + bool recalculate(const StyleCalculationParameters&) override; + + std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; + + BackgroundPaintProperties paint; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/background_layer_properties.cpp b/src/mbgl/layer/background_layer_properties.cpp new file mode 100644 index 0000000000..d866df7eee --- /dev/null +++ b/src/mbgl/layer/background_layer_properties.cpp @@ -0,0 +1,29 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/layer/background_layer_properties.hpp> + +namespace mbgl { + +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 StyleCascadeParameters& parameters) { + backgroundColor.cascade(parameters); + backgroundPattern.cascade(parameters); + backgroundOpacity.cascade(parameters); +} + +bool BackgroundPaintProperties::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = false; + + hasTransitions |= backgroundColor.calculate(parameters); + hasTransitions |= backgroundPattern.calculate(parameters); + hasTransitions |= backgroundOpacity.calculate(parameters); + + return hasTransitions; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/background_layer_properties.hpp b/src/mbgl/layer/background_layer_properties.hpp new file mode 100644 index 0000000000..5e388a7928 --- /dev/null +++ b/src/mbgl/layer/background_layer_properties.hpp @@ -0,0 +1,25 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#pragma once + +#include <mbgl/style/layout_property.hpp> +#include <mbgl/style/paint_property.hpp> +#include <mbgl/util/rapidjson.hpp> + +namespace mbgl { + +class StyleCascadeParameters; +class StyleCalculationParameters; + +class BackgroundPaintProperties { +public: + void parse(const JSValue&); + void cascade(const StyleCascadeParameters&); + bool recalculate(const StyleCalculationParameters&); + + PaintProperty<Color> backgroundColor { {{ 0, 0, 0, 1 }} }; + PaintProperty<std::string, CrossFadedFunctionEvaluator> backgroundPattern { "" }; + PaintProperty<float> backgroundOpacity { 1 }; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/circle_layer.cpp b/src/mbgl/layer/circle_layer.cpp index 839d1282a9..bf385c997c 100644 --- a/src/mbgl/layer/circle_layer.cpp +++ b/src/mbgl/layer/circle_layer.cpp @@ -1,81 +1,93 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + #include <mbgl/layer/circle_layer.hpp> -#include <mbgl/style/style_bucket_parameters.hpp> -#include <mbgl/renderer/circle_bucket.hpp> -#include <mbgl/geometry/feature_index.hpp> -#include <mbgl/util/math.hpp> -#include <mbgl/util/intersection_tests.hpp> +#include <mbgl/layer/circle_layer_impl.hpp> namespace mbgl { -std::unique_ptr<StyleLayer> CircleLayer::clone() const { +CircleLayer::CircleLayer(const std::string& layerID) + : Layer(Type::Circle, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; +} + +CircleLayer::CircleLayer(const Impl& other) + : Layer(Type::Circle, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { +} + +CircleLayer::~CircleLayer() = default; + +std::unique_ptr<Layer> CircleLayer::Impl::clone() const { return std::make_unique<CircleLayer>(*this); } -void CircleLayer::parsePaints(const JSValue& layer) { - paint.circleRadius.parse("circle-radius", layer); - paint.circleColor.parse("circle-color", layer); - paint.circleOpacity.parse("circle-opacity", layer); - paint.circleTranslate.parse("circle-translate", layer); - paint.circleTranslateAnchor.parse("circle-translate-anchor", layer); - paint.circleBlur.parse("circle-blur", layer); +// Source + +void CircleLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { + impl->source = sourceID; + impl->sourceLayer = sourceLayer; } -void CircleLayer::cascade(const StyleCascadeParameters& parameters) { - paint.circleRadius.cascade(parameters); - paint.circleColor.cascade(parameters); - paint.circleOpacity.cascade(parameters); - paint.circleTranslate.cascade(parameters); - paint.circleTranslateAnchor.cascade(parameters); - paint.circleBlur.cascade(parameters); +const std::string& CircleLayer::getSourceID() const { + return impl->source; } -bool CircleLayer::recalculate(const StyleCalculationParameters& parameters) { - bool hasTransitions = false; +const std::string& CircleLayer::getSourceLayer() const { + return impl->sourceLayer; +} + +// Layout properties + - hasTransitions |= paint.circleRadius.calculate(parameters); - hasTransitions |= paint.circleColor.calculate(parameters); - hasTransitions |= paint.circleOpacity.calculate(parameters); - hasTransitions |= paint.circleTranslate.calculate(parameters); - hasTransitions |= paint.circleTranslateAnchor.calculate(parameters); - hasTransitions |= paint.circleBlur.calculate(parameters); +// Paint properties - passes = (paint.circleRadius > 0 && paint.circleColor.value[3] > 0 && paint.circleOpacity > 0) - ? RenderPass::Translucent : RenderPass::None; +Function<float> CircleLayer::getCircleRadius() const { + return impl->paint.circleRadius.values.at(ClassID::Default); +} + +void CircleLayer::setCircleRadius(Function<float> value) { + impl->paint.circleRadius.values.emplace(ClassID::Default, value); +} + +Function<Color> CircleLayer::getCircleColor() const { + return impl->paint.circleColor.values.at(ClassID::Default); +} - return hasTransitions; +void CircleLayer::setCircleColor(Function<Color> value) { + impl->paint.circleColor.values.emplace(ClassID::Default, value); } -std::unique_ptr<Bucket> CircleLayer::createBucket(StyleBucketParameters& parameters) const { - auto bucket = std::make_unique<CircleBucket>(parameters.mode); +Function<float> CircleLayer::getCircleBlur() const { + return impl->paint.circleBlur.values.at(ClassID::Default); +} - auto& name = bucketName(); - parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) { - auto geometries = feature.getGeometries(); - bucket->addGeometry(geometries); - parameters.featureIndex.insert(geometries, index, layerName, name); - }); +void CircleLayer::setCircleBlur(Function<float> value) { + impl->paint.circleBlur.values.emplace(ClassID::Default, value); +} - return std::move(bucket); +Function<float> CircleLayer::getCircleOpacity() const { + return impl->paint.circleOpacity.values.at(ClassID::Default); } -float CircleLayer::getQueryRadius() const { - const std::array<float, 2>& translate = paint.circleTranslate; - return paint.circleRadius + util::length(translate[0], translate[1]); +void CircleLayer::setCircleOpacity(Function<float> value) { + impl->paint.circleOpacity.values.emplace(ClassID::Default, value); } -bool CircleLayer::queryIntersectsGeometry( - const GeometryCollection& queryGeometry, - const GeometryCollection& geometry, - const float bearing, - const float pixelsToTileUnits) const { +Function<std::array<float, 2>> CircleLayer::getCircleTranslate() const { + return impl->paint.circleTranslate.values.at(ClassID::Default); +} - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( - queryGeometry, paint.circleTranslate, paint.circleTranslateAnchor, bearing, pixelsToTileUnits); +void CircleLayer::setCircleTranslate(Function<std::array<float, 2>> value) { + impl->paint.circleTranslate.values.emplace(ClassID::Default, value); +} - auto circleRadius = paint.circleRadius * pixelsToTileUnits; +Function<TranslateAnchorType> CircleLayer::getCircleTranslateAnchor() const { + return impl->paint.circleTranslateAnchor.values.at(ClassID::Default); +} - return util::multiPolygonIntersectsBufferedMultiPoint( - translatedQueryGeometry.value_or(queryGeometry), geometry, circleRadius); +void CircleLayer::setCircleTranslateAnchor(Function<TranslateAnchorType> value) { + impl->paint.circleTranslateAnchor.values.emplace(ClassID::Default, value); } } // namespace mbgl diff --git a/src/mbgl/layer/circle_layer.hpp b/src/mbgl/layer/circle_layer.hpp deleted file mode 100644 index 543bae8f19..0000000000 --- a/src/mbgl/layer/circle_layer.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include <mbgl/style/style_layer.hpp> -#include <mbgl/style/paint_property.hpp> - -namespace mbgl { - -class CirclePaintProperties { -public: - PaintProperty<float> circleRadius { 5.0f }; - PaintProperty<Color> circleColor { {{ 0, 0, 0, 1 }} }; - PaintProperty<float> circleOpacity { 1.0f }; - PaintProperty<std::array<float, 2>> circleTranslate { {{ 0, 0 }} }; - PaintProperty<TranslateAnchorType> circleTranslateAnchor { TranslateAnchorType::Map }; - PaintProperty<float> circleBlur { 0 }; -}; - -class CircleLayer : public StyleLayer { -public: - CircleLayer() : StyleLayer(Type::Circle) {} - std::unique_ptr<StyleLayer> clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; - - void cascade(const StyleCascadeParameters&) override; - bool recalculate(const StyleCalculationParameters&) override; - - std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; - - float getQueryRadius() const override; - bool queryIntersectsGeometry( - const GeometryCollection& queryGeometry, - const GeometryCollection& geometry, - const float bearing, - const float pixelsToTileUnits) const override; - - CirclePaintProperties paint; -}; - -template <> -inline bool StyleLayer::is<CircleLayer>() const { - return type == Type::Circle; -} - -} // namespace mbgl diff --git a/src/mbgl/layer/circle_layer_impl.cpp b/src/mbgl/layer/circle_layer_impl.cpp new file mode 100644 index 0000000000..b1ba778cd6 --- /dev/null +++ b/src/mbgl/layer/circle_layer_impl.cpp @@ -0,0 +1,60 @@ +#include <mbgl/layer/circle_layer_impl.hpp> +#include <mbgl/style/style_bucket_parameters.hpp> +#include <mbgl/renderer/circle_bucket.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/util/intersection_tests.hpp> + +namespace mbgl { + +void CircleLayer::Impl::parsePaints(const JSValue& layer) { + paint.parse(layer); +} + +void CircleLayer::Impl::cascade(const StyleCascadeParameters& parameters) { + paint.cascade(parameters); +} + +bool CircleLayer::Impl::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = paint.recalculate(parameters); + + passes = (paint.circleRadius > 0 && paint.circleColor.value[3] > 0 && paint.circleOpacity > 0) + ? RenderPass::Translucent : RenderPass::None; + + return hasTransitions; +} + +std::unique_ptr<Bucket> CircleLayer::Impl::createBucket(StyleBucketParameters& parameters) const { + auto bucket = std::make_unique<CircleBucket>(parameters.mode); + + auto& name = bucketName(); + parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) { + auto geometries = feature.getGeometries(); + bucket->addGeometry(geometries); + parameters.featureIndex.insert(geometries, index, layerName, name); + }); + + return std::move(bucket); +} + +float CircleLayer::Impl::getQueryRadius() const { + const std::array<float, 2>& translate = paint.circleTranslate; + return paint.circleRadius + util::length(translate[0], translate[1]); +} + +bool CircleLayer::Impl::queryIntersectsGeometry( + const GeometryCollection& queryGeometry, + const GeometryCollection& geometry, + const float bearing, + const float pixelsToTileUnits) const { + + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, paint.circleTranslate, paint.circleTranslateAnchor, bearing, pixelsToTileUnits); + + auto circleRadius = paint.circleRadius * pixelsToTileUnits; + + return util::multiPolygonIntersectsBufferedMultiPoint( + translatedQueryGeometry.value_or(queryGeometry), geometry, circleRadius); +} + +} // namespace mbgl diff --git a/src/mbgl/layer/circle_layer_impl.hpp b/src/mbgl/layer/circle_layer_impl.hpp new file mode 100644 index 0000000000..1cb19a6205 --- /dev/null +++ b/src/mbgl/layer/circle_layer_impl.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/circle_layer.hpp> +#include <mbgl/layer/circle_layer_properties.hpp> + +namespace mbgl { + +class CircleLayer::Impl : public Layer::Impl { +public: + std::unique_ptr<Layer> clone() const override; + + void parseLayout(const JSValue&) override {}; + void parsePaints(const JSValue&) override; + + void cascade(const StyleCascadeParameters&) override; + bool recalculate(const StyleCalculationParameters&) override; + + std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; + + float getQueryRadius() const override; + bool queryIntersectsGeometry( + const GeometryCollection& queryGeometry, + const GeometryCollection& geometry, + const float bearing, + const float pixelsToTileUnits) const override; + + CirclePaintProperties paint; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/circle_layer_properties.cpp b/src/mbgl/layer/circle_layer_properties.cpp new file mode 100644 index 0000000000..48d99b579e --- /dev/null +++ b/src/mbgl/layer/circle_layer_properties.cpp @@ -0,0 +1,38 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/layer/circle_layer_properties.hpp> + +namespace mbgl { + +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 StyleCascadeParameters& parameters) { + circleRadius.cascade(parameters); + circleColor.cascade(parameters); + circleBlur.cascade(parameters); + circleOpacity.cascade(parameters); + circleTranslate.cascade(parameters); + circleTranslateAnchor.cascade(parameters); +} + +bool CirclePaintProperties::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = false; + + hasTransitions |= circleRadius.calculate(parameters); + hasTransitions |= circleColor.calculate(parameters); + hasTransitions |= circleBlur.calculate(parameters); + hasTransitions |= circleOpacity.calculate(parameters); + hasTransitions |= circleTranslate.calculate(parameters); + hasTransitions |= circleTranslateAnchor.calculate(parameters); + + return hasTransitions; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/circle_layer_properties.hpp b/src/mbgl/layer/circle_layer_properties.hpp new file mode 100644 index 0000000000..a88db27605 --- /dev/null +++ b/src/mbgl/layer/circle_layer_properties.hpp @@ -0,0 +1,28 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#pragma once + +#include <mbgl/style/layout_property.hpp> +#include <mbgl/style/paint_property.hpp> +#include <mbgl/util/rapidjson.hpp> + +namespace mbgl { + +class StyleCascadeParameters; +class StyleCalculationParameters; + +class CirclePaintProperties { +public: + void parse(const JSValue&); + void cascade(const StyleCascadeParameters&); + bool recalculate(const StyleCalculationParameters&); + + PaintProperty<float> circleRadius { 5 }; + PaintProperty<Color> circleColor { {{ 0, 0, 0, 1 }} }; + PaintProperty<float> circleBlur { 0 }; + PaintProperty<float> circleOpacity { 1 }; + PaintProperty<std::array<float, 2>> circleTranslate { {{ 0, 0 }} }; + PaintProperty<TranslateAnchorType> circleTranslateAnchor { TranslateAnchorType::Map }; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/custom_layer.cpp b/src/mbgl/layer/custom_layer.cpp index 3b683bf833..a33176e7f9 100644 --- a/src/mbgl/layer/custom_layer.cpp +++ b/src/mbgl/layer/custom_layer.cpp @@ -1,67 +1,22 @@ #include <mbgl/layer/custom_layer.hpp> -#include <mbgl/renderer/bucket.hpp> -#include <mbgl/map/transform_state.hpp> +#include <mbgl/layer/custom_layer_impl.hpp> namespace mbgl { -CustomLayer::CustomLayer(const std::string& id_, - CustomLayerInitializeFunction initializeFn_, - CustomLayerRenderFunction renderFn_, - CustomLayerDeinitializeFunction deinitializeFn_, - void* context_) - : StyleLayer(Type::Custom) { - id = id_; - initializeFn = initializeFn_; - renderFn = renderFn_; - deinitializeFn = deinitializeFn_; - context = context_; +CustomLayer::CustomLayer(const std::string& layerID, + CustomLayerInitializeFunction init, + CustomLayerRenderFunction render, + CustomLayerDeinitializeFunction deinit, + void* context) + : Layer(Type::Custom, std::make_unique<Impl>(layerID, init, render, deinit, context)) + , impl(static_cast<Impl*>(baseImpl.get())) { } -CustomLayer::CustomLayer(const CustomLayer& other) - : StyleLayer(other) { - id = other.id; - // Don't copy anything else. +CustomLayer::CustomLayer(const Impl& other) + : Layer(Type::Custom, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { } -CustomLayer::~CustomLayer() { - if (deinitializeFn) { - deinitializeFn(context); - } -} - -void CustomLayer::initialize() { - assert(initializeFn); - initializeFn(context); -} - -void CustomLayer::render(const TransformState& state) const { - assert(renderFn); - - CustomLayerRenderParameters parameters; - - parameters.width = state.getWidth(); - parameters.height = state.getHeight(); - parameters.latitude = state.getLatLng().latitude; - parameters.longitude = state.getLatLng().longitude; - parameters.zoom = state.getZoom(); - parameters.bearing = -state.getAngle() * util::RAD2DEG; - parameters.pitch = state.getPitch(); - parameters.altitude = state.getAltitude(); - - renderFn(context, parameters); -} - -bool CustomLayer::recalculate(const StyleCalculationParameters&) { - passes = RenderPass::Translucent; - return false; -} - -std::unique_ptr<StyleLayer> CustomLayer::clone() const { - return std::make_unique<CustomLayer>(*this); -} - -std::unique_ptr<Bucket> CustomLayer::createBucket(StyleBucketParameters&) const { - return nullptr; -} +CustomLayer::~CustomLayer() = default; } // namespace mbgl diff --git a/src/mbgl/layer/custom_layer_impl.cpp b/src/mbgl/layer/custom_layer_impl.cpp new file mode 100644 index 0000000000..8a08c804ed --- /dev/null +++ b/src/mbgl/layer/custom_layer_impl.cpp @@ -0,0 +1,66 @@ +#include <mbgl/layer/custom_layer_impl.hpp> +#include <mbgl/renderer/bucket.hpp> +#include <mbgl/map/transform_state.hpp> + +namespace mbgl { + +CustomLayer::Impl::Impl(const std::string& id_, + CustomLayerInitializeFunction initializeFn_, + CustomLayerRenderFunction renderFn_, + CustomLayerDeinitializeFunction deinitializeFn_, + void* context_) { + id = id_; + initializeFn = initializeFn_; + renderFn = renderFn_; + deinitializeFn = deinitializeFn_; + context = context_; +} + +CustomLayer::Impl::Impl(const CustomLayer::Impl& other) + : Layer::Impl(other) { + id = other.id; + // Don't copy anything else. +} + +CustomLayer::Impl::~Impl() { + if (deinitializeFn) { + deinitializeFn(context); + } +} + +std::unique_ptr<Layer> CustomLayer::Impl::clone() const { + return std::make_unique<CustomLayer>(*this); +} + +void CustomLayer::Impl::initialize() { + assert(initializeFn); + initializeFn(context); +} + +void CustomLayer::Impl::render(const TransformState& state) const { + assert(renderFn); + + CustomLayerRenderParameters parameters; + + parameters.width = state.getWidth(); + parameters.height = state.getHeight(); + parameters.latitude = state.getLatLng().latitude; + parameters.longitude = state.getLatLng().longitude; + parameters.zoom = state.getZoom(); + parameters.bearing = -state.getAngle() * util::RAD2DEG; + parameters.pitch = state.getPitch(); + parameters.altitude = state.getAltitude(); + + renderFn(context, parameters); +} + +bool CustomLayer::Impl::recalculate(const StyleCalculationParameters&) { + passes = RenderPass::Translucent; + return false; +} + +std::unique_ptr<Bucket> CustomLayer::Impl::createBucket(StyleBucketParameters&) const { + return nullptr; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/custom_layer.hpp b/src/mbgl/layer/custom_layer_impl.hpp index 93d9c85e6c..09709a2f9d 100644 --- a/src/mbgl/layer/custom_layer.hpp +++ b/src/mbgl/layer/custom_layer_impl.hpp @@ -1,27 +1,28 @@ #pragma once -#include <mbgl/style/style_layer.hpp> +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/custom_layer.hpp> namespace mbgl { class TransformState; -class CustomLayer : public StyleLayer { +class CustomLayer::Impl : public Layer::Impl { public: - CustomLayer(const std::string& id, - CustomLayerInitializeFunction, - CustomLayerRenderFunction, - CustomLayerDeinitializeFunction, - void* context); + Impl(const std::string& id, + CustomLayerInitializeFunction, + CustomLayerRenderFunction, + CustomLayerDeinitializeFunction, + void* context); - CustomLayer(const CustomLayer&); - ~CustomLayer(); + Impl(const Impl&); + ~Impl() final; void initialize(); void render(const TransformState&) const; private: - std::unique_ptr<StyleLayer> clone() const final; + std::unique_ptr<Layer> clone() const override; void parseLayout(const JSValue&) final {} void parsePaints(const JSValue&) final {} @@ -37,9 +38,4 @@ private: void* context = nullptr; }; -template <> -inline bool StyleLayer::is<CustomLayer>() const { - return type == Type::Custom; -} - } // namespace mbgl diff --git a/src/mbgl/layer/fill_layer.cpp b/src/mbgl/layer/fill_layer.cpp index 850bac4ab4..9a376089df 100644 --- a/src/mbgl/layer/fill_layer.cpp +++ b/src/mbgl/layer/fill_layer.cpp @@ -1,90 +1,101 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + #include <mbgl/layer/fill_layer.hpp> -#include <mbgl/style/style_bucket_parameters.hpp> -#include <mbgl/renderer/fill_bucket.hpp> -#include <mbgl/geometry/feature_index.hpp> -#include <mbgl/util/math.hpp> -#include <mbgl/util/intersection_tests.hpp> +#include <mbgl/layer/fill_layer_impl.hpp> namespace mbgl { -std::unique_ptr<StyleLayer> FillLayer::clone() const { +FillLayer::FillLayer(const std::string& layerID) + : Layer(Type::Fill, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; +} + +FillLayer::FillLayer(const Impl& other) + : Layer(Type::Fill, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { +} + +FillLayer::~FillLayer() = default; + +std::unique_ptr<Layer> FillLayer::Impl::clone() const { return std::make_unique<FillLayer>(*this); } -void FillLayer::parsePaints(const JSValue& layer) { - paint.fillAntialias.parse("fill-antialias", layer); - paint.fillOpacity.parse("fill-opacity", layer); - paint.fillColor.parse("fill-color", layer); - paint.fillOutlineColor.parse("fill-outline-color", layer); - paint.fillTranslate.parse("fill-translate", layer); - paint.fillTranslateAnchor.parse("fill-translate-anchor", layer); - paint.fillPattern.parse("fill-pattern", layer); +// Source + +void FillLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { + impl->source = sourceID; + impl->sourceLayer = sourceLayer; } -void FillLayer::cascade(const StyleCascadeParameters& parameters) { - paint.fillAntialias.cascade(parameters); - paint.fillOpacity.cascade(parameters); - paint.fillColor.cascade(parameters); - paint.fillOutlineColor.cascade(parameters); - paint.fillTranslate.cascade(parameters); - paint.fillTranslateAnchor.cascade(parameters); - paint.fillPattern.cascade(parameters); +const std::string& FillLayer::getSourceID() const { + return impl->source; } -bool FillLayer::recalculate(const StyleCalculationParameters& parameters) { - bool hasTransitions = false; +const std::string& FillLayer::getSourceLayer() const { + return impl->sourceLayer; +} - hasTransitions |= paint.fillAntialias.calculate(parameters); - hasTransitions |= paint.fillOpacity.calculate(parameters); - hasTransitions |= paint.fillColor.calculate(parameters); - hasTransitions |= paint.fillOutlineColor.calculate(parameters); - hasTransitions |= paint.fillTranslate.calculate(parameters); - hasTransitions |= paint.fillTranslateAnchor.calculate(parameters); - hasTransitions |= paint.fillPattern.calculate(parameters); +// Layout properties - passes = RenderPass::None; - if (paint.fillAntialias) { - passes |= RenderPass::Translucent; - } +// Paint properties - if (!paint.fillPattern.value.from.empty() || (paint.fillColor.value[3] * paint.fillOpacity) < 1.0f) { - passes |= RenderPass::Translucent; - } else { - passes |= RenderPass::Opaque; - } +Function<bool> FillLayer::getFillAntialias() const { + return impl->paint.fillAntialias.values.at(ClassID::Default); +} - return hasTransitions; +void FillLayer::setFillAntialias(Function<bool> value) { + impl->paint.fillAntialias.values.emplace(ClassID::Default, value); } -std::unique_ptr<Bucket> FillLayer::createBucket(StyleBucketParameters& parameters) const { - auto bucket = std::make_unique<FillBucket>(); +Function<float> FillLayer::getFillOpacity() const { + return impl->paint.fillOpacity.values.at(ClassID::Default); +} - auto& name = bucketName(); - parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) { - auto geometries = feature.getGeometries(); - bucket->addGeometry(geometries); - parameters.featureIndex.insert(geometries, index, layerName, name); - }); +void FillLayer::setFillOpacity(Function<float> value) { + impl->paint.fillOpacity.values.emplace(ClassID::Default, value); +} - return std::move(bucket); +Function<Color> FillLayer::getFillColor() const { + return impl->paint.fillColor.values.at(ClassID::Default); } -float FillLayer::getQueryRadius() const { - const std::array<float, 2>& translate = paint.fillTranslate; - return util::length(translate[0], translate[1]); +void FillLayer::setFillColor(Function<Color> value) { + impl->paint.fillColor.values.emplace(ClassID::Default, value); } -bool FillLayer::queryIntersectsGeometry( - const GeometryCollection& queryGeometry, - const GeometryCollection& geometry, - const float bearing, - const float pixelsToTileUnits) const { +Function<Color> FillLayer::getFillOutlineColor() const { + return impl->paint.fillOutlineColor.values.at(ClassID::Default); +} - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( - queryGeometry, paint.fillTranslate, paint.fillTranslateAnchor, bearing, pixelsToTileUnits); +void FillLayer::setFillOutlineColor(Function<Color> value) { + impl->paint.fillOutlineColor.values.emplace(ClassID::Default, value); +} + +Function<std::array<float, 2>> FillLayer::getFillTranslate() const { + return impl->paint.fillTranslate.values.at(ClassID::Default); +} + +void FillLayer::setFillTranslate(Function<std::array<float, 2>> value) { + impl->paint.fillTranslate.values.emplace(ClassID::Default, value); +} + +Function<TranslateAnchorType> FillLayer::getFillTranslateAnchor() const { + return impl->paint.fillTranslateAnchor.values.at(ClassID::Default); +} + +void FillLayer::setFillTranslateAnchor(Function<TranslateAnchorType> value) { + impl->paint.fillTranslateAnchor.values.emplace(ClassID::Default, value); +} + +Function<std::string> FillLayer::getFillPattern() const { + return impl->paint.fillPattern.values.at(ClassID::Default); +} - return util::multiPolygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), geometry); +void FillLayer::setFillPattern(Function<std::string> value) { + impl->paint.fillPattern.values.emplace(ClassID::Default, value); } } // namespace mbgl diff --git a/src/mbgl/layer/fill_layer.hpp b/src/mbgl/layer/fill_layer.hpp deleted file mode 100644 index eb8a507239..0000000000 --- a/src/mbgl/layer/fill_layer.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include <mbgl/style/style_layer.hpp> -#include <mbgl/style/paint_property.hpp> - -namespace mbgl { - -class FillPaintProperties { -public: - PaintProperty<bool> fillAntialias { true }; - PaintProperty<float> fillOpacity { 1.0f }; - PaintProperty<Color> fillColor { {{ 0, 0, 0, 1 }} }; - PaintProperty<Color> fillOutlineColor { {{ 0, 0, 0, -1 }} }; - PaintProperty<std::array<float, 2>> fillTranslate { {{ 0, 0 }} }; - PaintProperty<TranslateAnchorType> fillTranslateAnchor { TranslateAnchorType::Map }; - PaintProperty<std::string, CrossFadedFunctionEvaluator> fillPattern { "" }; -}; - -class FillLayer : public StyleLayer { -public: - FillLayer() : StyleLayer(Type::Fill) {} - std::unique_ptr<StyleLayer> clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; - - void cascade(const StyleCascadeParameters&) override; - bool recalculate(const StyleCalculationParameters&) override; - - std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; - - float getQueryRadius() const override; - bool queryIntersectsGeometry( - const GeometryCollection& queryGeometry, - const GeometryCollection& geometry, - const float bearing, - const float pixelsToTileUnits) const override; - - FillPaintProperties paint; -}; - -template <> -inline bool StyleLayer::is<FillLayer>() const { - return type == Type::Fill; -} - -} // namespace mbgl diff --git a/src/mbgl/layer/fill_layer_impl.cpp b/src/mbgl/layer/fill_layer_impl.cpp new file mode 100644 index 0000000000..21f482922d --- /dev/null +++ b/src/mbgl/layer/fill_layer_impl.cpp @@ -0,0 +1,66 @@ +#include <mbgl/layer/fill_layer_impl.hpp> +#include <mbgl/style/style_bucket_parameters.hpp> +#include <mbgl/renderer/fill_bucket.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/util/intersection_tests.hpp> + +namespace mbgl { + +void FillLayer::Impl::parsePaints(const JSValue& layer) { + paint.parse(layer); +} + +void FillLayer::Impl::cascade(const StyleCascadeParameters& parameters) { + paint.cascade(parameters); +} + +bool FillLayer::Impl::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = paint.recalculate(parameters); + + passes = RenderPass::None; + + if (paint.fillAntialias) { + passes |= RenderPass::Translucent; + } + + if (!paint.fillPattern.value.from.empty() || (paint.fillColor.value[3] * paint.fillOpacity) < 1.0f) { + passes |= RenderPass::Translucent; + } else { + passes |= RenderPass::Opaque; + } + + return hasTransitions; +} + +std::unique_ptr<Bucket> FillLayer::Impl::createBucket(StyleBucketParameters& parameters) const { + auto bucket = std::make_unique<FillBucket>(); + + auto& name = bucketName(); + parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) { + auto geometries = feature.getGeometries(); + bucket->addGeometry(geometries); + parameters.featureIndex.insert(geometries, index, layerName, name); + }); + + return std::move(bucket); +} + +float FillLayer::Impl::getQueryRadius() const { + const std::array<float, 2>& translate = paint.fillTranslate; + return util::length(translate[0], translate[1]); +} + +bool FillLayer::Impl::queryIntersectsGeometry( + const GeometryCollection& queryGeometry, + const GeometryCollection& geometry, + const float bearing, + const float pixelsToTileUnits) const { + + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, paint.fillTranslate, paint.fillTranslateAnchor, bearing, pixelsToTileUnits); + + return util::multiPolygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), geometry); +} + +} // namespace mbgl diff --git a/src/mbgl/layer/fill_layer_impl.hpp b/src/mbgl/layer/fill_layer_impl.hpp new file mode 100644 index 0000000000..2af0d6491d --- /dev/null +++ b/src/mbgl/layer/fill_layer_impl.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/fill_layer.hpp> +#include <mbgl/layer/fill_layer_properties.hpp> + +namespace mbgl { + +class FillLayer::Impl : public Layer::Impl { +public: + std::unique_ptr<Layer> clone() const override; + + void parseLayout(const JSValue&) override {}; + void parsePaints(const JSValue&) override; + + void cascade(const StyleCascadeParameters&) override; + bool recalculate(const StyleCalculationParameters&) override; + + std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; + + float getQueryRadius() const override; + bool queryIntersectsGeometry( + const GeometryCollection& queryGeometry, + const GeometryCollection& geometry, + const float bearing, + const float pixelsToTileUnits) const override; + + FillPaintProperties paint; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/fill_layer_properties.cpp b/src/mbgl/layer/fill_layer_properties.cpp new file mode 100644 index 0000000000..e0d4f10bc9 --- /dev/null +++ b/src/mbgl/layer/fill_layer_properties.cpp @@ -0,0 +1,41 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/layer/fill_layer_properties.hpp> + +namespace mbgl { + +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 StyleCascadeParameters& parameters) { + fillAntialias.cascade(parameters); + fillOpacity.cascade(parameters); + fillColor.cascade(parameters); + fillOutlineColor.cascade(parameters); + fillTranslate.cascade(parameters); + fillTranslateAnchor.cascade(parameters); + fillPattern.cascade(parameters); +} + +bool FillPaintProperties::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = false; + + hasTransitions |= fillAntialias.calculate(parameters); + hasTransitions |= fillOpacity.calculate(parameters); + hasTransitions |= fillColor.calculate(parameters); + hasTransitions |= fillOutlineColor.calculate(parameters); + hasTransitions |= fillTranslate.calculate(parameters); + hasTransitions |= fillTranslateAnchor.calculate(parameters); + hasTransitions |= fillPattern.calculate(parameters); + + return hasTransitions; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/fill_layer_properties.hpp b/src/mbgl/layer/fill_layer_properties.hpp new file mode 100644 index 0000000000..fb327a2d6c --- /dev/null +++ b/src/mbgl/layer/fill_layer_properties.hpp @@ -0,0 +1,29 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#pragma once + +#include <mbgl/style/layout_property.hpp> +#include <mbgl/style/paint_property.hpp> +#include <mbgl/util/rapidjson.hpp> + +namespace mbgl { + +class StyleCascadeParameters; +class StyleCalculationParameters; + +class FillPaintProperties { +public: + void parse(const JSValue&); + void cascade(const StyleCascadeParameters&); + bool recalculate(const StyleCalculationParameters&); + + PaintProperty<bool> fillAntialias { true }; + PaintProperty<float> fillOpacity { 1 }; + PaintProperty<Color> fillColor { {{ 0, 0, 0, 1 }} }; + PaintProperty<Color> fillOutlineColor { {{ 0, 0, 0, -1 }} }; + PaintProperty<std::array<float, 2>> fillTranslate { {{ 0, 0 }} }; + PaintProperty<TranslateAnchorType> fillTranslateAnchor { TranslateAnchorType::Map }; + PaintProperty<std::string, CrossFadedFunctionEvaluator> fillPattern { "" }; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/layer.cpp b/src/mbgl/layer/layer.cpp new file mode 100644 index 0000000000..154fbfe31f --- /dev/null +++ b/src/mbgl/layer/layer.cpp @@ -0,0 +1,32 @@ +#include <mbgl/style/layer.hpp> +#include <mbgl/layer/layer_impl.hpp> + +namespace mbgl { + +Layer::Layer(Type type_, std::unique_ptr<Impl> baseImpl_) + : baseImpl(std::move(baseImpl_)), type(type_) { +} + +Layer::~Layer() = default; + +const std::string& Layer::getID() const { + return baseImpl->id; +} + +VisibilityType Layer::getVisibility() const { + return baseImpl->visibility; +} + +void Layer::setVisibility(VisibilityType value) { + baseImpl->visibility = value; +} + +std::unique_ptr<Layer> Layer::copy(const std::string& id, + const std::string& ref) const { + std::unique_ptr<Layer> result = baseImpl->clone(); + result->baseImpl->id = id; + result->baseImpl->ref = ref; + return result; +} + +} // namespace mbgl diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/layer/layer_impl.cpp index defdfca110..315a1cb1b1 100644 --- a/src/mbgl/style/style_layer.cpp +++ b/src/mbgl/layer/layer_impl.cpp @@ -1,16 +1,16 @@ -#include <mbgl/style/style_layer.hpp> +#include <mbgl/layer/layer_impl.hpp> namespace mbgl { -const std::string& StyleLayer::bucketName() const { +const std::string& Layer::Impl::bucketName() const { return ref.empty() ? id : ref; } -bool StyleLayer::hasRenderPass(RenderPass pass) const { +bool Layer::Impl::hasRenderPass(RenderPass pass) const { return bool(passes & pass); } -bool StyleLayer::needsRendering() const { +bool Layer::Impl::needsRendering() const { return passes != RenderPass::None && visibility != VisibilityType::None; } diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/layer/layer_impl.hpp index 1388cbcb5a..3d6b5cccfd 100644 --- a/src/mbgl/style/style_layer.hpp +++ b/src/mbgl/layer/layer_impl.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/style/layer.hpp> #include <mbgl/style/types.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/renderer/render_pass.hpp> @@ -18,26 +19,23 @@ class StyleCalculationParameters; class StyleBucketParameters; class Bucket; -class StyleLayer { +/** + * `Layer::Impl` contains the internal implementation of `Layer`: the details that need to be accessible to other parts + * of the code, but hidden from the public API. Like `Layer`, it is an abstract base class, with derived classes for + * each layer type. + * + * Members that are public in `Layer` are part of the public API for all layers. + * Members that are public in `FooLayer` are part of the public API for "foo" layers. + * Members that are public in `Layer::Impl` are part of the internal API for all layers. + * Members that are public in `FooLayer::Impl` are part of the internal API for "foo" layers. + * Members that are private in `FooLayer::Impl` are internal to "foo" layers. + */ +class Layer::Impl { public: - virtual ~StyleLayer() = default; + virtual ~Impl() = default; - // Check whether this layer is of the given subtype. - template <class T> - bool is() const; - - // Dynamically cast this layer to the given subtype. - template <class T> - T* as() { - return is<T>() ? reinterpret_cast<T*>(this) : nullptr; - } - template <class T> - const T* as() const { - return is<T>() ? reinterpret_cast<const T*>(this) : nullptr; - } - - // Create a copy of this layer. - virtual std::unique_ptr<StyleLayer> clone() const = 0; + // Create an identical copy of this layer. + virtual std::unique_ptr<Layer> clone() const = 0; virtual void parseLayout(const JSValue& value) = 0; virtual void parsePaints(const JSValue& value) = 0; @@ -78,21 +76,9 @@ public: VisibilityType visibility = VisibilityType::Visible; protected: - enum class Type { - Fill, - Line, - Circle, - Symbol, - Raster, - Background, - Custom, - }; - - StyleLayer(Type type_) : type(type_) {} - StyleLayer(const StyleLayer&) = default; - StyleLayer& operator=(const StyleLayer&) = delete; - - const Type type; + Impl() = default; + Impl(const Impl&) = default; + Impl& operator=(const Impl&) = delete; // Stores what render passes this layer is currently enabled for. This depends on the // evaluated StyleProperties object and is updated accordingly. diff --git a/src/mbgl/layer/line_layer.cpp b/src/mbgl/layer/line_layer.cpp index d1d377462a..0064a0b8da 100644 --- a/src/mbgl/layer/line_layer.cpp +++ b/src/mbgl/layer/line_layer.cpp @@ -1,156 +1,153 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + #include <mbgl/layer/line_layer.hpp> -#include <mbgl/style/style_bucket_parameters.hpp> -#include <mbgl/renderer/line_bucket.hpp> -#include <mbgl/geometry/feature_index.hpp> -#include <mbgl/util/math.hpp> -#include <mbgl/util/intersection_tests.hpp> +#include <mbgl/layer/line_layer_impl.hpp> namespace mbgl { -std::unique_ptr<StyleLayer> LineLayer::clone() const { +LineLayer::LineLayer(const std::string& layerID) + : Layer(Type::Line, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; +} + +LineLayer::LineLayer(const Impl& other) + : Layer(Type::Line, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { +} + +LineLayer::~LineLayer() = default; + +std::unique_ptr<Layer> LineLayer::Impl::clone() const { return std::make_unique<LineLayer>(*this); } -void LineLayer::parseLayout(const JSValue& value) { - layout.lineCap.parse("line-cap", value); - layout.lineJoin.parse("line-join", value); - layout.lineMiterLimit.parse("line-miter-limit", value); - layout.lineRoundLimit.parse("line-round-limit", value); -} - -void LineLayer::parsePaints(const JSValue& layer) { - paint.lineOpacity.parse("line-opacity", layer); - paint.lineColor.parse("line-color", layer); - paint.lineTranslate.parse("line-translate", layer); - paint.lineTranslateAnchor.parse("line-translate-anchor", layer); - paint.lineWidth.parse("line-width", layer); - paint.lineGapWidth.parse("line-gap-width", layer); - paint.lineOffset.parse("line-offset", layer); - paint.lineBlur.parse("line-blur", layer); - paint.lineDasharray.parse("line-dasharray", layer); - paint.linePattern.parse("line-pattern", layer); +// Source + +void LineLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { + impl->source = sourceID; + impl->sourceLayer = sourceLayer; +} + +const std::string& LineLayer::getSourceID() const { + return impl->source; +} + +const std::string& LineLayer::getSourceLayer() const { + return impl->sourceLayer; +} + +// Layout properties + +Function<LineCapType> LineLayer::getLineCap() const { + return *impl->layout.lineCap.parsedValue; +} + +void LineLayer::setLineCap(Function<LineCapType> value) { + impl->layout.lineCap.parsedValue = value; +} +Function<LineJoinType> LineLayer::getLineJoin() const { + return *impl->layout.lineJoin.parsedValue; +} + +void LineLayer::setLineJoin(Function<LineJoinType> value) { + impl->layout.lineJoin.parsedValue = value; +} +Function<float> LineLayer::getLineMiterLimit() const { + return *impl->layout.lineMiterLimit.parsedValue; } -void LineLayer::cascade(const StyleCascadeParameters& parameters) { - paint.lineOpacity.cascade(parameters); - paint.lineColor.cascade(parameters); - paint.lineTranslate.cascade(parameters); - paint.lineTranslateAnchor.cascade(parameters); - paint.lineWidth.cascade(parameters); - paint.lineGapWidth.cascade(parameters); - paint.lineOffset.cascade(parameters); - paint.lineBlur.cascade(parameters); - paint.lineDasharray.cascade(parameters); - paint.linePattern.cascade(parameters); +void LineLayer::setLineMiterLimit(Function<float> value) { + impl->layout.lineMiterLimit.parsedValue = value; +} +Function<float> LineLayer::getLineRoundLimit() const { + return *impl->layout.lineRoundLimit.parsedValue; } -bool LineLayer::recalculate(const StyleCalculationParameters& parameters) { - // for scaling dasharrays - StyleCalculationParameters dashArrayParams = parameters; - dashArrayParams.z = std::floor(dashArrayParams.z); - paint.lineWidth.calculate(dashArrayParams); - dashLineWidth = paint.lineWidth; +void LineLayer::setLineRoundLimit(Function<float> value) { + impl->layout.lineRoundLimit.parsedValue = value; +} - bool hasTransitions = false; +// Paint properties - hasTransitions |= paint.lineOpacity.calculate(parameters); - hasTransitions |= paint.lineColor.calculate(parameters); - hasTransitions |= paint.lineTranslate.calculate(parameters); - hasTransitions |= paint.lineTranslateAnchor.calculate(parameters); - hasTransitions |= paint.lineWidth.calculate(parameters); - hasTransitions |= paint.lineGapWidth.calculate(parameters); - hasTransitions |= paint.lineOffset.calculate(parameters); - hasTransitions |= paint.lineBlur.calculate(parameters); - hasTransitions |= paint.lineDasharray.calculate(parameters); - hasTransitions |= paint.linePattern.calculate(parameters); +Function<float> LineLayer::getLineOpacity() const { + return impl->paint.lineOpacity.values.at(ClassID::Default); +} - passes = (paint.lineOpacity > 0 && paint.lineColor.value[3] > 0 && paint.lineWidth > 0) - ? RenderPass::Translucent : RenderPass::None; +void LineLayer::setLineOpacity(Function<float> value) { + impl->paint.lineOpacity.values.emplace(ClassID::Default, value); +} - return hasTransitions; +Function<Color> LineLayer::getLineColor() const { + return impl->paint.lineColor.values.at(ClassID::Default); } -std::unique_ptr<Bucket> LineLayer::createBucket(StyleBucketParameters& parameters) const { - auto bucket = std::make_unique<LineBucket>(parameters.tileID.overscaleFactor()); +void LineLayer::setLineColor(Function<Color> value) { + impl->paint.lineColor.values.emplace(ClassID::Default, value); +} - bucket->layout = layout; +Function<std::array<float, 2>> LineLayer::getLineTranslate() const { + return impl->paint.lineTranslate.values.at(ClassID::Default); +} - StyleCalculationParameters p(parameters.tileID.overscaledZ); - bucket->layout.lineCap.calculate(p); - bucket->layout.lineJoin.calculate(p); - bucket->layout.lineMiterLimit.calculate(p); - bucket->layout.lineRoundLimit.calculate(p); +void LineLayer::setLineTranslate(Function<std::array<float, 2>> value) { + impl->paint.lineTranslate.values.emplace(ClassID::Default, value); +} - auto& name = bucketName(); - parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) { - auto geometries = feature.getGeometries(); - bucket->addGeometry(geometries); - parameters.featureIndex.insert(geometries, index, layerName, name); - }); +Function<TranslateAnchorType> LineLayer::getLineTranslateAnchor() const { + return impl->paint.lineTranslateAnchor.values.at(ClassID::Default); +} - return std::move(bucket); +void LineLayer::setLineTranslateAnchor(Function<TranslateAnchorType> value) { + impl->paint.lineTranslateAnchor.values.emplace(ClassID::Default, value); } +Function<float> LineLayer::getLineWidth() const { + return impl->paint.lineWidth.values.at(ClassID::Default); +} -float LineLayer::getLineWidth() const { - if (paint.lineGapWidth > 0) { - return paint.lineGapWidth + 2 * paint.lineWidth; - } else { - return paint.lineWidth; - } +void LineLayer::setLineWidth(Function<float> value) { + impl->paint.lineWidth.values.emplace(ClassID::Default, value); } -optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const double offset) { - if (offset == 0) return {}; +Function<float> LineLayer::getLineGapWidth() const { + return impl->paint.lineGapWidth.values.at(ClassID::Default); +} - GeometryCollection newRings; - Point<double> zero(0, 0); - for (const auto& ring : rings) { - newRings.emplace_back(); - auto& newRing = newRings.back(); +void LineLayer::setLineGapWidth(Function<float> value) { + impl->paint.lineGapWidth.values.emplace(ClassID::Default, value); +} - for (auto i = ring.begin(); i != ring.end(); i++) { - auto& p = *i; - - Point<double> aToB = i == ring.begin() ? - zero : - util::perp(util::unit(convertPoint<double>(p - *(i - 1)))); - Point<double> bToC = i + 1 == ring.end() ? - zero : - util::perp(util::unit(convertPoint<double>(*(i + 1) - p))); - Point<double> extrude = util::unit(aToB + bToC); - - const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y; - extrude *= (1.0 / cosHalfAngle); +Function<float> LineLayer::getLineOffset() const { + return impl->paint.lineOffset.values.at(ClassID::Default); +} - newRing.push_back(convertPoint<int16_t>(extrude * offset) + p); - } - } +void LineLayer::setLineOffset(Function<float> value) { + impl->paint.lineOffset.values.emplace(ClassID::Default, value); +} - return newRings; +Function<float> LineLayer::getLineBlur() const { + return impl->paint.lineBlur.values.at(ClassID::Default); } -float LineLayer::getQueryRadius() const { - const std::array<float, 2>& translate = paint.lineTranslate; - return getLineWidth() / 2.0 + std::abs(paint.lineOffset) + util::length(translate[0], translate[1]); +void LineLayer::setLineBlur(Function<float> value) { + impl->paint.lineBlur.values.emplace(ClassID::Default, value); } -bool LineLayer::queryIntersectsGeometry( - const GeometryCollection& queryGeometry, - const GeometryCollection& geometry, - const float bearing, - const float pixelsToTileUnits) const { +Function<std::vector<float>> LineLayer::getLineDasharray() const { + return impl->paint.lineDasharray.values.at(ClassID::Default); +} - const float halfWidth = getLineWidth() / 2.0 * pixelsToTileUnits; +void LineLayer::setLineDasharray(Function<std::vector<float>> value) { + impl->paint.lineDasharray.values.emplace(ClassID::Default, value); +} - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( - queryGeometry, paint.lineTranslate, paint.lineTranslateAnchor, bearing, pixelsToTileUnits); - auto offsetGeometry = offsetLine(geometry, paint.lineOffset * pixelsToTileUnits); +Function<std::string> LineLayer::getLinePattern() const { + return impl->paint.linePattern.values.at(ClassID::Default); +} - return util::multiPolygonIntersectsBufferedMultiLine( - translatedQueryGeometry.value_or(queryGeometry), - offsetGeometry.value_or(geometry), - halfWidth); +void LineLayer::setLinePattern(Function<std::string> value) { + impl->paint.linePattern.values.emplace(ClassID::Default, value); } } // namespace mbgl diff --git a/src/mbgl/layer/line_layer.hpp b/src/mbgl/layer/line_layer.hpp deleted file mode 100644 index 60bd9fad55..0000000000 --- a/src/mbgl/layer/line_layer.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include <mbgl/style/style_layer.hpp> -#include <mbgl/style/layout_property.hpp> -#include <mbgl/style/paint_property.hpp> - -namespace mbgl { - -class LineLayoutProperties { -public: - LayoutProperty<LineCapType> lineCap { LineCapType::Butt }; - LayoutProperty<LineJoinType> lineJoin { LineJoinType::Miter }; - LayoutProperty<float> lineMiterLimit { 2.0f }; - LayoutProperty<float> lineRoundLimit { 1.0f }; -}; - -class LinePaintProperties { -public: - PaintProperty<float> lineOpacity { 1.0f }; - PaintProperty<Color> lineColor { {{ 0, 0, 0, 1 }} }; - PaintProperty<std::array<float, 2>> lineTranslate { {{ 0, 0 }} }; - PaintProperty<TranslateAnchorType> lineTranslateAnchor { TranslateAnchorType::Map }; - PaintProperty<float> lineWidth { 1 }; - PaintProperty<float> lineGapWidth { 0 }; - PaintProperty<float> lineBlur { 0 }; - PaintProperty<float> lineOffset { 0 }; - PaintProperty<std::vector<float>, CrossFadedFunctionEvaluator> lineDasharray { {} }; - PaintProperty<std::string, CrossFadedFunctionEvaluator> linePattern { "" }; -}; - -class LineLayer : public StyleLayer { -public: - LineLayer() : StyleLayer(Type::Line) {} - std::unique_ptr<StyleLayer> clone() const override; - - void parseLayout(const JSValue&) override; - void parsePaints(const JSValue&) override; - - void cascade(const StyleCascadeParameters&) override; - bool recalculate(const StyleCalculationParameters&) override; - - std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; - - float getQueryRadius() const override; - bool queryIntersectsGeometry( - const GeometryCollection& queryGeometry, - const GeometryCollection& geometry, - const float bearing, - const float pixelsToTileUnits) const override; - - LineLayoutProperties layout; - LinePaintProperties paint; - - float dashLineWidth = 1; -private: - float getLineWidth() const; -}; - -template <> -inline bool StyleLayer::is<LineLayer>() const { - return type == Type::Line; -} - -} // namespace mbgl diff --git a/src/mbgl/layer/line_layer_impl.cpp b/src/mbgl/layer/line_layer_impl.cpp new file mode 100644 index 0000000000..aee1687046 --- /dev/null +++ b/src/mbgl/layer/line_layer_impl.cpp @@ -0,0 +1,114 @@ +#include <mbgl/layer/line_layer_impl.hpp> +#include <mbgl/style/style_bucket_parameters.hpp> +#include <mbgl/renderer/line_bucket.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/util/intersection_tests.hpp> + +namespace mbgl { + +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 StyleCascadeParameters& parameters) { + paint.cascade(parameters); +} + +bool LineLayer::Impl::recalculate(const StyleCalculationParameters& parameters) { + // for scaling dasharrays + StyleCalculationParameters dashArrayParams = parameters; + dashArrayParams.z = std::floor(dashArrayParams.z); + paint.lineWidth.calculate(dashArrayParams); + dashLineWidth = paint.lineWidth; + + bool hasTransitions = paint.recalculate(parameters); + + passes = (paint.lineOpacity > 0 && paint.lineColor.value[3] > 0 && paint.lineWidth > 0) + ? RenderPass::Translucent : RenderPass::None; + + return hasTransitions; +} + +std::unique_ptr<Bucket> LineLayer::Impl::createBucket(StyleBucketParameters& parameters) const { + auto bucket = std::make_unique<LineBucket>(parameters.tileID.overscaleFactor()); + + bucket->layout = layout; + bucket->layout.recalculate(StyleCalculationParameters(parameters.tileID.overscaledZ)); + + auto& name = bucketName(); + parameters.eachFilteredFeature(filter, [&] (const auto& feature, std::size_t index, const std::string& layerName) { + auto geometries = feature.getGeometries(); + bucket->addGeometry(geometries); + parameters.featureIndex.insert(geometries, index, layerName, name); + }); + + return std::move(bucket); +} + +float LineLayer::Impl::getLineWidth() const { + if (paint.lineGapWidth > 0) { + return paint.lineGapWidth + 2 * paint.lineWidth; + } else { + return paint.lineWidth; + } +} + +optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const double offset) { + if (offset == 0) return {}; + + GeometryCollection newRings; + Point<double> zero(0, 0); + for (const auto& ring : rings) { + newRings.emplace_back(); + auto& newRing = newRings.back(); + + for (auto i = ring.begin(); i != ring.end(); i++) { + auto& p = *i; + + Point<double> aToB = i == ring.begin() ? + zero : + util::perp(util::unit(convertPoint<double>(p - *(i - 1)))); + Point<double> bToC = i + 1 == ring.end() ? + zero : + util::perp(util::unit(convertPoint<double>(*(i + 1) - p))); + Point<double> extrude = util::unit(aToB + bToC); + + const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y; + extrude *= (1.0 / cosHalfAngle); + + newRing.push_back(convertPoint<int16_t>(extrude * offset) + p); + } + } + + return newRings; +} + +float LineLayer::Impl::getQueryRadius() const { + const std::array<float, 2>& translate = paint.lineTranslate; + return getLineWidth() / 2.0 + std::abs(paint.lineOffset) + util::length(translate[0], translate[1]); +} + +bool LineLayer::Impl::queryIntersectsGeometry( + const GeometryCollection& queryGeometry, + const GeometryCollection& geometry, + const float bearing, + const float pixelsToTileUnits) const { + + const float halfWidth = getLineWidth() / 2.0 * pixelsToTileUnits; + + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, paint.lineTranslate, paint.lineTranslateAnchor, bearing, pixelsToTileUnits); + auto offsetGeometry = offsetLine(geometry, paint.lineOffset * pixelsToTileUnits); + + return util::multiPolygonIntersectsBufferedMultiLine( + translatedQueryGeometry.value_or(queryGeometry), + offsetGeometry.value_or(geometry), + halfWidth); +} + +} // namespace mbgl diff --git a/src/mbgl/layer/line_layer_impl.hpp b/src/mbgl/layer/line_layer_impl.hpp new file mode 100644 index 0000000000..b602df52fa --- /dev/null +++ b/src/mbgl/layer/line_layer_impl.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/line_layer.hpp> +#include <mbgl/layer/line_layer_properties.hpp> + +namespace mbgl { + +class LineLayer::Impl : public Layer::Impl { +public: + std::unique_ptr<Layer> clone() const override; + + void parseLayout(const JSValue&) override; + void parsePaints(const JSValue&) override; + + void cascade(const StyleCascadeParameters&) override; + bool recalculate(const StyleCalculationParameters&) override; + + std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; + + float getQueryRadius() const override; + bool queryIntersectsGeometry( + const GeometryCollection& queryGeometry, + const GeometryCollection& geometry, + const float bearing, + const float pixelsToTileUnits) const override; + + LineLayoutProperties layout; + LinePaintProperties paint; + + // Special case + float dashLineWidth = 1; + +private: + float getLineWidth() const; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/line_layer_properties.cpp b/src/mbgl/layer/line_layer_properties.cpp new file mode 100644 index 0000000000..4941a1ecd2 --- /dev/null +++ b/src/mbgl/layer/line_layer_properties.cpp @@ -0,0 +1,64 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/layer/line_layer_properties.hpp> + +namespace mbgl { + +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 StyleCalculationParameters& parameters) { + lineCap.calculate(parameters); + lineJoin.calculate(parameters); + lineMiterLimit.calculate(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 StyleCascadeParameters& parameters) { + lineOpacity.cascade(parameters); + lineColor.cascade(parameters); + lineTranslate.cascade(parameters); + lineTranslateAnchor.cascade(parameters); + lineWidth.cascade(parameters); + lineGapWidth.cascade(parameters); + lineOffset.cascade(parameters); + lineBlur.cascade(parameters); + lineDasharray.cascade(parameters); + linePattern.cascade(parameters); +} + +bool LinePaintProperties::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = false; + + hasTransitions |= lineOpacity.calculate(parameters); + hasTransitions |= lineColor.calculate(parameters); + hasTransitions |= lineTranslate.calculate(parameters); + hasTransitions |= lineTranslateAnchor.calculate(parameters); + hasTransitions |= lineWidth.calculate(parameters); + hasTransitions |= lineGapWidth.calculate(parameters); + hasTransitions |= lineOffset.calculate(parameters); + hasTransitions |= lineBlur.calculate(parameters); + hasTransitions |= lineDasharray.calculate(parameters); + hasTransitions |= linePattern.calculate(parameters); + + return hasTransitions; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/line_layer_properties.hpp b/src/mbgl/layer/line_layer_properties.hpp new file mode 100644 index 0000000000..ae87d6da5e --- /dev/null +++ b/src/mbgl/layer/line_layer_properties.hpp @@ -0,0 +1,43 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#pragma once + +#include <mbgl/style/layout_property.hpp> +#include <mbgl/style/paint_property.hpp> +#include <mbgl/util/rapidjson.hpp> + +namespace mbgl { + +class StyleCascadeParameters; +class StyleCalculationParameters; + +class LineLayoutProperties { +public: + void parse(const JSValue&); + void recalculate(const StyleCalculationParameters&); + + LayoutProperty<LineCapType> lineCap { LineCapType::Butt }; + LayoutProperty<LineJoinType> lineJoin { LineJoinType::Miter }; + LayoutProperty<float> lineMiterLimit { 2 }; + LayoutProperty<float> lineRoundLimit { 1.05 }; +}; + +class LinePaintProperties { +public: + void parse(const JSValue&); + void cascade(const StyleCascadeParameters&); + bool recalculate(const StyleCalculationParameters&); + + PaintProperty<float> lineOpacity { 1 }; + PaintProperty<Color> lineColor { {{ 0, 0, 0, 1 }} }; + PaintProperty<std::array<float, 2>> lineTranslate { {{ 0, 0 }} }; + PaintProperty<TranslateAnchorType> lineTranslateAnchor { TranslateAnchorType::Map }; + PaintProperty<float> lineWidth { 1 }; + PaintProperty<float> lineGapWidth { 0 }; + PaintProperty<float> lineOffset { 0 }; + PaintProperty<float> lineBlur { 0 }; + PaintProperty<std::vector<float>, CrossFadedFunctionEvaluator> lineDasharray { { } }; + PaintProperty<std::string, CrossFadedFunctionEvaluator> linePattern { "" }; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/raster_layer.cpp b/src/mbgl/layer/raster_layer.cpp index fa41609039..1ec2e4c0d4 100644 --- a/src/mbgl/layer/raster_layer.cpp +++ b/src/mbgl/layer/raster_layer.cpp @@ -1,50 +1,96 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + #include <mbgl/layer/raster_layer.hpp> -#include <mbgl/renderer/bucket.hpp> +#include <mbgl/layer/raster_layer_impl.hpp> namespace mbgl { -std::unique_ptr<StyleLayer> RasterLayer::clone() const { +RasterLayer::RasterLayer(const std::string& layerID) + : Layer(Type::Raster, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; +} + +RasterLayer::RasterLayer(const Impl& other) + : Layer(Type::Raster, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { +} + +RasterLayer::~RasterLayer() = default; + +std::unique_ptr<Layer> RasterLayer::Impl::clone() const { return std::make_unique<RasterLayer>(*this); } -void RasterLayer::parsePaints(const JSValue& layer) { - paint.rasterOpacity.parse("raster-opacity", layer); - paint.rasterHueRotate.parse("raster-hue-rotate", layer); - paint.rasterBrightnessMin.parse("raster-brightness-min", layer); - paint.rasterBrightnessMax.parse("raster-brightness-max", layer); - paint.rasterSaturation.parse("raster-saturation", layer); - paint.rasterContrast.parse("raster-contrast", layer); - paint.rasterFadeDuration.parse("raster-fade-duration", layer); +// Source + +void RasterLayer::setSource(const std::string& sourceID) { + impl->source = sourceID; +} + +const std::string& RasterLayer::getSourceID() const { + return impl->source; +} + +// Layout properties + + +// Paint properties + +Function<float> RasterLayer::getRasterOpacity() const { + return impl->paint.rasterOpacity.values.at(ClassID::Default); } -void RasterLayer::cascade(const StyleCascadeParameters& parameters) { - paint.rasterOpacity.cascade(parameters); - paint.rasterHueRotate.cascade(parameters); - paint.rasterBrightnessMin.cascade(parameters); - paint.rasterBrightnessMax.cascade(parameters); - paint.rasterSaturation.cascade(parameters); - paint.rasterContrast.cascade(parameters); - paint.rasterFadeDuration.cascade(parameters); +void RasterLayer::setRasterOpacity(Function<float> value) { + impl->paint.rasterOpacity.values.emplace(ClassID::Default, value); } -bool RasterLayer::recalculate(const StyleCalculationParameters& parameters) { - bool hasTransitions = false; +Function<float> RasterLayer::getRasterHueRotate() const { + return impl->paint.rasterHueRotate.values.at(ClassID::Default); +} - hasTransitions |= paint.rasterOpacity.calculate(parameters); - hasTransitions |= paint.rasterHueRotate.calculate(parameters); - hasTransitions |= paint.rasterBrightnessMin.calculate(parameters); - hasTransitions |= paint.rasterBrightnessMax.calculate(parameters); - hasTransitions |= paint.rasterSaturation.calculate(parameters); - hasTransitions |= paint.rasterContrast.calculate(parameters); - hasTransitions |= paint.rasterFadeDuration.calculate(parameters); +void RasterLayer::setRasterHueRotate(Function<float> value) { + impl->paint.rasterHueRotate.values.emplace(ClassID::Default, value); +} - passes = paint.rasterOpacity > 0 ? RenderPass::Translucent : RenderPass::None; +Function<float> RasterLayer::getRasterBrightnessMin() const { + return impl->paint.rasterBrightnessMin.values.at(ClassID::Default); +} + +void RasterLayer::setRasterBrightnessMin(Function<float> value) { + impl->paint.rasterBrightnessMin.values.emplace(ClassID::Default, value); +} + +Function<float> RasterLayer::getRasterBrightnessMax() const { + return impl->paint.rasterBrightnessMax.values.at(ClassID::Default); +} + +void RasterLayer::setRasterBrightnessMax(Function<float> value) { + impl->paint.rasterBrightnessMax.values.emplace(ClassID::Default, value); +} + +Function<float> RasterLayer::getRasterSaturation() const { + return impl->paint.rasterSaturation.values.at(ClassID::Default); +} + +void RasterLayer::setRasterSaturation(Function<float> value) { + impl->paint.rasterSaturation.values.emplace(ClassID::Default, value); +} + +Function<float> RasterLayer::getRasterContrast() const { + return impl->paint.rasterContrast.values.at(ClassID::Default); +} + +void RasterLayer::setRasterContrast(Function<float> value) { + impl->paint.rasterContrast.values.emplace(ClassID::Default, value); +} - return hasTransitions; +Function<float> RasterLayer::getRasterFadeDuration() const { + return impl->paint.rasterFadeDuration.values.at(ClassID::Default); } -std::unique_ptr<Bucket> RasterLayer::createBucket(StyleBucketParameters&) const { - return nullptr; +void RasterLayer::setRasterFadeDuration(Function<float> value) { + impl->paint.rasterFadeDuration.values.emplace(ClassID::Default, value); } } // namespace mbgl diff --git a/src/mbgl/layer/raster_layer.hpp b/src/mbgl/layer/raster_layer.hpp deleted file mode 100644 index d473505d56..0000000000 --- a/src/mbgl/layer/raster_layer.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include <mbgl/style/style_layer.hpp> -#include <mbgl/style/paint_property.hpp> - -namespace mbgl { - -class RasterPaintProperties { -public: - PaintProperty<float> rasterOpacity { 1.0f }; - PaintProperty<float> rasterHueRotate { 0.0f }; - PaintProperty<float> rasterBrightnessMin { 0.0f }; - PaintProperty<float> rasterBrightnessMax { 1.0f }; - PaintProperty<float> rasterSaturation { 0.0f }; - PaintProperty<float> rasterContrast { 0.0f }; - PaintProperty<float> rasterFadeDuration { 0.0f }; -}; - -class RasterLayer : public StyleLayer { -public: - RasterLayer() : StyleLayer(Type::Raster) {} - std::unique_ptr<StyleLayer> clone() const override; - - void parseLayout(const JSValue&) override {}; - void parsePaints(const JSValue&) override; - - void cascade(const StyleCascadeParameters&) override; - bool recalculate(const StyleCalculationParameters&) override; - - std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; - - RasterPaintProperties paint; -}; - -template <> -inline bool StyleLayer::is<RasterLayer>() const { - return type == Type::Raster; -} - -} // namespace mbgl diff --git a/src/mbgl/layer/raster_layer_impl.cpp b/src/mbgl/layer/raster_layer_impl.cpp new file mode 100644 index 0000000000..f44a424f99 --- /dev/null +++ b/src/mbgl/layer/raster_layer_impl.cpp @@ -0,0 +1,26 @@ +#include <mbgl/layer/raster_layer_impl.hpp> +#include <mbgl/renderer/bucket.hpp> + +namespace mbgl { + +void RasterLayer::Impl::parsePaints(const JSValue& layer) { + paint.parse(layer); +} + +void RasterLayer::Impl::cascade(const StyleCascadeParameters& parameters) { + paint.cascade(parameters); +} + +bool RasterLayer::Impl::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = paint.recalculate(parameters); + + passes = paint.rasterOpacity > 0 ? RenderPass::Translucent : RenderPass::None; + + return hasTransitions; +} + +std::unique_ptr<Bucket> RasterLayer::Impl::createBucket(StyleBucketParameters&) const { + return nullptr; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/raster_layer_impl.hpp b/src/mbgl/layer/raster_layer_impl.hpp new file mode 100644 index 0000000000..a83c7f259e --- /dev/null +++ b/src/mbgl/layer/raster_layer_impl.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/raster_layer.hpp> +#include <mbgl/layer/raster_layer_properties.hpp> + +namespace mbgl { + +class RasterLayer::Impl : public Layer::Impl { +public: + std::unique_ptr<Layer> clone() const override; + + void parseLayout(const JSValue&) override {}; + void parsePaints(const JSValue&) override; + + void cascade(const StyleCascadeParameters&) override; + bool recalculate(const StyleCalculationParameters&) override; + + std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; + + RasterPaintProperties paint; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/raster_layer_properties.cpp b/src/mbgl/layer/raster_layer_properties.cpp new file mode 100644 index 0000000000..898188bc83 --- /dev/null +++ b/src/mbgl/layer/raster_layer_properties.cpp @@ -0,0 +1,41 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/layer/raster_layer_properties.hpp> + +namespace mbgl { + +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 StyleCascadeParameters& parameters) { + rasterOpacity.cascade(parameters); + rasterHueRotate.cascade(parameters); + rasterBrightnessMin.cascade(parameters); + rasterBrightnessMax.cascade(parameters); + rasterSaturation.cascade(parameters); + rasterContrast.cascade(parameters); + rasterFadeDuration.cascade(parameters); +} + +bool RasterPaintProperties::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = false; + + hasTransitions |= rasterOpacity.calculate(parameters); + hasTransitions |= rasterHueRotate.calculate(parameters); + hasTransitions |= rasterBrightnessMin.calculate(parameters); + hasTransitions |= rasterBrightnessMax.calculate(parameters); + hasTransitions |= rasterSaturation.calculate(parameters); + hasTransitions |= rasterContrast.calculate(parameters); + hasTransitions |= rasterFadeDuration.calculate(parameters); + + return hasTransitions; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/raster_layer_properties.hpp b/src/mbgl/layer/raster_layer_properties.hpp new file mode 100644 index 0000000000..46bd00ff2e --- /dev/null +++ b/src/mbgl/layer/raster_layer_properties.hpp @@ -0,0 +1,29 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#pragma once + +#include <mbgl/style/layout_property.hpp> +#include <mbgl/style/paint_property.hpp> +#include <mbgl/util/rapidjson.hpp> + +namespace mbgl { + +class StyleCascadeParameters; +class StyleCalculationParameters; + +class RasterPaintProperties { +public: + void parse(const JSValue&); + void cascade(const StyleCascadeParameters&); + bool recalculate(const StyleCalculationParameters&); + + PaintProperty<float> rasterOpacity { 1 }; + PaintProperty<float> rasterHueRotate { 0 }; + PaintProperty<float> rasterBrightnessMin { 0 }; + PaintProperty<float> rasterBrightnessMax { 1 }; + PaintProperty<float> rasterSaturation { 0 }; + PaintProperty<float> rasterContrast { 0 }; + PaintProperty<float> rasterFadeDuration { 300 }; +}; + +} // namespace mbgl diff --git a/src/mbgl/layer/symbol_layer.cpp b/src/mbgl/layer/symbol_layer.cpp index b3222f9368..de2428fd25 100644 --- a/src/mbgl/layer/symbol_layer.cpp +++ b/src/mbgl/layer/symbol_layer.cpp @@ -1,188 +1,374 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + #include <mbgl/layer/symbol_layer.hpp> -#include <mbgl/renderer/symbol_bucket.hpp> -#include <mbgl/style/style_bucket_parameters.hpp> +#include <mbgl/layer/symbol_layer_impl.hpp> namespace mbgl { -std::unique_ptr<StyleLayer> SymbolLayer::clone() const { +SymbolLayer::SymbolLayer(const std::string& layerID) + : Layer(Type::Symbol, std::make_unique<Impl>()) + , impl(static_cast<Impl*>(baseImpl.get())) { + impl->id = layerID; +} + +SymbolLayer::SymbolLayer(const Impl& other) + : Layer(Type::Symbol, std::make_unique<Impl>(other)) + , impl(static_cast<Impl*>(baseImpl.get())) { +} + +SymbolLayer::~SymbolLayer() = default; + +std::unique_ptr<Layer> SymbolLayer::Impl::clone() const { return std::make_unique<SymbolLayer>(*this); } -void SymbolLayer::parseLayout(const JSValue& value) { - layout.symbolPlacement.parse("symbol-placement", value); - layout.symbolSpacing.parse("symbol-spacing", value); - layout.symbolAvoidEdges.parse("symbol-avoid-edges", value); - - layout.iconAllowOverlap.parse("icon-allow-overlap", value); - layout.iconIgnorePlacement.parse("icon-ignore-placement", value); - layout.iconOptional.parse("icon-optional", value); - layout.iconRotationAlignment.parse("icon-rotation-alignment", value); - layout.iconSize.parse("icon-size", value); - layout.iconImage.parse("icon-image", value); - layout.iconRotate.parse("icon-rotate", value); - layout.iconPadding.parse("icon-padding", value); - layout.iconKeepUpright.parse("icon-keep-upright", value); - layout.iconOffset.parse("icon-offset", value); - - layout.textRotationAlignment.parse("text-rotation-alignment", value); - layout.textField.parse("text-field", value); - layout.textFont.parse("text-font", value); - layout.textSize.parse("text-size", value); - layout.textMaxWidth.parse("text-max-width", value); - layout.textLineHeight.parse("text-line-height", value); - layout.textLetterSpacing.parse("text-letter-spacing", value); - layout.textJustify.parse("text-justify", value); - layout.textAnchor.parse("text-anchor", value); - layout.textMaxAngle.parse("text-max-angle", value); - layout.textRotate.parse("text-rotate", value); - layout.textPadding.parse("text-padding", value); - layout.textKeepUpright.parse("text-keep-upright", value); - layout.textTransform.parse("text-transform", value); - layout.textOffset.parse("text-offset", value); - layout.textAllowOverlap.parse("text-allow-overlap", value); - layout.textIgnorePlacement.parse("text-ignore-placement", value); - layout.textOptional.parse("text-optional", value); -} - -void SymbolLayer::parsePaints(const JSValue& layer) { - paint.iconOpacity.parse("icon-opacity", layer); - paint.iconColor.parse("icon-color", layer); - paint.iconHaloColor.parse("icon-halo-color", layer); - paint.iconHaloWidth.parse("icon-halo-width", layer); - paint.iconHaloBlur.parse("icon-halo-blur", layer); - paint.iconTranslate.parse("icon-translate", layer); - paint.iconTranslateAnchor.parse("icon-translate-anchor", layer); - - paint.textOpacity.parse("text-opacity", layer); - paint.textColor.parse("text-color", layer); - paint.textHaloColor.parse("text-halo-color", layer); - paint.textHaloWidth.parse("text-halo-width", layer); - paint.textHaloBlur.parse("text-halo-blur", layer); - paint.textTranslate.parse("text-translate", layer); - paint.textTranslateAnchor.parse("text-translate-anchor", layer); -} - -void SymbolLayer::cascade(const StyleCascadeParameters& parameters) { - paint.iconOpacity.cascade(parameters); - paint.iconColor.cascade(parameters); - paint.iconHaloColor.cascade(parameters); - paint.iconHaloWidth.cascade(parameters); - paint.iconHaloBlur.cascade(parameters); - paint.iconTranslate.cascade(parameters); - paint.iconTranslateAnchor.cascade(parameters); - - paint.textOpacity.cascade(parameters); - paint.textColor.cascade(parameters); - paint.textHaloColor.cascade(parameters); - paint.textHaloWidth.cascade(parameters); - paint.textHaloBlur.cascade(parameters); - paint.textTranslate.cascade(parameters); - paint.textTranslateAnchor.cascade(parameters); -} - -bool SymbolLayer::recalculate(const StyleCalculationParameters& parameters) { - bool hasTransitions = false; - - hasTransitions |= paint.iconOpacity.calculate(parameters); - hasTransitions |= paint.iconColor.calculate(parameters); - hasTransitions |= paint.iconHaloColor.calculate(parameters); - hasTransitions |= paint.iconHaloWidth.calculate(parameters); - hasTransitions |= paint.iconHaloBlur.calculate(parameters); - hasTransitions |= paint.iconTranslate.calculate(parameters); - hasTransitions |= paint.iconTranslateAnchor.calculate(parameters); - - hasTransitions |= paint.textOpacity.calculate(parameters); - hasTransitions |= paint.textColor.calculate(parameters); - hasTransitions |= paint.textHaloColor.calculate(parameters); - hasTransitions |= paint.textHaloWidth.calculate(parameters); - hasTransitions |= paint.textHaloBlur.calculate(parameters); - hasTransitions |= paint.textTranslate.calculate(parameters); - hasTransitions |= paint.textTranslateAnchor.calculate(parameters); - - // text-size and icon-size are layout properties but they also need to be evaluated as paint properties: - layout.iconSize.calculate(parameters); - layout.textSize.calculate(parameters); - iconSize = layout.iconSize; - textSize = layout.textSize; - - passes = ((paint.iconOpacity > 0 && (paint.iconColor.value[3] > 0 || paint.iconHaloColor.value[3] > 0) && iconSize > 0) - || (paint.textOpacity > 0 && (paint.textColor.value[3] > 0 || paint.textHaloColor.value[3] > 0) && textSize > 0)) - ? RenderPass::Translucent : RenderPass::None; - - return hasTransitions; -} - -std::unique_ptr<Bucket> SymbolLayer::createBucket(StyleBucketParameters& parameters) const { - auto bucket = std::make_unique<SymbolBucket>(parameters.tileID.overscaleFactor(), - parameters.tileID.overscaledZ, - parameters.mode, - id, - parameters.layer.getName()); - - bucket->layout = layout; - - StyleCalculationParameters p(parameters.tileID.overscaledZ); - bucket->layout.symbolPlacement.calculate(p); - if (bucket->layout.symbolPlacement.value == SymbolPlacementType::Line) { - bucket->layout.iconRotationAlignment.value = RotationAlignmentType::Map; - bucket->layout.textRotationAlignment.value = RotationAlignmentType::Map; - }; - bucket->layout.symbolSpacing.calculate(p); - bucket->layout.symbolAvoidEdges.calculate(p); - - bucket->layout.iconAllowOverlap.calculate(p); - bucket->layout.iconIgnorePlacement.calculate(p); - bucket->layout.iconOptional.calculate(p); - bucket->layout.iconRotationAlignment.calculate(p); - bucket->layout.iconImage.calculate(p); - bucket->layout.iconPadding.calculate(p); - bucket->layout.iconRotate.calculate(p); - bucket->layout.iconKeepUpright.calculate(p); - bucket->layout.iconOffset.calculate(p); - - bucket->layout.textRotationAlignment.calculate(p); - bucket->layout.textField.calculate(p); - bucket->layout.textFont.calculate(p); - bucket->layout.textMaxWidth.calculate(p); - bucket->layout.textLineHeight.calculate(p); - bucket->layout.textLetterSpacing.calculate(p); - bucket->layout.textMaxAngle.calculate(p); - bucket->layout.textRotate.calculate(p); - bucket->layout.textPadding.calculate(p); - bucket->layout.textIgnorePlacement.calculate(p); - bucket->layout.textOptional.calculate(p); - bucket->layout.textJustify.calculate(p); - bucket->layout.textAnchor.calculate(p); - bucket->layout.textKeepUpright.calculate(p); - bucket->layout.textTransform.calculate(p); - bucket->layout.textOffset.calculate(p); - bucket->layout.textAllowOverlap.calculate(p); - - bucket->layout.iconSize.calculate(StyleCalculationParameters(18)); - bucket->layout.textSize.calculate(StyleCalculationParameters(18)); - bucket->iconMaxSize = bucket->layout.iconSize; - bucket->textMaxSize = bucket->layout.textSize; - bucket->layout.iconSize.calculate(StyleCalculationParameters(p.z + 1)); - bucket->layout.textSize.calculate(StyleCalculationParameters(p.z + 1)); - - bucket->parseFeatures(parameters.layer, filter); - - if (bucket->needsDependencies(parameters.glyphStore, parameters.spriteStore)) { - parameters.partialParse = true; - } - - // We do not add features if the parser is in a "partial" state because - // the layer ordering needs to be respected when calculating text - // collisions. Although, at this point, we requested all the resources - // needed by this tile. - if (!parameters.partialParse) { - bucket->addFeatures(parameters.tileUID, - *spriteAtlas, - parameters.glyphAtlas, - parameters.glyphStore); - } - - return std::move(bucket); +// Source + +void SymbolLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) { + impl->source = sourceID; + impl->sourceLayer = sourceLayer; +} + +const std::string& SymbolLayer::getSourceID() const { + return impl->source; +} + +const std::string& SymbolLayer::getSourceLayer() const { + return impl->sourceLayer; +} + +// Layout properties + +Function<SymbolPlacementType> SymbolLayer::getSymbolPlacement() const { + return *impl->layout.symbolPlacement.parsedValue; +} + +void SymbolLayer::setSymbolPlacement(Function<SymbolPlacementType> value) { + impl->layout.symbolPlacement.parsedValue = value; +} +Function<float> SymbolLayer::getSymbolSpacing() const { + return *impl->layout.symbolSpacing.parsedValue; +} + +void SymbolLayer::setSymbolSpacing(Function<float> value) { + impl->layout.symbolSpacing.parsedValue = value; +} +Function<bool> SymbolLayer::getSymbolAvoidEdges() const { + return *impl->layout.symbolAvoidEdges.parsedValue; +} + +void SymbolLayer::setSymbolAvoidEdges(Function<bool> value) { + impl->layout.symbolAvoidEdges.parsedValue = value; +} +Function<bool> SymbolLayer::getIconAllowOverlap() const { + return *impl->layout.iconAllowOverlap.parsedValue; +} + +void SymbolLayer::setIconAllowOverlap(Function<bool> value) { + impl->layout.iconAllowOverlap.parsedValue = value; +} +Function<bool> SymbolLayer::getIconIgnorePlacement() const { + return *impl->layout.iconIgnorePlacement.parsedValue; +} + +void SymbolLayer::setIconIgnorePlacement(Function<bool> value) { + impl->layout.iconIgnorePlacement.parsedValue = value; +} +Function<bool> SymbolLayer::getIconOptional() const { + return *impl->layout.iconOptional.parsedValue; +} + +void SymbolLayer::setIconOptional(Function<bool> value) { + impl->layout.iconOptional.parsedValue = value; +} +Function<RotationAlignmentType> SymbolLayer::getIconRotationAlignment() const { + return *impl->layout.iconRotationAlignment.parsedValue; +} + +void SymbolLayer::setIconRotationAlignment(Function<RotationAlignmentType> value) { + impl->layout.iconRotationAlignment.parsedValue = value; +} +Function<float> SymbolLayer::getIconSize() const { + return *impl->layout.iconSize.parsedValue; +} + +void SymbolLayer::setIconSize(Function<float> value) { + impl->layout.iconSize.parsedValue = value; +} +Function<std::string> SymbolLayer::getIconImage() const { + return *impl->layout.iconImage.parsedValue; +} + +void SymbolLayer::setIconImage(Function<std::string> value) { + impl->layout.iconImage.parsedValue = value; +} +Function<float> SymbolLayer::getIconRotate() const { + return *impl->layout.iconRotate.parsedValue; +} + +void SymbolLayer::setIconRotate(Function<float> value) { + impl->layout.iconRotate.parsedValue = value; +} +Function<float> SymbolLayer::getIconPadding() const { + return *impl->layout.iconPadding.parsedValue; +} + +void SymbolLayer::setIconPadding(Function<float> value) { + impl->layout.iconPadding.parsedValue = value; +} +Function<bool> SymbolLayer::getIconKeepUpright() const { + return *impl->layout.iconKeepUpright.parsedValue; +} + +void SymbolLayer::setIconKeepUpright(Function<bool> value) { + impl->layout.iconKeepUpright.parsedValue = value; +} +Function<std::array<float, 2>> SymbolLayer::getIconOffset() const { + return *impl->layout.iconOffset.parsedValue; +} + +void SymbolLayer::setIconOffset(Function<std::array<float, 2>> value) { + impl->layout.iconOffset.parsedValue = value; +} +Function<RotationAlignmentType> SymbolLayer::getTextRotationAlignment() const { + return *impl->layout.textRotationAlignment.parsedValue; +} + +void SymbolLayer::setTextRotationAlignment(Function<RotationAlignmentType> value) { + impl->layout.textRotationAlignment.parsedValue = value; +} +Function<std::string> SymbolLayer::getTextField() const { + return *impl->layout.textField.parsedValue; +} + +void SymbolLayer::setTextField(Function<std::string> value) { + impl->layout.textField.parsedValue = value; +} +Function<std::vector<std::string>> SymbolLayer::getTextFont() const { + return *impl->layout.textFont.parsedValue; +} + +void SymbolLayer::setTextFont(Function<std::vector<std::string>> value) { + impl->layout.textFont.parsedValue = value; +} +Function<float> SymbolLayer::getTextSize() const { + return *impl->layout.textSize.parsedValue; +} + +void SymbolLayer::setTextSize(Function<float> value) { + impl->layout.textSize.parsedValue = value; +} +Function<float> SymbolLayer::getTextMaxWidth() const { + return *impl->layout.textMaxWidth.parsedValue; +} + +void SymbolLayer::setTextMaxWidth(Function<float> value) { + impl->layout.textMaxWidth.parsedValue = value; +} +Function<float> SymbolLayer::getTextLineHeight() const { + return *impl->layout.textLineHeight.parsedValue; +} + +void SymbolLayer::setTextLineHeight(Function<float> value) { + impl->layout.textLineHeight.parsedValue = value; +} +Function<float> SymbolLayer::getTextLetterSpacing() const { + return *impl->layout.textLetterSpacing.parsedValue; +} + +void SymbolLayer::setTextLetterSpacing(Function<float> value) { + impl->layout.textLetterSpacing.parsedValue = value; +} +Function<TextJustifyType> SymbolLayer::getTextJustify() const { + return *impl->layout.textJustify.parsedValue; +} + +void SymbolLayer::setTextJustify(Function<TextJustifyType> value) { + impl->layout.textJustify.parsedValue = value; +} +Function<TextAnchorType> SymbolLayer::getTextAnchor() const { + return *impl->layout.textAnchor.parsedValue; +} + +void SymbolLayer::setTextAnchor(Function<TextAnchorType> value) { + impl->layout.textAnchor.parsedValue = value; +} +Function<float> SymbolLayer::getTextMaxAngle() const { + return *impl->layout.textMaxAngle.parsedValue; +} + +void SymbolLayer::setTextMaxAngle(Function<float> value) { + impl->layout.textMaxAngle.parsedValue = value; +} +Function<float> SymbolLayer::getTextRotate() const { + return *impl->layout.textRotate.parsedValue; +} + +void SymbolLayer::setTextRotate(Function<float> value) { + impl->layout.textRotate.parsedValue = value; +} +Function<float> SymbolLayer::getTextPadding() const { + return *impl->layout.textPadding.parsedValue; +} + +void SymbolLayer::setTextPadding(Function<float> value) { + impl->layout.textPadding.parsedValue = value; +} +Function<bool> SymbolLayer::getTextKeepUpright() const { + return *impl->layout.textKeepUpright.parsedValue; +} + +void SymbolLayer::setTextKeepUpright(Function<bool> value) { + impl->layout.textKeepUpright.parsedValue = value; +} +Function<TextTransformType> SymbolLayer::getTextTransform() const { + return *impl->layout.textTransform.parsedValue; +} + +void SymbolLayer::setTextTransform(Function<TextTransformType> value) { + impl->layout.textTransform.parsedValue = value; +} +Function<std::array<float, 2>> SymbolLayer::getTextOffset() const { + return *impl->layout.textOffset.parsedValue; +} + +void SymbolLayer::setTextOffset(Function<std::array<float, 2>> value) { + impl->layout.textOffset.parsedValue = value; +} +Function<bool> SymbolLayer::getTextAllowOverlap() const { + return *impl->layout.textAllowOverlap.parsedValue; +} + +void SymbolLayer::setTextAllowOverlap(Function<bool> value) { + impl->layout.textAllowOverlap.parsedValue = value; +} +Function<bool> SymbolLayer::getTextIgnorePlacement() const { + return *impl->layout.textIgnorePlacement.parsedValue; +} + +void SymbolLayer::setTextIgnorePlacement(Function<bool> value) { + impl->layout.textIgnorePlacement.parsedValue = value; +} +Function<bool> SymbolLayer::getTextOptional() const { + return *impl->layout.textOptional.parsedValue; +} + +void SymbolLayer::setTextOptional(Function<bool> value) { + impl->layout.textOptional.parsedValue = value; +} + +// Paint properties + +Function<float> SymbolLayer::getIconOpacity() const { + return impl->paint.iconOpacity.values.at(ClassID::Default); +} + +void SymbolLayer::setIconOpacity(Function<float> value) { + impl->paint.iconOpacity.values.emplace(ClassID::Default, value); +} + +Function<Color> SymbolLayer::getIconColor() const { + return impl->paint.iconColor.values.at(ClassID::Default); +} + +void SymbolLayer::setIconColor(Function<Color> value) { + impl->paint.iconColor.values.emplace(ClassID::Default, value); +} + +Function<Color> SymbolLayer::getIconHaloColor() const { + return impl->paint.iconHaloColor.values.at(ClassID::Default); +} + +void SymbolLayer::setIconHaloColor(Function<Color> value) { + impl->paint.iconHaloColor.values.emplace(ClassID::Default, value); +} + +Function<float> SymbolLayer::getIconHaloWidth() const { + return impl->paint.iconHaloWidth.values.at(ClassID::Default); +} + +void SymbolLayer::setIconHaloWidth(Function<float> value) { + impl->paint.iconHaloWidth.values.emplace(ClassID::Default, value); +} + +Function<float> SymbolLayer::getIconHaloBlur() const { + return impl->paint.iconHaloBlur.values.at(ClassID::Default); +} + +void SymbolLayer::setIconHaloBlur(Function<float> value) { + impl->paint.iconHaloBlur.values.emplace(ClassID::Default, value); +} + +Function<std::array<float, 2>> SymbolLayer::getIconTranslate() const { + return impl->paint.iconTranslate.values.at(ClassID::Default); +} + +void SymbolLayer::setIconTranslate(Function<std::array<float, 2>> value) { + impl->paint.iconTranslate.values.emplace(ClassID::Default, value); +} + +Function<TranslateAnchorType> SymbolLayer::getIconTranslateAnchor() const { + return impl->paint.iconTranslateAnchor.values.at(ClassID::Default); +} + +void SymbolLayer::setIconTranslateAnchor(Function<TranslateAnchorType> value) { + impl->paint.iconTranslateAnchor.values.emplace(ClassID::Default, value); +} + +Function<float> SymbolLayer::getTextOpacity() const { + return impl->paint.textOpacity.values.at(ClassID::Default); +} + +void SymbolLayer::setTextOpacity(Function<float> value) { + impl->paint.textOpacity.values.emplace(ClassID::Default, value); +} + +Function<Color> SymbolLayer::getTextColor() const { + return impl->paint.textColor.values.at(ClassID::Default); +} + +void SymbolLayer::setTextColor(Function<Color> value) { + impl->paint.textColor.values.emplace(ClassID::Default, value); +} + +Function<Color> SymbolLayer::getTextHaloColor() const { + return impl->paint.textHaloColor.values.at(ClassID::Default); +} + +void SymbolLayer::setTextHaloColor(Function<Color> value) { + impl->paint.textHaloColor.values.emplace(ClassID::Default, value); +} + +Function<float> SymbolLayer::getTextHaloWidth() const { + return impl->paint.textHaloWidth.values.at(ClassID::Default); +} + +void SymbolLayer::setTextHaloWidth(Function<float> value) { + impl->paint.textHaloWidth.values.emplace(ClassID::Default, value); +} + +Function<float> SymbolLayer::getTextHaloBlur() const { + return impl->paint.textHaloBlur.values.at(ClassID::Default); +} + +void SymbolLayer::setTextHaloBlur(Function<float> value) { + impl->paint.textHaloBlur.values.emplace(ClassID::Default, value); +} + +Function<std::array<float, 2>> SymbolLayer::getTextTranslate() const { + return impl->paint.textTranslate.values.at(ClassID::Default); +} + +void SymbolLayer::setTextTranslate(Function<std::array<float, 2>> value) { + impl->paint.textTranslate.values.emplace(ClassID::Default, value); +} + +Function<TranslateAnchorType> SymbolLayer::getTextTranslateAnchor() const { + return impl->paint.textTranslateAnchor.values.at(ClassID::Default); +} + +void SymbolLayer::setTextTranslateAnchor(Function<TranslateAnchorType> value) { + impl->paint.textTranslateAnchor.values.emplace(ClassID::Default, value); } } // namespace mbgl diff --git a/src/mbgl/layer/symbol_layer_impl.cpp b/src/mbgl/layer/symbol_layer_impl.cpp new file mode 100644 index 0000000000..3a0e0dceca --- /dev/null +++ b/src/mbgl/layer/symbol_layer_impl.cpp @@ -0,0 +1,80 @@ +#include <mbgl/layer/symbol_layer_impl.hpp> +#include <mbgl/renderer/symbol_bucket.hpp> +#include <mbgl/style/style_bucket_parameters.hpp> + +namespace mbgl { + +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 StyleCascadeParameters& parameters) { + paint.cascade(parameters); +} + +bool SymbolLayer::Impl::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = paint.recalculate(parameters); + + // text-size and icon-size are layout properties but they also need to be evaluated as paint properties: + layout.iconSize.calculate(parameters); + layout.textSize.calculate(parameters); + iconSize = layout.iconSize; + textSize = layout.textSize; + + passes = ((paint.iconOpacity > 0 && (paint.iconColor.value[3] > 0 || paint.iconHaloColor.value[3] > 0) && iconSize > 0) + || (paint.textOpacity > 0 && (paint.textColor.value[3] > 0 || paint.textHaloColor.value[3] > 0) && textSize > 0)) + ? RenderPass::Translucent : RenderPass::None; + + return hasTransitions; +} + +std::unique_ptr<Bucket> SymbolLayer::Impl::createBucket(StyleBucketParameters& parameters) const { + auto bucket = std::make_unique<SymbolBucket>(parameters.tileID.overscaleFactor(), + parameters.tileID.overscaledZ, + parameters.mode, + id, + parameters.layer.getName()); + + bucket->layout = layout; + + StyleCalculationParameters p(parameters.tileID.overscaledZ); + bucket->layout.symbolPlacement.calculate(p); + if (bucket->layout.symbolPlacement.value == SymbolPlacementType::Line) { + bucket->layout.iconRotationAlignment.value = RotationAlignmentType::Map; + bucket->layout.textRotationAlignment.value = RotationAlignmentType::Map; + }; + + bucket->layout.recalculate(p); + + bucket->layout.iconSize.calculate(StyleCalculationParameters(18)); + bucket->layout.textSize.calculate(StyleCalculationParameters(18)); + bucket->iconMaxSize = bucket->layout.iconSize; + bucket->textMaxSize = bucket->layout.textSize; + bucket->layout.iconSize.calculate(StyleCalculationParameters(p.z + 1)); + bucket->layout.textSize.calculate(StyleCalculationParameters(p.z + 1)); + + bucket->parseFeatures(parameters.layer, filter); + + if (bucket->needsDependencies(parameters.glyphStore, parameters.spriteStore)) { + parameters.partialParse = true; + } + + // We do not add features if the parser is in a "partial" state because + // the layer ordering needs to be respected when calculating text + // collisions. Although, at this point, we requested all the resources + // needed by this tile. + if (!parameters.partialParse) { + bucket->addFeatures(parameters.tileUID, + *spriteAtlas, + parameters.glyphAtlas, + parameters.glyphStore); + } + + return std::move(bucket); +} + +} // namespace mbgl diff --git a/src/mbgl/layer/symbol_layer_impl.hpp b/src/mbgl/layer/symbol_layer_impl.hpp new file mode 100644 index 0000000000..46503ab916 --- /dev/null +++ b/src/mbgl/layer/symbol_layer_impl.hpp @@ -0,0 +1,35 @@ +#ifndef MBGL_SYMBOL_LAYER +#define MBGL_SYMBOL_LAYER + +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/symbol_layer.hpp> +#include <mbgl/layer/symbol_layer_properties.hpp> + +namespace mbgl { + +class SpriteAtlas; + +class SymbolLayer::Impl : public Layer::Impl { +public: + std::unique_ptr<Layer> clone() const override; + + void parseLayout(const JSValue&) override; + void parsePaints(const JSValue&) override; + + void cascade(const StyleCascadeParameters&) override; + bool recalculate(const StyleCalculationParameters&) override; + + std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; + + SymbolLayoutProperties layout; + SymbolPaintProperties paint; + + float iconSize = 1.0f; + float textSize = 16.0f; + + SpriteAtlas* spriteAtlas = nullptr; +}; + +} // namespace mbgl + +#endif diff --git a/src/mbgl/layer/symbol_layer_properties.cpp b/src/mbgl/layer/symbol_layer_properties.cpp new file mode 100644 index 0000000000..4b9e9a5fb6 --- /dev/null +++ b/src/mbgl/layer/symbol_layer_properties.cpp @@ -0,0 +1,130 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + +#include <mbgl/layer/symbol_layer_properties.hpp> + +namespace mbgl { + +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); + 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); + 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 StyleCalculationParameters& parameters) { + symbolPlacement.calculate(parameters); + symbolSpacing.calculate(parameters); + symbolAvoidEdges.calculate(parameters); + iconAllowOverlap.calculate(parameters); + iconIgnorePlacement.calculate(parameters); + iconOptional.calculate(parameters); + iconRotationAlignment.calculate(parameters); + iconSize.calculate(parameters); + iconImage.calculate(parameters); + iconRotate.calculate(parameters); + iconPadding.calculate(parameters); + iconKeepUpright.calculate(parameters); + iconOffset.calculate(parameters); + textRotationAlignment.calculate(parameters); + textField.calculate(parameters); + textFont.calculate(parameters); + textSize.calculate(parameters); + textMaxWidth.calculate(parameters); + textLineHeight.calculate(parameters); + textLetterSpacing.calculate(parameters); + textJustify.calculate(parameters); + textAnchor.calculate(parameters); + textMaxAngle.calculate(parameters); + textRotate.calculate(parameters); + textPadding.calculate(parameters); + textKeepUpright.calculate(parameters); + textTransform.calculate(parameters); + textOffset.calculate(parameters); + textAllowOverlap.calculate(parameters); + textIgnorePlacement.calculate(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 StyleCascadeParameters& parameters) { + iconOpacity.cascade(parameters); + iconColor.cascade(parameters); + iconHaloColor.cascade(parameters); + iconHaloWidth.cascade(parameters); + iconHaloBlur.cascade(parameters); + iconTranslate.cascade(parameters); + iconTranslateAnchor.cascade(parameters); + textOpacity.cascade(parameters); + textColor.cascade(parameters); + textHaloColor.cascade(parameters); + textHaloWidth.cascade(parameters); + textHaloBlur.cascade(parameters); + textTranslate.cascade(parameters); + textTranslateAnchor.cascade(parameters); +} + +bool SymbolPaintProperties::recalculate(const StyleCalculationParameters& parameters) { + bool hasTransitions = false; + + hasTransitions |= iconOpacity.calculate(parameters); + hasTransitions |= iconColor.calculate(parameters); + hasTransitions |= iconHaloColor.calculate(parameters); + hasTransitions |= iconHaloWidth.calculate(parameters); + hasTransitions |= iconHaloBlur.calculate(parameters); + hasTransitions |= iconTranslate.calculate(parameters); + hasTransitions |= iconTranslateAnchor.calculate(parameters); + hasTransitions |= textOpacity.calculate(parameters); + hasTransitions |= textColor.calculate(parameters); + hasTransitions |= textHaloColor.calculate(parameters); + hasTransitions |= textHaloWidth.calculate(parameters); + hasTransitions |= textHaloBlur.calculate(parameters); + hasTransitions |= textTranslate.calculate(parameters); + hasTransitions |= textTranslateAnchor.calculate(parameters); + + return hasTransitions; +} + +} // namespace mbgl diff --git a/src/mbgl/layer/symbol_layer.hpp b/src/mbgl/layer/symbol_layer_properties.hpp index 3119ee1f03..ccbecef00e 100644 --- a/src/mbgl/layer/symbol_layer.hpp +++ b/src/mbgl/layer/symbol_layer_properties.hpp @@ -1,42 +1,46 @@ +// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`. + #pragma once -#include <mbgl/style/style_layer.hpp> #include <mbgl/style/layout_property.hpp> #include <mbgl/style/paint_property.hpp> +#include <mbgl/util/rapidjson.hpp> namespace mbgl { -class SpriteAtlas; +class StyleCascadeParameters; +class StyleCalculationParameters; class SymbolLayoutProperties { public: + void parse(const JSValue&); + void recalculate(const StyleCalculationParameters&); + LayoutProperty<SymbolPlacementType> symbolPlacement { SymbolPlacementType::Point }; - LayoutProperty<float> symbolSpacing { 250.0f }; + LayoutProperty<float> symbolSpacing { 250 }; LayoutProperty<bool> symbolAvoidEdges { false }; - LayoutProperty<bool> iconAllowOverlap { false }; LayoutProperty<bool> iconIgnorePlacement { false }; LayoutProperty<bool> iconOptional { false }; LayoutProperty<RotationAlignmentType> iconRotationAlignment { RotationAlignmentType::Viewport }; - LayoutProperty<float> iconSize { 1.0f }; + LayoutProperty<float> iconSize { 1 }; LayoutProperty<std::string> iconImage { "" }; - LayoutProperty<float> iconRotate { 0.0f }; - LayoutProperty<float> iconPadding { 2.0f }; + LayoutProperty<float> iconRotate { 0 }; + LayoutProperty<float> iconPadding { 2 }; LayoutProperty<bool> iconKeepUpright { false }; LayoutProperty<std::array<float, 2>> iconOffset { {{ 0, 0 }} }; - LayoutProperty<RotationAlignmentType> textRotationAlignment { RotationAlignmentType::Viewport }; LayoutProperty<std::string> textField { "" }; LayoutProperty<std::vector<std::string>> textFont { { "Open Sans Regular", "Arial Unicode MS Regular" } }; - LayoutProperty<float> textSize { 16.0f }; - LayoutProperty<float> textMaxWidth { 10.0f /* em */ }; - LayoutProperty<float> textLineHeight { 1.2f /* em */ }; - LayoutProperty<float> textLetterSpacing { 0.0f /* em */ }; + LayoutProperty<float> textSize { 16 }; + LayoutProperty<float> textMaxWidth { 10 }; + LayoutProperty<float> textLineHeight { 1.2 }; + LayoutProperty<float> textLetterSpacing { 0 }; LayoutProperty<TextJustifyType> textJustify { TextJustifyType::Center }; LayoutProperty<TextAnchorType> textAnchor { TextAnchorType::Center }; - LayoutProperty<float> textMaxAngle { 45.0f /* degrees */ }; - LayoutProperty<float> textRotate { 0.0f }; - LayoutProperty<float> textPadding { 2.0f }; + LayoutProperty<float> textMaxAngle { 45 }; + LayoutProperty<float> textRotate { 0 }; + LayoutProperty<float> textPadding { 2 }; LayoutProperty<bool> textKeepUpright { true }; LayoutProperty<TextTransformType> textTransform { TextTransformType::None }; LayoutProperty<std::array<float, 2>> textOffset { {{ 0, 0 }} }; @@ -47,48 +51,24 @@ public: class SymbolPaintProperties { public: - PaintProperty<float> iconOpacity { 1.0f }; + void parse(const JSValue&); + void cascade(const StyleCascadeParameters&); + bool recalculate(const StyleCalculationParameters&); + + PaintProperty<float> iconOpacity { 1 }; PaintProperty<Color> iconColor { {{ 0, 0, 0, 1 }} }; PaintProperty<Color> iconHaloColor { {{ 0, 0, 0, 0 }} }; - PaintProperty<float> iconHaloWidth { 0.0f }; - PaintProperty<float> iconHaloBlur { 0.0f }; + PaintProperty<float> iconHaloWidth { 0 }; + PaintProperty<float> iconHaloBlur { 0 }; PaintProperty<std::array<float, 2>> iconTranslate { {{ 0, 0 }} }; PaintProperty<TranslateAnchorType> iconTranslateAnchor { TranslateAnchorType::Map }; - - PaintProperty<float> textOpacity { 1.0f }; + PaintProperty<float> textOpacity { 1 }; PaintProperty<Color> textColor { {{ 0, 0, 0, 1 }} }; PaintProperty<Color> textHaloColor { {{ 0, 0, 0, 0 }} }; - PaintProperty<float> textHaloWidth { 0.0f }; - PaintProperty<float> textHaloBlur { 0.0f }; + PaintProperty<float> textHaloWidth { 0 }; + PaintProperty<float> textHaloBlur { 0 }; PaintProperty<std::array<float, 2>> textTranslate { {{ 0, 0 }} }; PaintProperty<TranslateAnchorType> textTranslateAnchor { TranslateAnchorType::Map }; }; -class SymbolLayer : public StyleLayer { -public: - SymbolLayer() : StyleLayer(Type::Symbol) {} - std::unique_ptr<StyleLayer> clone() const override; - - void parseLayout(const JSValue&) override; - void parsePaints(const JSValue&) override; - - void cascade(const StyleCascadeParameters&) override; - bool recalculate(const StyleCalculationParameters&) override; - - std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const override; - - SymbolLayoutProperties layout; - SymbolPaintProperties paint; - - float iconSize = 1.0f; - float textSize = 16.0f; - - SpriteAtlas* spriteAtlas = nullptr; -}; - -template <> -inline bool StyleLayer::is<SymbolLayer>() const { - return type == Type::Symbol; -} - } // namespace mbgl diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index f89fde1f03..aee6777525 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -6,7 +6,6 @@ #include <mbgl/annotation/annotation_manager.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/style_observer.hpp> -#include <mbgl/style/style_layer.hpp> #include <mbgl/style/property_transition.hpp> #include <mbgl/style/style_update_parameters.hpp> #include <mbgl/style/style_query_parameters.hpp> diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index cffc0ba8df..89b0ceefb2 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -13,7 +13,7 @@ namespace mbgl { class Painter; -class StyleLayer; +class Layer; class UnwrappedTileID; class CollisionTile; @@ -31,7 +31,7 @@ public: // Every time this bucket is getting rendered, this function is called. This happens either // once or twice (for Opaque and Transparent render passes). - virtual void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) = 0; + virtual void render(Painter&, const Layer&, const UnwrappedTileID&, const mat4&) = 0; virtual ~Bucket() = default; diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp index 6df186f2d0..969e05131b 100644 --- a/src/mbgl/renderer/circle_bucket.cpp +++ b/src/mbgl/renderer/circle_bucket.cpp @@ -21,7 +21,7 @@ void CircleBucket::upload(gl::ObjectStore& store) { } void CircleBucket::render(Painter& painter, - const StyleLayer& layer, + const Layer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { painter.renderCircle(*this, *layer.as<CircleLayer>(), tileID, matrix); diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp index b0349c7426..9c95fce045 100644 --- a/src/mbgl/renderer/circle_bucket.hpp +++ b/src/mbgl/renderer/circle_bucket.hpp @@ -19,7 +19,7 @@ public: ~CircleBucket() override; void upload(gl::ObjectStore&) override; - void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override; + void render(Painter&, const Layer&, const UnwrappedTileID&, const mat4&) override; bool hasData() const override; bool needsClipping() const override; diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp index 78d4c40a97..4a9709f4e8 100644 --- a/src/mbgl/renderer/fill_bucket.cpp +++ b/src/mbgl/renderer/fill_bucket.cpp @@ -104,7 +104,7 @@ void FillBucket::upload(gl::ObjectStore& store) { } void FillBucket::render(Painter& painter, - const StyleLayer& layer, + const Layer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { painter.renderFill(*this, *layer.as<FillLayer>(), tileID, matrix); diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp index f1b137893c..21e3239f29 100644 --- a/src/mbgl/renderer/fill_bucket.hpp +++ b/src/mbgl/renderer/fill_bucket.hpp @@ -21,7 +21,7 @@ public: ~FillBucket() override; void upload(gl::ObjectStore&) override; - void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override; + void render(Painter&, const Layer&, const UnwrappedTileID&, const mat4&) override; bool hasData() const override; bool needsClipping() const override; diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp index c308f02588..8124a5daed 100644 --- a/src/mbgl/renderer/line_bucket.cpp +++ b/src/mbgl/renderer/line_bucket.cpp @@ -444,7 +444,7 @@ void LineBucket::upload(gl::ObjectStore& store) { } void LineBucket::render(Painter& painter, - const StyleLayer& layer, + const Layer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { painter.renderLine(*this, *layer.as<LineLayer>(), tileID, matrix); diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp index 8b60be5f00..1093ec2a48 100644 --- a/src/mbgl/renderer/line_bucket.hpp +++ b/src/mbgl/renderer/line_bucket.hpp @@ -5,7 +5,7 @@ #include <mbgl/geometry/vao.hpp> #include <mbgl/geometry/elements_buffer.hpp> #include <mbgl/geometry/line_buffer.hpp> -#include <mbgl/layer/line_layer.hpp> +#include <mbgl/layer/line_layer_impl.hpp> #include <vector> @@ -26,7 +26,7 @@ public: ~LineBucket() override; void upload(gl::ObjectStore&) override; - void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override; + void render(Painter&, const Layer&, const UnwrappedTileID&, const mat4&) override; bool hasData() const override; bool needsClipping() const override; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 486865dc78..ccc6e23408 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -7,11 +7,12 @@ #include <mbgl/gl/debugging.hpp> #include <mbgl/style/style.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/layer/layer_impl.hpp> #include <mbgl/style/style_render_parameters.hpp> #include <mbgl/layer/background_layer.hpp> #include <mbgl/layer/custom_layer.hpp> +#include <mbgl/layer/custom_layer_impl.hpp> #include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/geometry/line_atlas.hpp> @@ -239,9 +240,9 @@ void Painter::renderPass(RenderPass pass_, currentLayer = i; const auto& item = *it; - const StyleLayer& layer = item.layer; + const Layer& layer = item.layer; - if (!layer.hasRenderPass(pass)) + if (!layer.baseImpl->hasRenderPass(pass)) continue; if (pass == RenderPass::Translucent) { @@ -258,12 +259,12 @@ void Painter::renderPass(RenderPass pass_, MBGL_DEBUG_GROUP("background"); renderBackground(*layer.as<BackgroundLayer>()); } else if (layer.is<CustomLayer>()) { - MBGL_DEBUG_GROUP(layer.id + " - custom"); + MBGL_DEBUG_GROUP(layer.baseImpl->id + " - custom"); VertexArrayObject::Unbind(); - layer.as<CustomLayer>()->render(state); + layer.as<CustomLayer>()->impl->render(state); config.setDirty(); } else { - MBGL_DEBUG_GROUP(layer.id + " - " + util::toString(item.tile->id)); + MBGL_DEBUG_GROUP(layer.baseImpl->id + " - " + util::toString(item.tile->id)); if (item.bucket->needsClipping()) { setClipping(item.tile->clip); } diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 70d5312b38..ad26457555 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -29,7 +29,6 @@ namespace mbgl { class Style; -class StyleLayer; class Tile; class SpriteAtlas; class GlyphAtlas; diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp index 3f01b74403..bc01d3c32f 100644 --- a/src/mbgl/renderer/painter_background.cpp +++ b/src/mbgl/renderer/painter_background.cpp @@ -1,6 +1,7 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/layer/background_layer.hpp> +#include <mbgl/layer/background_layer_impl.hpp> #include <mbgl/shader/pattern_shader.hpp> #include <mbgl/shader/plain_shader.hpp> #include <mbgl/sprite/sprite_atlas.hpp> @@ -12,7 +13,7 @@ using namespace mbgl; void Painter::renderBackground(const BackgroundLayer& layer) { // Note that for bottommost layers without a pattern, the background color is drawn with // glClear rather than this method. - const BackgroundPaintProperties& properties = layer.paint; + const BackgroundPaintProperties& properties = layer.impl->paint; bool isPatterned = !properties.backgroundPattern.value.to.empty();// && false; optional<SpriteAtlasPosition> imagePosA; diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp index fe4348c362..c371f4debe 100644 --- a/src/mbgl/renderer/painter_circle.cpp +++ b/src/mbgl/renderer/painter_circle.cpp @@ -2,6 +2,7 @@ #include <mbgl/renderer/circle_bucket.hpp> #include <mbgl/layer/circle_layer.hpp> +#include <mbgl/layer/circle_layer_impl.hpp> #include <mbgl/shader/circle_shader.hpp> @@ -20,7 +21,7 @@ void Painter::renderCircle(CircleBucket& bucket, config.depthMask = GL_FALSE; setDepthSublayer(0); - const CirclePaintProperties& properties = layer.paint; + const CirclePaintProperties& properties = layer.impl->paint; mat4 vtxMatrix = translatedMatrix(matrix, properties.circleTranslate, tileID, properties.circleTranslateAnchor); diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index 51cfa1b068..b499d20da3 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -1,6 +1,7 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/renderer/fill_bucket.hpp> #include <mbgl/layer/fill_layer.hpp> +#include <mbgl/layer/fill_layer_impl.hpp> #include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/shader/outline_shader.hpp> #include <mbgl/shader/outlinepattern_shader.hpp> @@ -13,7 +14,7 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { - const FillPaintProperties& properties = layer.paint; + const FillPaintProperties& properties = layer.impl->paint; mat4 vtxMatrix = translatedMatrix(matrix, properties.fillTranslate, tileID, properties.fillTranslateAnchor); diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp index d9e3d4037b..3cf1ad4147 100644 --- a/src/mbgl/renderer/painter_line.cpp +++ b/src/mbgl/renderer/painter_line.cpp @@ -1,6 +1,7 @@ #include <mbgl/renderer/painter.hpp> #include <mbgl/renderer/line_bucket.hpp> #include <mbgl/layer/line_layer.hpp> +#include <mbgl/layer/line_layer_impl.hpp> #include <mbgl/shader/line_shader.hpp> #include <mbgl/shader/linesdf_shader.hpp> #include <mbgl/shader/linepattern_shader.hpp> @@ -23,7 +24,7 @@ void Painter::renderLine(LineBucket& bucket, config.depthTest = GL_TRUE; config.depthMask = GL_FALSE; - const auto& properties = layer.paint; + const auto& properties = layer.impl->paint; const auto& layout = bucket.layout; // the distance over which the line edge fades out. @@ -75,8 +76,8 @@ void Painter::renderLine(LineBucket& bucket, LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, layout.lineCap == LineCapType::Round, store); LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, layout.lineCap == LineCapType::Round, store); - const float widthA = posA.width * properties.lineDasharray.value.fromScale * layer.dashLineWidth; - const float widthB = posB.width * properties.lineDasharray.value.toScale * layer.dashLineWidth; + const float widthA = posA.width * properties.lineDasharray.value.fromScale * layer.impl->dashLineWidth; + const float widthB = posB.width * properties.lineDasharray.value.toScale * layer.impl->dashLineWidth; float scaleXA = 1.0 / tileID.pixelsToTileUnits(widthA, state.getIntegerZoom()); float scaleYA = -posA.height / 2.0; diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp index 7f55e23ac2..511ac96387 100644 --- a/src/mbgl/renderer/painter_raster.cpp +++ b/src/mbgl/renderer/painter_raster.cpp @@ -2,6 +2,7 @@ #include <mbgl/gl/gl.hpp> #include <mbgl/renderer/raster_bucket.hpp> #include <mbgl/layer/raster_layer.hpp> +#include <mbgl/layer/raster_layer_impl.hpp> #include <mbgl/shader/raster_shader.hpp> using namespace mbgl; @@ -12,7 +13,7 @@ void Painter::renderRaster(RasterBucket& bucket, const mat4& matrix) { if (pass != RenderPass::Translucent) return; - const RasterPaintProperties& properties = layer.paint; + const RasterPaintProperties& properties = layer.impl->paint; if (bucket.hasData()) { config.program = rasterShader->getID(); diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp index 55d2e27c11..9774568074 100644 --- a/src/mbgl/renderer/painter_symbol.cpp +++ b/src/mbgl/renderer/painter_symbol.cpp @@ -110,7 +110,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, return; } - const auto& paint = layer.paint; + const auto& paint = layer.impl->paint; const auto& layout = bucket.layout; config.depthMask = GL_FALSE; @@ -146,10 +146,10 @@ void Painter::renderSymbol(SymbolBucket& bucket, ? state.getAngle() : 0; - const float fontSize = layer.iconSize; + const float fontSize = layer.impl->iconSize; const float fontScale = fontSize / 1.0f; - SpriteAtlas* activeSpriteAtlas = layer.spriteAtlas; + SpriteAtlas* activeSpriteAtlas = layer.impl->spriteAtlas; const bool iconScaled = fontScale != 1 || frame.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear; const bool iconTransformed = layout.iconRotationAlignment == RotationAlignmentType::Map || angleOffset != 0 || state.getPitch() != 0; config.activeTexture = GL_TEXTURE0; @@ -172,7 +172,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, paint.iconHaloBlur, paint.iconTranslate, paint.iconTranslateAnchor, - layer.iconSize); + layer.impl->iconSize); } else { mat4 vtxMatrix = translatedMatrix(matrix, paint.iconTranslate, tileID, paint.iconTranslateAnchor); @@ -235,7 +235,7 @@ void Painter::renderSymbol(SymbolBucket& bucket, paint.textHaloBlur, paint.textTranslate, paint.textTranslateAnchor, - layer.textSize); + layer.impl->textSize); } if (bucket.hasCollisionBoxData()) { diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp index d6786969c9..b16d7f8161 100644 --- a/src/mbgl/renderer/raster_bucket.cpp +++ b/src/mbgl/renderer/raster_bucket.cpp @@ -17,7 +17,7 @@ void RasterBucket::upload(gl::ObjectStore& store) { } void RasterBucket::render(Painter& painter, - const StyleLayer& layer, + const Layer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { painter.renderRaster(*this, *layer.as<RasterLayer>(), tileID, matrix); diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp index 33956fedcd..9125ef2047 100644 --- a/src/mbgl/renderer/raster_bucket.hpp +++ b/src/mbgl/renderer/raster_bucket.hpp @@ -14,7 +14,7 @@ public: RasterBucket(gl::TexturePool&); void upload(gl::ObjectStore&) override; - void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override; + void render(Painter&, const Layer&, const UnwrappedTileID&, const mat4&) override; bool hasData() const override; bool needsClipping() const override; diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index 2f5af330a4..67c8468ecd 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -85,7 +85,7 @@ void SymbolBucket::upload(gl::ObjectStore& store) { } void SymbolBucket::render(Painter& painter, - const StyleLayer& layer, + const Layer& layer, const UnwrappedTileID& tileID, const mat4& matrix) { painter.renderSymbol(*this, *layer.as<SymbolLayer>(), tileID, matrix); diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index 268bcb7c77..b19a86b275 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -13,7 +13,7 @@ #include <mbgl/text/shaping.hpp> #include <mbgl/text/quads.hpp> #include <mbgl/style/filter.hpp> -#include <mbgl/layer/symbol_layer.hpp> +#include <mbgl/layer/symbol_layer_impl.hpp> #include <memory> #include <map> @@ -70,7 +70,7 @@ public: ~SymbolBucket() override; void upload(gl::ObjectStore&) override; - void render(Painter&, const StyleLayer&, const UnwrappedTileID&, const mat4&) override; + void render(Painter&, const Layer&, const UnwrappedTileID&, const mat4&) override; bool hasData() const override; bool hasTextData() const; bool hasIconData() const; diff --git a/src/mbgl/source/source.cpp b/src/mbgl/source/source.cpp index 1c55b9c024..66546909ac 100644 --- a/src/mbgl/source/source.cpp +++ b/src/mbgl/source/source.cpp @@ -11,7 +11,7 @@ #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/storage/file_source.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/style/layer.hpp> #include <mbgl/style/style_update_parameters.hpp> #include <mbgl/style/style_query_parameters.hpp> #include <mbgl/platform/log.hpp> diff --git a/src/mbgl/style/function.hpp b/src/mbgl/style/function.hpp deleted file mode 100644 index a04fc8bb4f..0000000000 --- a/src/mbgl/style/function.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include <vector> -#include <utility> - -namespace mbgl { - -template <typename T> -class Function { -public: - using Stop = std::pair<float, T>; - using Stops = std::vector<Stop>; - - explicit Function(const T& constant) - : stops({{ 0, constant }}) {} - - explicit Function(const Stops& stops_, float base_) - : base(base_), stops(stops_) {} - - float getBase() const { return base; } - const std::vector<std::pair<float, T>>& getStops() const { return stops; } - -private: - float base = 1; - std::vector<std::pair<float, T>> stops; -}; - -} // namespace mbgl diff --git a/src/mbgl/style/function_evaluator.hpp b/src/mbgl/style/function_evaluator.hpp index 43549179df..de49e79f98 100644 --- a/src/mbgl/style/function_evaluator.hpp +++ b/src/mbgl/style/function_evaluator.hpp @@ -1,6 +1,6 @@ #pragma once -#include <mbgl/style/function.hpp> +#include <mbgl/style/types.hpp> #include <mbgl/util/interpolate.hpp> namespace mbgl { diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp index 1df780be52..a856e7589c 100644 --- a/src/mbgl/style/layout_property.hpp +++ b/src/mbgl/style/layout_property.hpp @@ -1,7 +1,6 @@ #pragma once #include <mbgl/style/property_parsing.hpp> -#include <mbgl/style/function.hpp> #include <mbgl/style/function_evaluator.hpp> #include <mbgl/util/rapidjson.hpp> @@ -27,7 +26,6 @@ public: } } - void operator=(const T& v) { value = v; } operator T() const { return value; } optional<Function<T>> parsedValue; diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp index 256f045d0d..4bbc564398 100644 --- a/src/mbgl/style/paint_property.hpp +++ b/src/mbgl/style/paint_property.hpp @@ -2,7 +2,6 @@ #include <mbgl/style/class_dictionary.hpp> #include <mbgl/style/property_parsing.hpp> -#include <mbgl/style/function.hpp> #include <mbgl/style/function_evaluator.hpp> #include <mbgl/style/property_transition.hpp> #include <mbgl/style/style_cascade_parameters.hpp> @@ -97,7 +96,6 @@ public: return cascaded->prior.operator bool(); } - void operator=(const T& v) { values.emplace(ClassID::Default, Fn(v)); } operator T() const { return value; } std::map<ClassID, Fn> values; diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp index 362b0d7b5a..67baa3ec8d 100644 --- a/src/mbgl/style/property_parsing.cpp +++ b/src/mbgl/style/property_parsing.cpp @@ -1,4 +1,7 @@ #include <mbgl/style/property_parsing.hpp> +#include <mbgl/style/property_transition.hpp> + +#include <mbgl/platform/log.hpp> #include <csscolorparser/csscolorparser.hpp> diff --git a/src/mbgl/style/property_parsing.hpp b/src/mbgl/style/property_parsing.hpp index 8deb58c00b..17c9bf6ba8 100644 --- a/src/mbgl/style/property_parsing.hpp +++ b/src/mbgl/style/property_parsing.hpp @@ -1,7 +1,6 @@ #pragma once #include <mbgl/style/types.hpp> -#include <mbgl/style/function.hpp> #include <mbgl/style/property_transition.hpp> #include <mbgl/util/rapidjson.hpp> diff --git a/src/mbgl/style/render_item.hpp b/src/mbgl/style/render_item.hpp index a70c92f620..ebf6799828 100644 --- a/src/mbgl/style/render_item.hpp +++ b/src/mbgl/style/render_item.hpp @@ -2,12 +2,12 @@ namespace mbgl { -class StyleLayer; +class Layer; class Tile; class Bucket; struct RenderItem { - inline RenderItem(const StyleLayer& layer_, + inline RenderItem(const Layer& layer_, const Tile* tile_ = nullptr, Bucket* bucket_ = nullptr) : tile(tile_), bucket(bucket_), layer(layer_) { @@ -15,7 +15,7 @@ struct RenderItem { const Tile* const tile; Bucket* const bucket; - const StyleLayer& layer; + const Layer& layer; }; } // namespace mbgl diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index bc2a1d9a40..ee847ccf57 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -4,10 +4,14 @@ #include <mbgl/tile/tile.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/layer/symbol_layer.hpp> +#include <mbgl/layer/symbol_layer_impl.hpp> #include <mbgl/layer/custom_layer.hpp> +#include <mbgl/layer/custom_layer_impl.hpp> +#include <mbgl/layer/background_layer.hpp> +#include <mbgl/layer/background_layer_impl.hpp> #include <mbgl/sprite/sprite_store.hpp> #include <mbgl/sprite/sprite_atlas.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/layer/layer_impl.hpp> #include <mbgl/style/style_parser.hpp> #include <mbgl/style/property_transition.hpp> #include <mbgl/style/class_dictionary.hpp> @@ -19,7 +23,6 @@ #include <mbgl/util/constants.hpp> #include <mbgl/util/string.hpp> #include <mbgl/platform/log.hpp> -#include <mbgl/layer/background_layer.hpp> #include <mbgl/math/minmax.hpp> #include <csscolorparser/csscolorparser.hpp> @@ -109,35 +112,35 @@ void Style::addSource(std::unique_ptr<Source> source) { sources.emplace_back(std::move(source)); } -std::vector<std::unique_ptr<StyleLayer>> Style::getLayers() const { - std::vector<std::unique_ptr<StyleLayer>> result; +std::vector<std::unique_ptr<Layer>> Style::getLayers() const { + std::vector<std::unique_ptr<Layer>> result; result.reserve(layers.size()); for (const auto& layer : layers) { - result.push_back(layer->clone()); + result.push_back(layer->baseImpl->clone()); } return result; } -std::vector<std::unique_ptr<StyleLayer>>::const_iterator Style::findLayer(const std::string& id) const { +std::vector<std::unique_ptr<Layer>>::const_iterator Style::findLayer(const std::string& id) const { return std::find_if(layers.begin(), layers.end(), [&](const auto& layer) { - return layer->id == id; + return layer->baseImpl->id == id; }); } -StyleLayer* Style::getLayer(const std::string& id) const { +Layer* Style::getLayer(const std::string& id) const { auto it = findLayer(id); return it != layers.end() ? it->get() : nullptr; } -void Style::addLayer(std::unique_ptr<StyleLayer> layer, optional<std::string> before) { +void Style::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) { if (SymbolLayer* symbolLayer = layer->as<SymbolLayer>()) { - if (!symbolLayer->spriteAtlas) { - symbolLayer->spriteAtlas = spriteAtlas.get(); + if (!symbolLayer->impl->spriteAtlas) { + symbolLayer->impl->spriteAtlas = spriteAtlas.get(); } } if (CustomLayer* customLayer = layer->as<CustomLayer>()) { - customLayer->initialize(); + customLayer->impl->initialize(); } layers.emplace(before ? findLayer(*before) : layers.end(), std::move(layer)); @@ -187,7 +190,7 @@ void Style::cascade(const TimePoint& timePoint, MapMode mode) { transitionProperties = {}; for (const auto& layer : layers) { - layer->cascade(parameters); + layer->baseImpl->cascade(parameters); } } @@ -207,10 +210,10 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) { hasPendingTransitions = false; for (const auto& layer : layers) { - hasPendingTransitions |= layer->recalculate(parameters); + hasPendingTransitions |= layer->baseImpl->recalculate(parameters); - Source* source = getSource(layer->source); - if (source && layer->needsRendering()) { + Source* source = getSource(layer->baseImpl->source); + if (source && layer->baseImpl->needsRendering()) { source->enabled = true; if (!source->loaded && !source->isLoading()) { source->load(fileSource); @@ -257,17 +260,18 @@ RenderData Style::getRenderData() const { } for (const auto& layer : layers) { - if (layer->visibility == VisibilityType::None) + if (layer->baseImpl->visibility == VisibilityType::None) continue; if (const BackgroundLayer* background = layer->as<BackgroundLayer>()) { - if (layer.get() == layers[0].get() && background->paint.backgroundPattern.value.from.empty()) { + const BackgroundPaintProperties& paint = background->impl->paint; + if (layer.get() == layers[0].get() && paint.backgroundPattern.value.from.empty()) { // This is a solid background. We can use glClear(). - result.backgroundColor = background->paint.backgroundColor; - result.backgroundColor[0] *= background->paint.backgroundOpacity; - result.backgroundColor[1] *= background->paint.backgroundOpacity; - result.backgroundColor[2] *= background->paint.backgroundOpacity; - result.backgroundColor[3] *= background->paint.backgroundOpacity; + result.backgroundColor = paint.backgroundColor; + result.backgroundColor[0] *= paint.backgroundOpacity; + result.backgroundColor[1] *= paint.backgroundOpacity; + result.backgroundColor[2] *= paint.backgroundOpacity; + result.backgroundColor[3] *= paint.backgroundOpacity; } else { // This is a textured background, or not the bottommost layer. We need to render it with a quad. result.order.emplace_back(*layer); @@ -280,9 +284,9 @@ RenderData Style::getRenderData() const { continue; } - Source* source = getSource(layer->source); + Source* source = getSource(layer->baseImpl->source); if (!source) { - Log::Warning(Event::Render, "can't find source for layer '%s'", layer->id.c_str()); + Log::Warning(Event::Render, "can't find source for layer '%s'", layer->baseImpl->id.c_str()); continue; } @@ -333,7 +337,7 @@ std::vector<Feature> Style::queryRenderedFeatures(const StyleQueryParameters& pa // Combine all results based on the style layer order. for (const auto& layer : layers) { - auto it = resultsByLayer.find(layer->id); + auto it = resultsByLayer.find(layer->baseImpl->id); if (it != resultsByLayer.end()) { std::move(it->second.begin(), it->second.end(), std::back_inserter(result)); } @@ -345,7 +349,7 @@ std::vector<Feature> Style::queryRenderedFeatures(const StyleQueryParameters& pa float Style::getQueryRadius() const { float additionalRadius = 0; for (auto& layer : layers) { - additionalRadius = util::max(additionalRadius, layer->getQueryRadius()); + additionalRadius = util::max(additionalRadius, layer->baseImpl->getQueryRadius()); } return additionalRadius; } diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp index 5fdd6cdc8e..6892f4967a 100644 --- a/src/mbgl/style/style.hpp +++ b/src/mbgl/style/style.hpp @@ -69,9 +69,9 @@ public: Source* getSource(const std::string& id) const; void addSource(std::unique_ptr<Source>); - std::vector<std::unique_ptr<StyleLayer>> getLayers() const; - StyleLayer* getLayer(const std::string& id) const; - void addLayer(std::unique_ptr<StyleLayer>, + std::vector<std::unique_ptr<Layer>> getLayers() const; + Layer* getLayer(const std::string& id) const; + void addLayer(std::unique_ptr<Layer>, optional<std::string> beforeLayerID = {}); void removeLayer(const std::string& layerID); @@ -101,11 +101,11 @@ public: private: std::vector<std::unique_ptr<Source>> sources; - std::vector<std::unique_ptr<StyleLayer>> layers; + std::vector<std::unique_ptr<Layer>> layers; std::vector<std::string> classes; optional<PropertyTransition> transitionProperties; - std::vector<std::unique_ptr<StyleLayer>>::const_iterator findLayer(const std::string& layerID) const; + std::vector<std::unique_ptr<Layer>>::const_iterator findLayer(const std::string& layerID) const; // GlyphStoreObserver implementation. void onGlyphsLoaded(const FontStack&, const GlyphRange&) override; diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index 4f081e7d85..6a67ea9daa 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -5,6 +5,8 @@ #include <mbgl/layer/symbol_layer.hpp> #include <mbgl/layer/raster_layer.hpp> #include <mbgl/layer/background_layer.hpp> +#include <mbgl/layer/layer_impl.hpp> +#include <mbgl/layer/symbol_layer_impl.hpp> #include <mbgl/platform/log.hpp> @@ -331,7 +333,7 @@ void StyleParser::parseLayers(const JSValue& value) { continue; } - layersMap.emplace(layerID, std::pair<const JSValue&, std::unique_ptr<StyleLayer>> { layerValue, nullptr }); + layersMap.emplace(layerID, std::pair<const JSValue&, std::unique_ptr<Layer>> { layerValue, nullptr }); ids.push_back(layerID); } @@ -352,7 +354,7 @@ void StyleParser::parseLayers(const JSValue& value) { } } -void StyleParser::parseLayer(const std::string& id, const JSValue& value, std::unique_ptr<StyleLayer>& layer) { +void StyleParser::parseLayer(const std::string& id, const JSValue& value, std::unique_ptr<Layer>& layer) { if (layer) { // Skip parsing this again. We already have a valid layer definition. return; @@ -386,15 +388,13 @@ void StyleParser::parseLayer(const std::string& id, const JSValue& value, std::u it->second.second); stack.pop_front(); - StyleLayer* reference = it->second.second.get(); + Layer* reference = it->second.second.get(); if (!reference) { return; } - layer = reference->clone(); - layer->id = id; - layer->ref = ref; - + layer = reference->copy(id, ref); + layer->baseImpl->parsePaints(value); } else { // Otherwise, parse the source/source-layer/filter/render keys to form the bucket. if (!value.HasMember("type")) { @@ -411,75 +411,75 @@ void StyleParser::parseLayer(const std::string& id, const JSValue& value, std::u std::string type { typeVal.GetString(), typeVal.GetStringLength() }; if (type == "fill") { - layer = std::make_unique<FillLayer>(); + layer = std::make_unique<FillLayer>(id); } else if (type == "line") { - layer = std::make_unique<LineLayer>(); + layer = std::make_unique<LineLayer>(id); } else if (type == "circle") { - layer = std::make_unique<CircleLayer>(); + layer = std::make_unique<CircleLayer>(id); } else if (type == "symbol") { - layer = std::make_unique<SymbolLayer>(); + layer = std::make_unique<SymbolLayer>(id); } else if (type == "raster") { - layer = std::make_unique<RasterLayer>(); + layer = std::make_unique<RasterLayer>(id); } else if (type == "background") { - layer = std::make_unique<BackgroundLayer>(); + layer = std::make_unique<BackgroundLayer>(id); } else { Log::Warning(Event::ParseStyle, "unknown type '%s' for layer '%s'", type.c_str(), id.c_str()); return; } - layer->id = id; + Layer::Impl* impl = layer->baseImpl.get(); if (value.HasMember("source")) { const JSValue& value_source = value["source"]; if (value_source.IsString()) { - layer->source = { value_source.GetString(), value_source.GetStringLength() }; - auto source_it = sourcesMap.find(layer->source); + 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'", layer->source.c_str(), layer->id.c_str()); + 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", layer->id.c_str()); + 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()) { - layer->sourceLayer = { value_source_layer.GetString(), value_source_layer.GetStringLength() }; + impl->sourceLayer = { value_source_layer.GetString(), value_source_layer.GetStringLength() }; } else { - Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", layer->id.c_str()); + Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", impl->id.c_str()); } } if (value.HasMember("filter")) { - layer->filter = parseFilter(value["filter"]); + impl->filter = parseFilter(value["filter"]); } if (value.HasMember("minzoom")) { const JSValue& min_zoom = value["minzoom"]; if (min_zoom.IsNumber()) { - layer->minZoom = min_zoom.GetDouble(); + impl->minZoom = min_zoom.GetDouble(); } else { - Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", layer->id.c_str()); + 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()) { - layer->maxZoom = max_zoom.GetDouble(); + impl->maxZoom = max_zoom.GetDouble(); } else { - Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", layer->id.c_str()); + Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", impl->id.c_str()); } } if (value.HasMember("layout")) { parseVisibility(*layer, value["layout"]); - layer->parseLayout(value["layout"]); + impl->parseLayout(value["layout"]); } - } - layer->parsePaints(value); + impl->parsePaints(value); + } } MBGL_DEFINE_ENUM_CLASS(VisibilityTypeClass, VisibilityType, { @@ -487,15 +487,16 @@ MBGL_DEFINE_ENUM_CLASS(VisibilityTypeClass, VisibilityType, { { VisibilityType::None, "none" }, }); -void StyleParser::parseVisibility(StyleLayer& layer, const JSValue& value) { +void StyleParser::parseVisibility(Layer& layer, const JSValue& value) { + Layer::Impl& impl = *layer.baseImpl; if (!value.HasMember("visibility")) { return; } else if (!value["visibility"].IsString()) { Log::Warning(Event::ParseStyle, "value of 'visibility' must be a string"); - layer.visibility = VisibilityType::Visible; + impl.visibility = VisibilityType::Visible; return; } - layer.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() }); + impl.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() }); } Value parseFeatureType(const Value& value) { @@ -669,7 +670,7 @@ std::vector<FontStack> StyleParser::fontStacks() const { for (const auto& layer : layers) { if (layer->is<SymbolLayer>()) { - LayoutProperty<FontStack> property = layer->as<SymbolLayer>()->layout.textFont; + LayoutProperty<FontStack> property = layer->as<SymbolLayer>()->impl->layout.textFont; if (property.parsedValue) { for (const auto& stop : property.parsedValue->getStops()) { result.insert(stop.second); diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp index 98481aec51..b5445bbfb3 100644 --- a/src/mbgl/style/style_parser.hpp +++ b/src/mbgl/style/style_parser.hpp @@ -1,7 +1,7 @@ #pragma once #include <mbgl/style/types.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/style/layer.hpp> #include <mbgl/source/source.hpp> #include <mbgl/style/filter.hpp> #include <mbgl/util/rapidjson.hpp> @@ -14,9 +14,6 @@ namespace mbgl { -class StyleLayer; -class Source; - Filter parseFilter(const JSValue&); class StyleParser { @@ -29,7 +26,7 @@ public: std::string glyphURL; std::vector<std::unique_ptr<Source>> sources; - std::vector<std::unique_ptr<StyleLayer>> layers; + std::vector<std::unique_ptr<Layer>> layers; // Statically evaluate layer properties to determine what font stacks are used. std::vector<FontStack> fontStacks() const; @@ -42,11 +39,11 @@ public: private: void parseSources(const JSValue&); void parseLayers(const JSValue&); - void parseLayer(const std::string& id, const JSValue&, std::unique_ptr<StyleLayer>&); - void parseVisibility(StyleLayer&, const JSValue& value); + void parseLayer(const std::string& id, const JSValue&, std::unique_ptr<Layer>&); + void parseVisibility(Layer&, const JSValue& value); std::unordered_map<std::string, const Source*> sourcesMap; - std::unordered_map<std::string, std::pair<const JSValue&, std::unique_ptr<StyleLayer>>> layersMap; + std::unordered_map<std::string, std::pair<const JSValue&, std::unique_ptr<Layer>>> layersMap; // Store a stack of layer IDs we're parsing right now. This is to prevent reference cycles. std::forward_list<std::string> stack; diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp index f78d913e74..3cb508a102 100644 --- a/src/mbgl/text/quads.cpp +++ b/src/mbgl/text/quads.cpp @@ -2,7 +2,7 @@ #include <mbgl/text/shaping.hpp> #include <mbgl/tile/geometry_tile.hpp> #include <mbgl/geometry/anchor.hpp> -#include <mbgl/layer/symbol_layer.hpp> +#include <mbgl/layer/symbol_layer_properties.hpp> #include <mbgl/util/math.hpp> #include <mbgl/util/constants.hpp> #include <cassert> diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp index 9ad3c3e71d..ce93b4977e 100644 --- a/src/mbgl/text/shaping.cpp +++ b/src/mbgl/text/shaping.cpp @@ -1,5 +1,5 @@ #include <mbgl/text/shaping.hpp> -#include <mbgl/layer/symbol_layer.hpp> +#include <mbgl/layer/symbol_layer_properties.hpp> namespace mbgl { diff --git a/src/mbgl/tile/raster_tile_data.cpp b/src/mbgl/tile/raster_tile_data.cpp index 29b7ca6af8..a5eab3fb23 100644 --- a/src/mbgl/tile/raster_tile_data.cpp +++ b/src/mbgl/tile/raster_tile_data.cpp @@ -61,7 +61,7 @@ RasterTileData::~RasterTileData() { cancel(); } -Bucket* RasterTileData::getBucket(StyleLayer const&) { +Bucket* RasterTileData::getBucket(const Layer&) { return bucket.get(); } diff --git a/src/mbgl/tile/raster_tile_data.hpp b/src/mbgl/tile/raster_tile_data.hpp index 74e0cc400d..ea9b144e25 100644 --- a/src/mbgl/tile/raster_tile_data.hpp +++ b/src/mbgl/tile/raster_tile_data.hpp @@ -7,7 +7,7 @@ namespace mbgl { class FileSource; class AsyncRequest; -class StyleLayer; +class Layer; namespace gl { class TexturePool; } class RasterTileData : public TileData { @@ -22,7 +22,7 @@ public: ~RasterTileData(); void cancel() override; - Bucket* getBucket(StyleLayer const &layer_desc) override; + Bucket* getBucket(const Layer&) override; private: gl::TexturePool& texturePool; diff --git a/src/mbgl/tile/tile_data.hpp b/src/mbgl/tile/tile_data.hpp index 297bfabcae..035a7ed319 100644 --- a/src/mbgl/tile/tile_data.hpp +++ b/src/mbgl/tile/tile_data.hpp @@ -16,7 +16,7 @@ namespace mbgl { -class StyleLayer; +class Layer; class Worker; class DebugBucket; class TransformState; @@ -29,7 +29,7 @@ public: // Mark this tile as no longer needed and cancel any pending work. virtual void cancel() = 0; - virtual Bucket* getBucket(const StyleLayer&) = 0; + virtual Bucket* getBucket(const Layer&) = 0; virtual bool parsePending(std::function<void (std::exception_ptr)>) { return true; } virtual void redoPlacement(PlacementConfig, const std::function<void()>&) {} diff --git a/src/mbgl/tile/tile_worker.cpp b/src/mbgl/tile/tile_worker.cpp index fdebe91229..9076684a2d 100644 --- a/src/mbgl/tile/tile_worker.cpp +++ b/src/mbgl/tile/tile_worker.cpp @@ -1,11 +1,11 @@ #include <mbgl/text/collision_tile.hpp> #include <mbgl/tile/tile_worker.hpp> #include <mbgl/tile/geometry_tile.hpp> -#include <mbgl/style/style_layer.hpp> #include <mbgl/style/style_bucket_parameters.hpp> #include <mbgl/layer/background_layer.hpp> #include <mbgl/layer/custom_layer.hpp> #include <mbgl/layer/symbol_layer.hpp> +#include <mbgl/layer/symbol_layer_impl.hpp> #include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/geometry/glyph_atlas.hpp> #include <mbgl/renderer/symbol_bucket.hpp> @@ -37,7 +37,7 @@ TileWorker::~TileWorker() { glyphAtlas.removeGlyphs(reinterpret_cast<uintptr_t>(this)); } -TileParseResult TileWorker::parseAllLayers(std::vector<std::unique_ptr<StyleLayer>> layers_, +TileParseResult TileWorker::parseAllLayers(std::vector<std::unique_ptr<Layer>> layers_, std::unique_ptr<const GeometryTile> geometryTile_, PlacementConfig config) { // We're doing a fresh parse of the tile, because the underlying data has changed. @@ -55,12 +55,12 @@ TileParseResult TileWorker::parseAllLayers(std::vector<std::unique_ptr<StyleLaye std::set<std::string> parsed; for (auto i = layers.rbegin(); i != layers.rend(); i++) { - const StyleLayer* layer = i->get(); - if (parsed.find(layer->bucketName()) == parsed.end()) { - parsed.emplace(layer->bucketName()); + const Layer* layer = i->get(); + if (parsed.find(layer->baseImpl->bucketName()) == parsed.end()) { + parsed.emplace(layer->baseImpl->bucketName()); parseLayer(layer); } - featureIndex->addBucketLayerName(layer->bucketName(), layer->id); + featureIndex->addBucketLayerName(layer->baseImpl->bucketName(), layer->baseImpl->id); } return prepareResult(config); @@ -70,16 +70,15 @@ TileParseResult TileWorker::parsePendingLayers(const PlacementConfig config) { // Try parsing the remaining layers that we couldn't parse in the first step due to missing // dependencies. for (auto it = pending.begin(); it != pending.end();) { - auto& layer = *it->first; - auto bucket = dynamic_cast<SymbolBucket*>(it->second.get()); - assert(bucket); // Only symbol layers can be pending, so the dynamic cast should never fail. - - if (!bucket->needsDependencies(glyphStore, spriteStore)) { - bucket->addFeatures(reinterpret_cast<uintptr_t>(this), - *layer.spriteAtlas, - glyphAtlas, - glyphStore); - placementPending.emplace(layer.bucketName(), std::move(it->second)); + const SymbolLayer& symbolLayer = *it->first; + SymbolBucket* symbolBucket = dynamic_cast<SymbolBucket*>(it->second.get()); + + if (!symbolBucket->needsDependencies(glyphStore, spriteStore)) { + symbolBucket->addFeatures(reinterpret_cast<uintptr_t>(this), + *symbolLayer.impl->spriteAtlas, + glyphAtlas, + glyphStore); + placementPending.emplace(symbolLayer.impl->bucketName(), std::move(it->second)); pending.erase(it++); continue; } @@ -120,7 +119,7 @@ std::unique_ptr<CollisionTile> TileWorker::redoPlacement( auto collisionTile = std::make_unique<CollisionTile>(config); for (auto i = layers.rbegin(); i != layers.rend(); i++) { - const auto it = buckets->find((*i)->id); + const auto it = buckets->find((*i)->baseImpl->id); if (it != buckets->end()) { it->second->placeFeatures(*collisionTile); } @@ -129,7 +128,7 @@ std::unique_ptr<CollisionTile> TileWorker::redoPlacement( return collisionTile; } -void TileWorker::parseLayer(const StyleLayer* layer) { +void TileWorker::parseLayer(const Layer* layer) { // Cancel early when parsing. if (obsolete) return; @@ -139,19 +138,19 @@ void TileWorker::parseLayer(const StyleLayer* layer) { return; // Skip this bucket if we are to not render this - if ((layer->source != sourceID) || - (id.overscaledZ < std::floor(layer->minZoom)) || - (id.overscaledZ >= std::ceil(layer->maxZoom)) || - (layer->visibility == VisibilityType::None)) { + if ((layer->baseImpl->source != sourceID) || + (id.overscaledZ < std::floor(layer->baseImpl->minZoom)) || + (id.overscaledZ >= std::ceil(layer->baseImpl->maxZoom)) || + (layer->baseImpl->visibility == VisibilityType::None)) { return; } - auto geometryLayer = geometryTile->getLayer(layer->sourceLayer); + auto geometryLayer = geometryTile->getLayer(layer->baseImpl->sourceLayer); if (!geometryLayer) { // The layer specified in the bucket does not exist. Do nothing. if (debug::tileParseWarnings) { Log::Warning(Event::ParseTile, "layer '%s' does not exist in tile %s", - layer->sourceLayer.c_str(), util::toString(id).c_str()); + layer->baseImpl->sourceLayer.c_str(), util::toString(id).c_str()); } return; } @@ -167,17 +166,17 @@ void TileWorker::parseLayer(const StyleLayer* layer) { *featureIndex, mode); - std::unique_ptr<Bucket> bucket = layer->createBucket(parameters); + std::unique_ptr<Bucket> bucket = layer->baseImpl->createBucket(parameters); if (layer->is<SymbolLayer>()) { if (partialParse) { // We cannot parse this bucket yet. Instead, we're saving it for later. pending.emplace_back(layer->as<SymbolLayer>(), std::move(bucket)); } else { - placementPending.emplace(layer->bucketName(), std::move(bucket)); + placementPending.emplace(layer->baseImpl->bucketName(), std::move(bucket)); } } else { - insertBucket(layer->bucketName(), std::move(bucket)); + insertBucket(layer->baseImpl->bucketName(), std::move(bucket)); } } diff --git a/src/mbgl/tile/tile_worker.hpp b/src/mbgl/tile/tile_worker.hpp index 83bf6c7f43..a04ef6a78f 100644 --- a/src/mbgl/tile/tile_worker.hpp +++ b/src/mbgl/tile/tile_worker.hpp @@ -23,7 +23,7 @@ class SpriteStore; class GlyphAtlas; class GlyphStore; class Bucket; -class StyleLayer; +class Layer; class SymbolLayer; // We're using this class to shuttle the resulting buckets from the worker thread to the MapContext @@ -51,7 +51,7 @@ public: const MapMode); ~TileWorker(); - TileParseResult parseAllLayers(std::vector<std::unique_ptr<StyleLayer>>, + TileParseResult parseAllLayers(std::vector<std::unique_ptr<Layer>>, std::unique_ptr<const GeometryTile> geometryTile, PlacementConfig); @@ -62,7 +62,7 @@ public: private: TileParseResult prepareResult(const PlacementConfig& config); - void parseLayer(const StyleLayer*); + void parseLayer(const Layer*); void insertBucket(const std::string& name, std::unique_ptr<Bucket>); std::unique_ptr<CollisionTile> placeLayers(PlacementConfig); @@ -77,7 +77,7 @@ private: bool partialParse = false; - std::vector<std::unique_ptr<StyleLayer>> layers; + std::vector<std::unique_ptr<Layer>> layers; std::unique_ptr<FeatureIndex> featureIndex; std::unique_ptr<const GeometryTile> geometryTile; diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp index 428c605f26..db0ec8029e 100644 --- a/src/mbgl/tile/vector_tile_data.cpp +++ b/src/mbgl/tile/vector_tile_data.cpp @@ -1,6 +1,6 @@ #include <mbgl/tile/vector_tile_data.hpp> #include <mbgl/tile/geometry_tile.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/layer/layer_impl.hpp> #include <mbgl/util/worker.hpp> #include <mbgl/util/work_request.hpp> #include <mbgl/style/style.hpp> @@ -139,8 +139,8 @@ bool VectorTileData::parsePending(std::function<void(std::exception_ptr)> callba return true; } -Bucket* VectorTileData::getBucket(const StyleLayer& layer) { - const auto it = buckets.find(layer.bucketName()); +Bucket* VectorTileData::getBucket(const Layer& layer) { + const auto it = buckets.find(layer.baseImpl->bucketName()); if (it == buckets.end()) { return nullptr; } diff --git a/src/mbgl/tile/vector_tile_data.hpp b/src/mbgl/tile/vector_tile_data.hpp index 2545df801b..4695338e1e 100644 --- a/src/mbgl/tile/vector_tile_data.hpp +++ b/src/mbgl/tile/vector_tile_data.hpp @@ -27,7 +27,7 @@ public: ~VectorTileData(); - Bucket* getBucket(const StyleLayer&) override; + Bucket* getBucket(const Layer&) override; bool parsePending(std::function<void(std::exception_ptr)> callback) override; diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp index e116d3f6c6..43abe6792a 100644 --- a/src/mbgl/util/worker.cpp +++ b/src/mbgl/util/worker.cpp @@ -4,7 +4,7 @@ #include <mbgl/platform/platform.hpp> #include <mbgl/renderer/raster_bucket.hpp> #include <mbgl/tile/geometry_tile.hpp> -#include <mbgl/style/style_layer.hpp> +#include <mbgl/style/layer.hpp> #include <mbgl/text/collision_tile.hpp> #include <cassert> @@ -30,7 +30,7 @@ public: } void parseGeometryTile(TileWorker* worker, - std::vector<std::unique_ptr<StyleLayer>> layers, + std::vector<std::unique_ptr<Layer>> layers, std::unique_ptr<GeometryTile> tile, PlacementConfig config, std::function<void(TileParseResult)> callback) { @@ -79,7 +79,7 @@ Worker::parseRasterTile(std::unique_ptr<RasterBucket> bucket, std::unique_ptr<AsyncRequest> Worker::parseGeometryTile(TileWorker& worker, - std::vector<std::unique_ptr<StyleLayer>> layers, + std::vector<std::unique_ptr<Layer>> layers, std::unique_ptr<GeometryTile> tile, PlacementConfig config, std::function<void(TileParseResult)> callback) { diff --git a/src/mbgl/util/worker.hpp b/src/mbgl/util/worker.hpp index e07b8b8b44..68625f42bf 100644 --- a/src/mbgl/util/worker.hpp +++ b/src/mbgl/util/worker.hpp @@ -40,7 +40,7 @@ public: std::function<void(RasterTileParseResult)> callback); Request parseGeometryTile(TileWorker&, - std::vector<std::unique_ptr<StyleLayer>>, + std::vector<std::unique_ptr<Layer>>, std::unique_ptr<GeometryTile>, PlacementConfig, std::function<void(TileParseResult)> callback); diff --git a/test/style/functions.cpp b/test/style/functions.cpp index 2389459dbc..586941ecf0 100644 --- a/test/style/functions.cpp +++ b/test/style/functions.cpp @@ -1,7 +1,6 @@ #include <iostream> #include <mbgl/test/util.hpp> -#include <mbgl/style/function.hpp> #include <mbgl/style/function_evaluator.hpp> #include <mbgl/style/style_calculation_parameters.hpp> diff --git a/test/style/source.cpp b/test/style/source.cpp index 5023a9efea..b9eb1bc434 100644 --- a/test/style/source.cpp +++ b/test/style/source.cpp @@ -274,9 +274,8 @@ TEST(Source, VectorTileCorrupt) { }; // Need to have at least one layer that uses the source. - auto layer = std::make_unique<LineLayer>(); - layer->source = "source"; - layer->sourceLayer = "water"; + auto layer = std::make_unique<LineLayer>("id"); + layer->setSource("source", "water"); test.style.addLayer(std::move(layer)); auto info = std::make_unique<SourceInfo>(); diff --git a/test/style/style_layer.cpp b/test/style/style_layer.cpp index 3b1d3be337..3274fe3377 100644 --- a/test/style/style_layer.cpp +++ b/test/style/style_layer.cpp @@ -1,24 +1,18 @@ #include <mbgl/test/util.hpp> - -#include <mbgl/style/style_layer.hpp> #include <mbgl/layer/background_layer.hpp> +#include <mbgl/layer/background_layer_impl.hpp> using namespace mbgl; -TEST(StyleLayer, Create) { - std::unique_ptr<StyleLayer> layer = std::make_unique<BackgroundLayer>(); - EXPECT_TRUE(reinterpret_cast<BackgroundLayer*>(layer.get())); -} - -TEST(StyleLayer, Clone) { - std::unique_ptr<StyleLayer> layer = std::make_unique<BackgroundLayer>(); - std::unique_ptr<StyleLayer> clone = layer->clone(); +TEST(Layer, Clone) { + std::unique_ptr<Layer> layer = std::make_unique<BackgroundLayer>("id"); + std::unique_ptr<Layer> clone = layer->baseImpl->clone(); EXPECT_NE(layer.get(), clone.get()); - EXPECT_TRUE(reinterpret_cast<BackgroundLayer*>(layer.get())); + EXPECT_TRUE(reinterpret_cast<BackgroundLayer::Impl*>(clone->baseImpl.get())); } -TEST(StyleLayer, CloneCopiesBaseProperties) { - std::unique_ptr<BackgroundLayer> layer = std::make_unique<BackgroundLayer>(); - layer->id = "test"; - EXPECT_EQ("test", layer->clone()->id); +TEST(Layer, CloneCopiesBaseProperties) { + std::unique_ptr<BackgroundLayer> layer = std::make_unique<BackgroundLayer>("id"); + layer->impl->id = "test"; + EXPECT_EQ("test", layer->baseImpl->clone()->getID()); } |