[core] Runtime style layer API

This commit is contained in:
John Firebaugh
2016-04-25 13:15:44 -07:00
parent 27baa34d44
commit a43940afb2
105 changed files with 3111 additions and 1099 deletions

View File

@@ -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 \

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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",

View File

@@ -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>

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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 {
BackgroundLayer::BackgroundLayer(const std::string& layerID)
: Layer(Type::Background, std::make_unique<Impl>())
, impl(static_cast<Impl*>(baseImpl.get())) {
impl->id = layerID;
}
BackgroundLayer::BackgroundLayer(const Impl& other)
: Layer(Type::Background, std::make_unique<Impl>(other))
, impl(static_cast<Impl*>(baseImpl.get())) {
}
BackgroundLayer::~BackgroundLayer() = default;
std::unique_ptr<Layer> BackgroundLayer::Impl::clone() const {
return std::make_unique<BackgroundLayer>(*this);
}
void BackgroundLayer::parsePaints(const JSValue& layer) {
paint.backgroundOpacity.parse("background-opacity", layer);
paint.backgroundColor.parse("background-color", layer);
paint.backgroundPattern.parse("background-pattern", layer);
// Layout properties
// Paint properties
Function<Color> BackgroundLayer::getBackgroundColor() const {
return impl->paint.backgroundColor.values.at(ClassID::Default);
}
void BackgroundLayer::cascade(const StyleCascadeParameters& parameters) {
paint.backgroundOpacity.cascade(parameters);
paint.backgroundColor.cascade(parameters);
paint.backgroundPattern.cascade(parameters);
void BackgroundLayer::setBackgroundColor(Function<Color> value) {
impl->paint.backgroundColor.values.emplace(ClassID::Default, value);
}
bool BackgroundLayer::recalculate(const StyleCalculationParameters& parameters) {
bool hasTransitions = false;
hasTransitions |= paint.backgroundOpacity.calculate(parameters);
hasTransitions |= paint.backgroundColor.calculate(parameters);
hasTransitions |= paint.backgroundPattern.calculate(parameters);
passes = paint.backgroundOpacity > 0 ? RenderPass::Translucent : RenderPass::None;
return hasTransitions;
Function<std::string> BackgroundLayer::getBackgroundPattern() const {
return impl->paint.backgroundPattern.values.at(ClassID::Default);
}
std::unique_ptr<Bucket> BackgroundLayer::createBucket(StyleBucketParameters&) const {
return nullptr;
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);
}
void BackgroundLayer::setBackgroundOpacity(Function<float> value) {
impl->paint.backgroundOpacity.values.emplace(ClassID::Default, value);
}
} // namespace mbgl

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
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);
passes = (paint.circleRadius > 0 && paint.circleColor.value[3] > 0 && paint.circleOpacity > 0)
? RenderPass::Translucent : RenderPass::None;
return hasTransitions;
const std::string& CircleLayer::getSourceLayer() const {
return impl->sourceLayer;
}
std::unique_ptr<Bucket> CircleLayer::createBucket(StyleBucketParameters& parameters) const {
auto bucket = std::make_unique<CircleBucket>(parameters.mode);
// Layout properties
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);
// Paint properties
Function<float> CircleLayer::getCircleRadius() const {
return impl->paint.circleRadius.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::setCircleRadius(Function<float> value) {
impl->paint.circleRadius.values.emplace(ClassID::Default, value);
}
bool CircleLayer::queryIntersectsGeometry(
const GeometryCollection& queryGeometry,
const GeometryCollection& geometry,
const float bearing,
const float pixelsToTileUnits) const {
Function<Color> CircleLayer::getCircleColor() const {
return impl->paint.circleColor.values.at(ClassID::Default);
}
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
queryGeometry, paint.circleTranslate, paint.circleTranslateAnchor, bearing, pixelsToTileUnits);
void CircleLayer::setCircleColor(Function<Color> value) {
impl->paint.circleColor.values.emplace(ClassID::Default, value);
}
auto circleRadius = paint.circleRadius * pixelsToTileUnits;
Function<float> CircleLayer::getCircleBlur() const {
return impl->paint.circleBlur.values.at(ClassID::Default);
}
return util::multiPolygonIntersectsBufferedMultiPoint(
translatedQueryGeometry.value_or(queryGeometry), geometry, circleRadius);
void CircleLayer::setCircleBlur(Function<float> value) {
impl->paint.circleBlur.values.emplace(ClassID::Default, value);
}
Function<float> CircleLayer::getCircleOpacity() const {
return impl->paint.circleOpacity.values.at(ClassID::Default);
}
void CircleLayer::setCircleOpacity(Function<float> value) {
impl->paint.circleOpacity.values.emplace(ClassID::Default, value);
}
Function<std::array<float, 2>> CircleLayer::getCircleTranslate() const {
return impl->paint.circleTranslate.values.at(ClassID::Default);
}
void CircleLayer::setCircleTranslate(Function<std::array<float, 2>> value) {
impl->paint.circleTranslate.values.emplace(ClassID::Default, value);
}
Function<TranslateAnchorType> CircleLayer::getCircleTranslateAnchor() const {
return impl->paint.circleTranslateAnchor.values.at(ClassID::Default);
}
void CircleLayer::setCircleTranslateAnchor(Function<TranslateAnchorType> value) {
impl->paint.circleTranslateAnchor.values.emplace(ClassID::Default, value);
}
} // namespace mbgl

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
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);
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;
const std::string& FillLayer::getSourceLayer() const {
return impl->sourceLayer;
}
std::unique_ptr<Bucket> FillLayer::createBucket(StyleBucketParameters& parameters) const {
auto bucket = std::make_unique<FillBucket>();
// Layout properties
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);
// Paint properties
Function<bool> FillLayer::getFillAntialias() const {
return impl->paint.fillAntialias.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::setFillAntialias(Function<bool> value) {
impl->paint.fillAntialias.values.emplace(ClassID::Default, value);
}
bool FillLayer::queryIntersectsGeometry(
const GeometryCollection& queryGeometry,
const GeometryCollection& geometry,
const float bearing,
const float pixelsToTileUnits) const {
Function<float> FillLayer::getFillOpacity() const {
return impl->paint.fillOpacity.values.at(ClassID::Default);
}
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
queryGeometry, paint.fillTranslate, paint.fillTranslateAnchor, bearing, pixelsToTileUnits);
void FillLayer::setFillOpacity(Function<float> value) {
impl->paint.fillOpacity.values.emplace(ClassID::Default, value);
}
return util::multiPolygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), geometry);
Function<Color> FillLayer::getFillColor() const {
return impl->paint.fillColor.values.at(ClassID::Default);
}
void FillLayer::setFillColor(Function<Color> value) {
impl->paint.fillColor.values.emplace(ClassID::Default, value);
}
Function<Color> FillLayer::getFillOutlineColor() const {
return impl->paint.fillOutlineColor.values.at(ClassID::Default);
}
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);
}
void FillLayer::setFillPattern(Function<std::string> value) {
impl->paint.fillPattern.values.emplace(ClassID::Default, value);
}
} // namespace mbgl

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

