diff options
Diffstat (limited to 'src/mbgl/renderer/layers')
-rw-r--r-- | src/mbgl/renderer/layers/render_background_layer.cpp | 37 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_background_layer.hpp | 32 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_circle_layer.cpp | 67 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_circle_layer.hpp | 39 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_custom_layer.cpp | 76 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_custom_layer.hpp | 31 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp | 55 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp | 39 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_layer.cpp | 71 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_fill_layer.hpp | 39 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_line_layer.cpp | 119 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_line_layer.hpp | 51 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_raster_layer.cpp | 50 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_raster_layer.hpp | 34 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_symbol_layer.cpp | 107 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_symbol_layer.hpp | 95 |
16 files changed, 942 insertions, 0 deletions
diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp new file mode 100644 index 0000000000..702977cd23 --- /dev/null +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -0,0 +1,37 @@ +#include <mbgl/renderer/layers/render_background_layer.hpp> +#include <mbgl/style/layers/background_layer_impl.hpp> +#include <mbgl/renderer/bucket.hpp> + +namespace mbgl { + +RenderBackgroundLayer::RenderBackgroundLayer(Immutable<style::BackgroundLayer::Impl> _impl) + : RenderLayer(style::LayerType::Background, _impl), + unevaluated(impl().paint.untransitioned()) { +} + +const style::BackgroundLayer::Impl& RenderBackgroundLayer::impl() const { + return static_cast<const style::BackgroundLayer::Impl&>(*baseImpl); +} + +std::unique_ptr<Bucket> RenderBackgroundLayer::createBucket(const BucketParameters &, + const std::vector<const RenderLayer *> &) const { + assert(false); + return nullptr; +} + +void RenderBackgroundLayer::transition(const TransitionParameters ¶meters) { + unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters ¶meters) { + evaluated = unevaluated.evaluate(parameters); + + passes = evaluated.get<style::BackgroundOpacity>() > 0 ? RenderPass::Translucent + : RenderPass::None; +} + +bool RenderBackgroundLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp new file mode 100644 index 0000000000..0fba3d2bb1 --- /dev/null +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/background_layer_impl.hpp> +#include <mbgl/style/layers/background_layer_properties.hpp> + +namespace mbgl { + +class RenderBackgroundLayer: public RenderLayer { +public: + RenderBackgroundLayer(Immutable<style::BackgroundLayer::Impl>); + ~RenderBackgroundLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + + // Paint properties + style::BackgroundPaintProperties::Unevaluated unevaluated; + style::BackgroundPaintProperties::PossiblyEvaluated evaluated; + + const style::BackgroundLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is<RenderBackgroundLayer>() const { + return type == style::LayerType::Background; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp new file mode 100644 index 0000000000..51a5ecd7d6 --- /dev/null +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -0,0 +1,67 @@ +#include <mbgl/renderer/layers/render_circle_layer.hpp> +#include <mbgl/renderer/buckets/circle_bucket.hpp> +#include <mbgl/style/layers/circle_layer_impl.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/util/intersection_tests.hpp> + +namespace mbgl { + +RenderCircleLayer::RenderCircleLayer(Immutable<style::CircleLayer::Impl> _impl) + : RenderLayer(style::LayerType::Circle, _impl), + unevaluated(impl().paint.untransitioned()) { +} + +const style::CircleLayer::Impl& RenderCircleLayer::impl() const { + return static_cast<const style::CircleLayer::Impl&>(*baseImpl); +} + +std::unique_ptr<Bucket> RenderCircleLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const { + return std::make_unique<CircleBucket>(parameters, layers); +} + +void RenderCircleLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + passes = ((evaluated.get<style::CircleRadius>().constantOr(1) > 0 || + evaluated.get<style::CircleStrokeWidth>().constantOr(1) > 0) + && (evaluated.get<style::CircleColor>().constantOr(Color::black()).a > 0 || + evaluated.get<style::CircleStrokeColor>().constantOr(Color::black()).a > 0) + && (evaluated.get<style::CircleOpacity>().constantOr(1) > 0 || + evaluated.get<style::CircleStrokeOpacity>().constantOr(1) > 0)) + ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderCircleLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +bool RenderCircleLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float zoom, + const float bearing, + const float pixelsToTileUnits) const { + + // Translate query geometry + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get<style::CircleTranslate>(), + evaluated.get<style::CircleTranslateAnchor>(), + bearing, + pixelsToTileUnits); + + // Evaluate function + auto circleRadius = evaluated.get<style::CircleRadius>() + .evaluate(feature, zoom, style::CircleRadius::defaultValue()) + * pixelsToTileUnits; + + // Test intersection + return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), circleRadius); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp new file mode 100644 index 0000000000..4ae7399ad1 --- /dev/null +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/circle_layer_impl.hpp> +#include <mbgl/style/layers/circle_layer_properties.hpp> + +namespace mbgl { + +class RenderCircleLayer: public RenderLayer { +public: + RenderCircleLayer(Immutable<style::CircleLayer::Impl>); + ~RenderCircleLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + + // Paint properties + style::CirclePaintProperties::Unevaluated unevaluated; + style::CirclePaintProperties::PossiblyEvaluated evaluated; + + const style::CircleLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is<RenderCircleLayer>() const { + return type == style::LayerType::Circle; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_custom_layer.cpp b/src/mbgl/renderer/layers/render_custom_layer.cpp new file mode 100644 index 0000000000..4d6084075d --- /dev/null +++ b/src/mbgl/renderer/layers/render_custom_layer.cpp @@ -0,0 +1,76 @@ +#include <mbgl/renderer/layers/render_custom_layer.hpp> +#include <mbgl/renderer/painter.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/style/layers/custom_layer_impl.hpp> +#include <mbgl/map/transform_state.hpp> +#include <mbgl/map/backend_scope.hpp> + +namespace mbgl { + +using namespace style; + +RenderCustomLayer::RenderCustomLayer(Immutable<style::CustomLayer::Impl> _impl) + : RenderLayer(LayerType::Custom, _impl) { +} + +RenderCustomLayer::~RenderCustomLayer() { + assert(BackendScope::exists()); + if (initialized && impl().deinitializeFn) { + impl().deinitializeFn(impl().context); + } +} + +const CustomLayer::Impl& RenderCustomLayer::impl() const { + return static_cast<const CustomLayer::Impl&>(*baseImpl); +} + +void RenderCustomLayer::evaluate(const PropertyEvaluationParameters&) { + passes = RenderPass::Translucent; +} + +bool RenderCustomLayer::hasTransition() const { + return false; +} + +std::unique_ptr<Bucket> RenderCustomLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const { + assert(false); + return nullptr; +} + +void RenderCustomLayer::render(Painter& painter, PaintParameters& paintParameters, RenderSource*) { + if (!initialized) { + assert(impl().initializeFn); + impl().initializeFn(impl().context); + initialized = true; + } + + gl::Context& context = painter.context; + const TransformState& state = painter.state; + + // Reset GL state to a known state so the CustomLayer always has a clean slate. + context.vertexArrayObject = 0; + context.setDepthMode(painter.depthModeForSublayer(0, gl::DepthMode::ReadOnly)); + context.setStencilMode(gl::StencilMode::disabled()); + context.setColorMode(painter.colorModeForRenderPass()); + + CustomLayerRenderParameters parameters; + + parameters.width = state.getSize().width; + parameters.height = state.getSize().height; + 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.fieldOfView = state.getFieldOfView(); + + assert(impl().renderFn); + impl().renderFn(impl().context, parameters); + + // Reset the view back to our original one, just in case the CustomLayer changed + // the viewport or Framebuffer. + paintParameters.view.bind(); + context.setDirtyState(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_custom_layer.hpp b/src/mbgl/renderer/layers/render_custom_layer.hpp new file mode 100644 index 0000000000..dd52d315cf --- /dev/null +++ b/src/mbgl/renderer/layers/render_custom_layer.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/custom_layer_impl.hpp> + +namespace mbgl { + +class RenderCustomLayer: public RenderLayer { +public: + RenderCustomLayer(Immutable<style::CustomLayer::Impl>); + ~RenderCustomLayer() final; + + void transition(const TransitionParameters&) final {} + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const final; + void render(Painter&, PaintParameters&, RenderSource*) final; + + const style::CustomLayer::Impl& impl() const; + +private: + bool initialized = false; +}; + +template <> +inline bool RenderLayer::is<RenderCustomLayer>() const { + return type == style::LayerType::Custom; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp new file mode 100644 index 0000000000..cd69316670 --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -0,0 +1,55 @@ +#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp> +#include <mbgl/renderer/buckets/fill_extrusion_bucket.hpp> +#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/util/intersection_tests.hpp> + +namespace mbgl { + +RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl> _impl) + : RenderLayer(style::LayerType::FillExtrusion, _impl), + unevaluated(impl().paint.untransitioned()) { +} + +const style::FillExtrusionLayer::Impl& RenderFillExtrusionLayer::impl() const { + return static_cast<const style::FillExtrusionLayer::Impl&>(*baseImpl); +} + +std::unique_ptr<Bucket> RenderFillExtrusionLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const { + return std::make_unique<FillExtrusionBucket>(parameters, layers); +} + +void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + passes = (evaluated.get<style::FillExtrusionOpacity>() > 0) ? RenderPass::Translucent + : RenderPass::None; +} + +bool RenderFillExtrusionLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +bool RenderFillExtrusionLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float, + const float bearing, + const float pixelsToTileUnits) const { + + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get<style::FillExtrusionTranslate>(), + evaluated.get<style::FillExtrusionTranslateAnchor>(), + bearing, + pixelsToTileUnits); + + return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp new file mode 100644 index 0000000000..1a55b56836 --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp> +#include <mbgl/style/layers/fill_extrusion_layer_properties.hpp> + +namespace mbgl { + +class RenderFillExtrusionLayer: public RenderLayer { +public: + RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl>); + ~RenderFillExtrusionLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + + // Paint properties + style::FillExtrusionPaintProperties::Unevaluated unevaluated; + style::FillExtrusionPaintProperties::PossiblyEvaluated evaluated; + + const style::FillExtrusionLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is<RenderFillExtrusionLayer>() const { + return type == style::LayerType::FillExtrusion; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp new file mode 100644 index 0000000000..f1c7e97067 --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -0,0 +1,71 @@ +#include <mbgl/renderer/layers/render_fill_layer.hpp> +#include <mbgl/renderer/buckets/fill_bucket.hpp> +#include <mbgl/style/layers/fill_layer_impl.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/util/intersection_tests.hpp> + +namespace mbgl { + +RenderFillLayer::RenderFillLayer(Immutable<style::FillLayer::Impl> _impl) + : RenderLayer(style::LayerType::Fill, _impl), + unevaluated(impl().paint.untransitioned()) { +} + +const style::FillLayer::Impl& RenderFillLayer::impl() const { + return static_cast<const style::FillLayer::Impl&>(*baseImpl); +} + +std::unique_ptr<Bucket> RenderFillLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const { + return std::make_unique<FillBucket>(parameters, layers); +} + +void RenderFillLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + if (unevaluated.get<style::FillOutlineColor>().isUndefined()) { + evaluated.get<style::FillOutlineColor>() = evaluated.get<style::FillColor>(); + } + + passes = RenderPass::None; + + if (evaluated.get<style::FillAntialias>()) { + passes |= RenderPass::Translucent; + } + + if (!unevaluated.get<style::FillPattern>().isUndefined() + || evaluated.get<style::FillColor>().constantOr(Color()).a < 1.0f + || evaluated.get<style::FillOpacity>().constantOr(0) < 1.0f) { + passes |= RenderPass::Translucent; + } else { + passes |= RenderPass::Opaque; + } +} + +bool RenderFillLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +bool RenderFillLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float, + const float bearing, + const float pixelsToTileUnits) const { + + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get<style::FillTranslate>(), + evaluated.get<style::FillTranslateAnchor>(), + bearing, + pixelsToTileUnits); + + return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); +} + + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp new file mode 100644 index 0000000000..1960fb653f --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/fill_layer_impl.hpp> +#include <mbgl/style/layers/fill_layer_properties.hpp> + +namespace mbgl { + +class RenderFillLayer: public RenderLayer { +public: + RenderFillLayer(Immutable<style::FillLayer::Impl>); + ~RenderFillLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + + // Paint properties + style::FillPaintProperties::Unevaluated unevaluated; + style::FillPaintProperties::PossiblyEvaluated evaluated; + + const style::FillLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is<RenderFillLayer>() const { + return type == style::LayerType::Fill; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp new file mode 100644 index 0000000000..c27e5ea990 --- /dev/null +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -0,0 +1,119 @@ +#include <mbgl/renderer/layers/render_line_layer.hpp> +#include <mbgl/renderer/buckets/line_bucket.hpp> +#include <mbgl/style/layers/line_layer_impl.hpp> +#include <mbgl/geometry/feature_index.hpp> +#include <mbgl/util/math.hpp> +#include <mbgl/util/intersection_tests.hpp> + +namespace mbgl { + +RenderLineLayer::RenderLineLayer(Immutable<style::LineLayer::Impl> _impl) + : RenderLayer(style::LayerType::Line, _impl), + unevaluated(impl().paint.untransitioned()) { +} + +const style::LineLayer::Impl& RenderLineLayer::impl() const { + return static_cast<const style::LineLayer::Impl&>(*baseImpl); +} + +std::unique_ptr<Bucket> RenderLineLayer::createBucket(const BucketParameters& parameters, const std::vector<const RenderLayer*>& layers) const { + return std::make_unique<LineBucket>(parameters, layers, impl().layout); +} + +void RenderLineLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { + style::Properties<LineFloorwidth>::Unevaluated extra(unevaluated.get<style::LineWidth>()); + + auto dashArrayParams = parameters; + dashArrayParams.useIntegerZoom = true; + + evaluated = RenderLinePaintProperties::PossiblyEvaluated( + unevaluated.evaluate(parameters).concat(extra.evaluate(dashArrayParams))); + + passes = (evaluated.get<style::LineOpacity>().constantOr(1.0) > 0 + && evaluated.get<style::LineColor>().constantOr(Color::black()).a > 0 + && evaluated.get<style::LineWidth>().constantOr(1.0) > 0) + ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderLineLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +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; +} + +bool RenderLineLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float zoom, + const float bearing, + const float pixelsToTileUnits) const { + + // Translate query geometry + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get<style::LineTranslate>(), + evaluated.get<style::LineTranslateAnchor>(), + bearing, + pixelsToTileUnits); + + // Evaluate function + auto offset = evaluated.get<style::LineOffset>() + .evaluate(feature, zoom, style::LineOffset::defaultValue()) * pixelsToTileUnits; + + // Apply offset to geometry + auto offsetGeometry = offsetLine(feature.getGeometries(), offset); + + // Test intersection + const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits; + return util::polygonIntersectsBufferedMultiLine( + translatedQueryGeometry.value_or(queryGeometry), + offsetGeometry.value_or(feature.getGeometries()), + halfWidth); +} + +float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const { + float lineWidth = evaluated.get<style::LineWidth>() + .evaluate(feature, zoom, style::LineWidth::defaultValue()); + float gapWidth = evaluated.get<style::LineGapWidth>() + .evaluate(feature, zoom, style::LineGapWidth::defaultValue()); + if (gapWidth) { + return gapWidth + 2 * lineWidth; + } else { + return lineWidth; + } +} + + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp new file mode 100644 index 0000000000..77551b6b7c --- /dev/null +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/line_layer_impl.hpp> +#include <mbgl/style/layers/line_layer_properties.hpp> +#include <mbgl/programs/uniforms.hpp> + +namespace mbgl { + +struct LineFloorwidth : style::DataDrivenPaintProperty<float, attributes::a_floorwidth, uniforms::u_floorwidth> { + static float defaultValue() { return 1; } +}; + +class RenderLinePaintProperties : public style::ConcatenateProperties< + style::LinePaintProperties::PropertyTypes, + TypeList<LineFloorwidth>>::Type {}; + +class RenderLineLayer: public RenderLayer { +public: + RenderLineLayer(Immutable<style::LineLayer::Impl>); + ~RenderLineLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + + // Paint properties + style::LinePaintProperties::Unevaluated unevaluated; + RenderLinePaintProperties::PossiblyEvaluated evaluated; + + const style::LineLayer::Impl& impl() const; + +private: + float getLineWidth(const GeometryTileFeature&, const float) const; +}; + +template <> +inline bool RenderLayer::is<RenderLineLayer>() const { + return type == style::LayerType::Line; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp new file mode 100644 index 0000000000..84e27a3895 --- /dev/null +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -0,0 +1,50 @@ +#include <mbgl/renderer/layers/render_raster_layer.hpp> +#include <mbgl/renderer/bucket.hpp> +#include <mbgl/style/layers/raster_layer_impl.hpp> +#include <mbgl/gl/context.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/tile/tile.hpp> +#include <mbgl/renderer/sources/render_image_source.hpp> +#include <mbgl/renderer/painter.hpp> + +namespace mbgl { + +RenderRasterLayer::RenderRasterLayer(Immutable<style::RasterLayer::Impl> _impl) + : RenderLayer(style::LayerType::Raster, _impl), + unevaluated(impl().paint.untransitioned()) { +} + +const style::RasterLayer::Impl& RenderRasterLayer::impl() const { + return static_cast<const style::RasterLayer::Impl&>(*baseImpl); +} + +std::unique_ptr<Bucket> RenderRasterLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const { + assert(false); + return nullptr; +} + +void RenderRasterLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + passes = evaluated.get<style::RasterOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderRasterLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +void RenderRasterLayer::render(Painter& painter, PaintParameters& parameters, RenderSource* source) { + RenderLayer::render(painter, parameters, source); + if (renderTiles.empty()) { + RenderImageSource* imageSource = source->as<RenderImageSource>(); + if (imageSource) { + imageSource->render(painter, parameters, *this); + } + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp new file mode 100644 index 0000000000..ce46152a95 --- /dev/null +++ b/src/mbgl/renderer/layers/render_raster_layer.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/layers/raster_layer_impl.hpp> +#include <mbgl/style/layers/raster_layer_properties.hpp> + +namespace mbgl { + +class RenderRasterLayer: public RenderLayer { +public: + RenderRasterLayer(Immutable<style::RasterLayer::Impl>); + ~RenderRasterLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + void render(Painter&, PaintParameters&, RenderSource*) override; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + + // Paint properties + style::RasterPaintProperties::Unevaluated unevaluated; + style::RasterPaintProperties::PossiblyEvaluated evaluated; + + const style::RasterLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is<RenderRasterLayer>() const { + return type == style::LayerType::Raster; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp new file mode 100644 index 0000000000..6540fc9612 --- /dev/null +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -0,0 +1,107 @@ +#include <mbgl/renderer/layers/render_symbol_layer.hpp> +#include <mbgl/layout/symbol_layout.hpp> +#include <mbgl/renderer/bucket.hpp> +#include <mbgl/renderer/bucket_parameters.hpp> +#include <mbgl/renderer/property_evaluation_parameters.hpp> +#include <mbgl/style/layers/symbol_layer_impl.hpp> +#include <mbgl/tile/geometry_tile_data.hpp> + +namespace mbgl { + +RenderSymbolLayer::RenderSymbolLayer(Immutable<style::SymbolLayer::Impl> _impl) + : RenderLayer(style::LayerType::Symbol, _impl), + unevaluated(impl().paint.untransitioned()) { +} + +const style::SymbolLayer::Impl& RenderSymbolLayer::impl() const { + return static_cast<const style::SymbolLayer::Impl&>(*baseImpl); +} + +std::unique_ptr<Bucket> RenderSymbolLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const { + assert(false); // Should be calling createLayout() instead. + return nullptr; +} + +std::unique_ptr<SymbolLayout> RenderSymbolLayer::createLayout(const BucketParameters& parameters, + const std::vector<const RenderLayer*>& group, + std::unique_ptr<GeometryTileLayer> layer, + GlyphDependencies& glyphDependencies, + ImageDependencies& imageDependencies) const { + return std::make_unique<SymbolLayout>(parameters, + group, + std::move(layer), + imageDependencies, + glyphDependencies); +} + +void RenderSymbolLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated)); +} + +void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + auto hasIconOpacity = evaluated.get<style::IconColor>().constantOr(Color::black()).a > 0 || + evaluated.get<style::IconHaloColor>().constantOr(Color::black()).a > 0; + auto hasTextOpacity = evaluated.get<style::TextColor>().constantOr(Color::black()).a > 0 || + evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0; + + passes = ((evaluated.get<style::IconOpacity>().constantOr(1) > 0 && hasIconOpacity && iconSize > 0) + || (evaluated.get<style::TextOpacity>().constantOr(1) > 0 && hasTextOpacity && textSize > 0)) + ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderSymbolLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +style::IconPaintProperties::PossiblyEvaluated RenderSymbolLayer::iconPaintProperties() const { + return style::IconPaintProperties::PossiblyEvaluated { + evaluated.get<style::IconOpacity>(), + evaluated.get<style::IconColor>(), + evaluated.get<style::IconHaloColor>(), + evaluated.get<style::IconHaloWidth>(), + evaluated.get<style::IconHaloBlur>(), + evaluated.get<style::IconTranslate>(), + evaluated.get<style::IconTranslateAnchor>() + }; +} + +style::TextPaintProperties::PossiblyEvaluated RenderSymbolLayer::textPaintProperties() const { + return style::TextPaintProperties::PossiblyEvaluated { + evaluated.get<style::TextOpacity>(), + evaluated.get<style::TextColor>(), + evaluated.get<style::TextHaloColor>(), + evaluated.get<style::TextHaloWidth>(), + evaluated.get<style::TextHaloBlur>(), + evaluated.get<style::TextTranslate>(), + evaluated.get<style::TextTranslateAnchor>() + }; +} + + +style::SymbolPropertyValues RenderSymbolLayer::iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const { + return style::SymbolPropertyValues { + layout_.get<style::IconRotationAlignment>(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment + layout_.get<style::IconRotationAlignment>(), + evaluated.get<style::IconTranslate>(), + evaluated.get<style::IconTranslateAnchor>(), + evaluated.get<style::IconHaloColor>().constantOr(Color::black()).a > 0 && + evaluated.get<style::IconHaloWidth>().constantOr(1), + evaluated.get<style::IconColor>().constantOr(Color::black()).a > 0 + }; +} + +style::SymbolPropertyValues RenderSymbolLayer::textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const { + return style::SymbolPropertyValues { + layout_.get<style::TextPitchAlignment>(), + layout_.get<style::TextRotationAlignment>(), + evaluated.get<style::TextTranslate>(), + evaluated.get<style::TextTranslateAnchor>(), + evaluated.get<style::TextHaloColor>().constantOr(Color::black()).a > 0 && + evaluated.get<style::TextHaloWidth>().constantOr(1), + evaluated.get<style::TextColor>().constantOr(Color::black()).a > 0 + }; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp new file mode 100644 index 0000000000..2199103de2 --- /dev/null +++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp @@ -0,0 +1,95 @@ +#pragma once + +#include <mbgl/text/glyph.hpp> +#include <mbgl/renderer/render_layer.hpp> +#include <mbgl/style/image_impl.hpp> +#include <mbgl/style/layers/symbol_layer_impl.hpp> +#include <mbgl/style/layers/symbol_layer_properties.hpp> + +namespace mbgl { + +namespace style { + +// {icon,text}-specific paint-property packs for use in the symbol Programs. +// Since each program deals either with icons or text, using a smaller property set +// lets us avoid unnecessarily binding attributes for properties the program wouldn't use. +class IconPaintProperties : public Properties< + IconOpacity, + IconColor, + IconHaloColor, + IconHaloWidth, + IconHaloBlur, + IconTranslate, + IconTranslateAnchor +> {}; + +class TextPaintProperties : public Properties< + TextOpacity, + TextColor, + TextHaloColor, + TextHaloWidth, + TextHaloBlur, + TextTranslate, + TextTranslateAnchor +> {}; + +// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties +// for genericity over icons vs. text. +class SymbolPropertyValues { +public: + // Layout + AlignmentType pitchAlignment; + AlignmentType rotationAlignment; + + // Paint + std::array<float, 2> translate; + TranslateAnchorType translateAnchor; + + bool hasHalo; + bool hasFill; +}; + +} // namespace style + +class BucketParameters; +class SymbolLayout; +class GeometryTileLayer; + +class RenderSymbolLayer: public RenderLayer { +public: + RenderSymbolLayer(Immutable<style::SymbolLayer::Impl>); + ~RenderSymbolLayer() final = default; + + void transition(const TransitionParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + style::IconPaintProperties::PossiblyEvaluated iconPaintProperties() const; + style::TextPaintProperties::PossiblyEvaluated textPaintProperties() const; + + style::SymbolPropertyValues iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const; + style::SymbolPropertyValues textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const; + + std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override; + std::unique_ptr<SymbolLayout> createLayout(const BucketParameters&, + const std::vector<const RenderLayer*>&, + std::unique_ptr<GeometryTileLayer>, + GlyphDependencies&, + ImageDependencies&) const; + + // Paint properties + style::SymbolPaintProperties::Unevaluated unevaluated; + style::SymbolPaintProperties::PossiblyEvaluated evaluated; + + float iconSize = 1.0f; + float textSize = 16.0f; + + const style::SymbolLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is<RenderSymbolLayer>() const { + return type == style::LayerType::Symbol; +} + +} // namespace mbgl |