32
src/mbgl/layer/layer.cpp Normal file
View File

@@ -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

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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);
// Source
void LineLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
impl->source = sourceID;
impl->sourceLayer = sourceLayer;
}
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);
const std::string& LineLayer::getSourceID() const {
return impl->source;
}
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);
const std::string& LineLayer::getSourceLayer() const {
return impl->sourceLayer;
}
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;
// Layout properties
bool hasTransitions = false;
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);
passes = (paint.lineOpacity > 0 && paint.lineColor.value[3] > 0 && paint.lineWidth > 0)
? RenderPass::Translucent : RenderPass::None;
return hasTransitions;
Function<LineCapType> LineLayer::getLineCap() const {
return *impl->layout.lineCap.parsedValue;
}
std::unique_ptr<Bucket> LineLayer::createBucket(StyleBucketParameters& parameters) const {
auto bucket = std::make_unique<LineBucket>(parameters.tileID.overscaleFactor());
bucket->layout = layout;
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);
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);
void LineLayer::setLineCap(Function<LineCapType> value) {
impl->layout.lineCap.parsedValue = value;
}
Function<LineJoinType> LineLayer::getLineJoin() const {
return *impl->layout.lineJoin.parsedValue;
}
float LineLayer::getLineWidth() const {
if (paint.lineGapWidth > 0) {
return paint.lineGapWidth + 2 * paint.lineWidth;
} else {
return paint.lineWidth;
}
void LineLayer::setLineJoin(Function<LineJoinType> value) {
impl->layout.lineJoin.parsedValue = value;
}
Function<float> LineLayer::getLineMiterLimit() const {
return *impl->layout.lineMiterLimit.parsedValue;
}
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;
void LineLayer::setLineMiterLimit(Function<float> value) {
impl->layout.lineMiterLimit.parsedValue = value;
}
Function<float> LineLayer::getLineRoundLimit() const {
return *impl->layout.lineRoundLimit.parsedValue;
}
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::setLineRoundLimit(Function<float> value) {
impl->layout.lineRoundLimit.parsedValue = value;
}
bool LineLayer::queryIntersectsGeometry(
const GeometryCollection& queryGeometry,
const GeometryCollection& geometry,
const float bearing,
const float pixelsToTileUnits) const {
// Paint properties
const float halfWidth = getLineWidth() / 2.0 * pixelsToTileUnits;
Function<float> LineLayer::getLineOpacity() const {
return impl->paint.lineOpacity.values.at(ClassID::Default);
}
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
queryGeometry, paint.lineTranslate, paint.lineTranslateAnchor, bearing, pixelsToTileUnits);
auto offsetGeometry = offsetLine(geometry, paint.lineOffset * pixelsToTileUnits);
void LineLayer::setLineOpacity(Function<float> value) {
impl->paint.lineOpacity.values.emplace(ClassID::Default, value);
}
return util::multiPolygonIntersectsBufferedMultiLine(
translatedQueryGeometry.value_or(queryGeometry),
offsetGeometry.value_or(geometry),
halfWidth);
Function<Color> LineLayer::getLineColor() const {
return impl->paint.lineColor.values.at(ClassID::Default);
}
void LineLayer::setLineColor(Function<Color> value) {
impl->paint.lineColor.values.emplace(ClassID::Default, value);
}
Function<std::array<float, 2>> LineLayer::getLineTranslate() const {
return impl->paint.lineTranslate.values.at(ClassID::Default);
}
void LineLayer::setLineTranslate(Function<std::array<float, 2>> value) {
impl->paint.lineTranslate.values.emplace(ClassID::Default, value);
}
Function<TranslateAnchorType> LineLayer::getLineTranslateAnchor() const {
return impl->paint.lineTranslateAnchor.values.at(ClassID::Default);
}
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);
}
void LineLayer::setLineWidth(Function<float> value) {
impl->paint.lineWidth.values.emplace(ClassID::Default, value);
}
Function<float> LineLayer::getLineGapWidth() const {
return impl->paint.lineGapWidth.values.at(ClassID::Default);
}
void LineLayer::setLineGapWidth(Function<float> value) {
impl->paint.lineGapWidth.values.emplace(ClassID::Default, value);
}
Function<float> LineLayer::getLineOffset() const {
return impl->paint.lineOffset.values.at(ClassID::Default);
}
void LineLayer::setLineOffset(Function<float> value) {
impl->paint.lineOffset.values.emplace(ClassID::Default, value);
}
Function<float> LineLayer::getLineBlur() const {
return impl->paint.lineBlur.values.at(ClassID::Default);
}
void LineLayer::setLineBlur(Function<float> value) {
impl->paint.lineBlur.values.emplace(ClassID::Default, value);
}
Function<std::vector<float>> LineLayer::getLineDasharray() const {
return impl->paint.lineDasharray.values.at(ClassID::Default);
}
void LineLayer::setLineDasharray(Function<std::vector<float>> value) {
impl->paint.lineDasharray.values.emplace(ClassID::Default, value);
}
Function<std::string> LineLayer::getLinePattern() const {
return impl->paint.linePattern.values.at(ClassID::Default);
}
void LineLayer::setLinePattern(Function<std::string> value) {
impl->paint.linePattern.values.emplace(ClassID::Default, value);
}
} // namespace mbgl

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
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);
const std::string& RasterLayer::getSourceID() const {
return impl->source;
}
bool RasterLayer::recalculate(const StyleCalculationParameters& parameters) {
bool hasTransitions = false;
// Layout properties
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);
passes = paint.rasterOpacity > 0 ? RenderPass::Translucent : RenderPass::None;
// Paint properties
return hasTransitions;
Function<float> RasterLayer::getRasterOpacity() const {
return impl->paint.rasterOpacity.values.at(ClassID::Default);
}
std::unique_ptr<Bucket> RasterLayer::createBucket(StyleBucketParameters&) const {
return nullptr;
void RasterLayer::setRasterOpacity(Function<float> value) {
impl->paint.rasterOpacity.values.emplace(ClassID::Default, value);
}
Function<float> RasterLayer::getRasterHueRotate() const {
return impl->paint.rasterHueRotate.values.at(ClassID::Default);
}
void RasterLayer::setRasterHueRotate(Function<float> value) {
impl->paint.rasterHueRotate.values.emplace(ClassID::Default, value);
}
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);
}
Function<float> RasterLayer::getRasterFadeDuration() const {
return impl->paint.rasterFadeDuration.values.at(ClassID::Default);
}
void RasterLayer::setRasterFadeDuration(Function<float> value) {
impl->paint.rasterFadeDuration.values.emplace(ClassID::Default, value);
}
} // namespace mbgl

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
// Source
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::setSource(const std::string& sourceID, const std::string& sourceLayer) {
impl->source = sourceID;
impl->sourceLayer = sourceLayer;
}
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);
const std::string& SymbolLayer::getSourceID() const {
return impl->source;
}
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);
const std::string& SymbolLayer::getSourceLayer() const {
return impl->sourceLayer;
}
bool SymbolLayer::recalculate(const StyleCalculationParameters& parameters) {
bool hasTransitions = false;
// Layout properties
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;
Function<SymbolPlacementType> SymbolLayer::getSymbolPlacement() const {
return *impl->layout.symbolPlacement.parsedValue;
}
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());
void SymbolLayer::setSymbolPlacement(Function<SymbolPlacementType> value) {
impl->layout.symbolPlacement.parsedValue = value;
}
Function<float> SymbolLayer::getSymbolSpacing() const {
return *impl->layout.symbolSpacing.parsedValue;
}
bucket->layout = layout;
void SymbolLayer::setSymbolSpacing(Function<float> value) {
impl->layout.symbolSpacing.parsedValue = value;
}
Function<bool> SymbolLayer::getSymbolAvoidEdges() const {
return *impl->layout.symbolAvoidEdges.parsedValue;
}
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);
void SymbolLayer::setSymbolAvoidEdges(Function<bool> value) {
impl->layout.symbolAvoidEdges.parsedValue = value;
}
Function<bool> SymbolLayer::getIconAllowOverlap() const {
return *impl->layout.iconAllowOverlap.parsedValue;
}
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);
void SymbolLayer::setIconAllowOverlap(Function<bool> value) {
impl->layout.iconAllowOverlap.parsedValue = value;
}
Function<bool> SymbolLayer::getIconIgnorePlacement() const {
return *impl->layout.iconIgnorePlacement.parsedValue;
}
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);
void SymbolLayer::setIconIgnorePlacement(Function<bool> value) {
impl->layout.iconIgnorePlacement.parsedValue = value;
}
Function<bool> SymbolLayer::getIconOptional() const {
return *impl->layout.iconOptional.parsedValue;
}
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));
void SymbolLayer::setIconOptional(Function<bool> value) {
impl->layout.iconOptional.parsedValue = value;
}
Function<RotationAlignmentType> SymbolLayer::getIconRotationAlignment() const {
return *impl->layout.iconRotationAlignment.parsedValue;
}
bucket->parseFeatures(parameters.layer, filter);
void SymbolLayer::setIconRotationAlignment(Function<RotationAlignmentType> value) {
impl->layout.iconRotationAlignment.parsedValue = value;
}
Function<float> SymbolLayer::getIconSize() const {
return *impl->layout.iconSize.parsedValue;
}
if (bucket->needsDependencies(parameters.glyphStore, parameters.spriteStore)) {
parameters.partialParse = true;
}
void SymbolLayer::setIconSize(Function<float> value) {
impl->layout.iconSize.parsedValue = value;
}
Function<std::string> SymbolLayer::getIconImage() const {
return *impl->layout.iconImage.parsedValue;
}
// 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);
}
void SymbolLayer::setIconImage(Function<std::string> value) {
impl->layout.iconImage.parsedValue = value;
}
Function<float> SymbolLayer::getIconRotate() const {
return *impl->layout.iconRotate.parsedValue;
}
return std::move(bucket);
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:
LayoutProperty<SymbolPlacementType> symbolPlacement { SymbolPlacementType::Point };
LayoutProperty<float> symbolSpacing { 250.0f };
LayoutProperty<bool> symbolAvoidEdges { false };
void parse(const JSValue&);
void recalculate(const StyleCalculationParameters&);
LayoutProperty<SymbolPlacementType> symbolPlacement { SymbolPlacementType::Point };
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

View File

@@ -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>

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -29,7 +29,6 @@
namespace mbgl {
class Style;
class StyleLayer;
class Tile;
class SpriteAtlas;
class GlyphAtlas;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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();

View File

@@ -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()) {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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>

View File

@@ -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

View File

@@ -1,6 +1,6 @@
#pragma once
#include <mbgl/style/function.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/util/interpolate.hpp>
namespace mbgl {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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>

View File

@@ -1,5 +1,5 @@
#include <mbgl/text/shaping.hpp>
#include <mbgl/layer/symbol_layer.hpp>
#include <mbgl/layer/symbol_layer_properties.hpp>
namespace mbgl {

View File

@@ -61,7 +61,7 @@ RasterTileData::~RasterTileData() {
cancel();
}
Bucket* RasterTileData::getBucket(StyleLayer const&) {
Bucket* RasterTileData::getBucket(const Layer&) {
return bucket.get();
}

View File

@@ -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;

View File

@@ -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()>&) {}

View File

@@ -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.
const SymbolLayer& symbolLayer = *it->first;
SymbolBucket* symbolBucket = dynamic_cast<SymbolBucket*>(it->second.get());
if (!bucket->needsDependencies(glyphStore, spriteStore)) {
bucket->addFeatures(reinterpret_cast<uintptr_t>(this),
*layer.spriteAtlas,
glyphAtlas,
glyphStore);
placementPending.emplace(layer.bucketName(), std::move(it->second));
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));
}
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

Some files were not shown because too many files have changed in this diff Show More