Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Layer type evaluators #9064

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions include/mbgl/style/layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,21 @@ class Layer : public mbgl::util::noncopyable {
auto accept(V&& visitor) {
switch (getType()) {
case LayerType::Fill:
return visitor(*as<FillLayer>());
return std::forward<V>(visitor)(*as<FillLayer>());
case LayerType::Line:
return visitor(*as<LineLayer>());
return std::forward<V>(visitor)(*as<LineLayer>());
case LayerType::Circle:
return visitor(*as<CircleLayer>());
return std::forward<V>(visitor)(*as<CircleLayer>());
case LayerType::Symbol:
return visitor(*as<SymbolLayer>());
return std::forward<V>(visitor)(*as<SymbolLayer>());
case LayerType::Raster:
return visitor(*as<RasterLayer>());
return std::forward<V>(visitor)(*as<RasterLayer>());
case LayerType::Background:
return visitor(*as<BackgroundLayer>());
return std::forward<V>(visitor)(*as<BackgroundLayer>());
case LayerType::Custom:
return visitor(*as<CustomLayer>());
return std::forward<V>(visitor)(*as<CustomLayer>());
case LayerType::FillExtrusion:
return visitor(*as<FillExtrusionLayer>());
return std::forward<V>(visitor)(*as<FillExtrusionLayer>());
}
}

Expand Down
4 changes: 4 additions & 0 deletions platform/android/src/style/layers/custom_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ namespace android {
: Layer(map, coreLayer) {
}

CustomLayer::CustomLayer(mbgl::Map& map, std::unique_ptr<mbgl::style::CustomLayer> coreLayer)
: Layer(map, std::move(coreLayer)) {
}

CustomLayer::~CustomLayer() = default;

void CustomLayer::update(jni::JNIEnv&) {
Expand Down
2 changes: 2 additions & 0 deletions platform/android/src/style/layers/custom_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class CustomLayer : public Layer {

CustomLayer(mbgl::Map&, mbgl::style::CustomLayer&);

CustomLayer(mbgl::Map&, std::unique_ptr<mbgl::style::CustomLayer>);

~CustomLayer();

void update(jni::JNIEnv&);
Expand Down
91 changes: 43 additions & 48 deletions platform/android/src/style/layers/layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,75 +98,70 @@ namespace android {
}
}

struct SetFilterEvaluator {
style::Filter filter;

void operator()(style::BackgroundLayer&) { Log::Warning(mbgl::Event::JNI, "BackgroundLayer doesn't support filters"); }
void operator()(style::CustomLayer&) { Log::Warning(mbgl::Event::JNI, "CustomLayer doesn't support filters"); }
void operator()(style::RasterLayer&) { Log::Warning(mbgl::Event::JNI, "RasterLayer doesn't support filters"); }

template <class LayerType>
void operator()(LayerType& layer) {
layer.setFilter(filter);
}
};

void Layer::setFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) {
using namespace mbgl::style;
using namespace mbgl::style::conversion;

Value wrapped(env, jfilter);
Filter filter;

Error error;
optional<Filter> converted = convert<Filter>(wrapped, error);
if (!converted) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + error.message);
return;
}
filter = std::move(*converted);

if (layer.is<FillLayer>()) {
layer.as<FillLayer>()->setFilter(filter);
} else if (layer.is<LineLayer>()) {
layer.as<LineLayer>()->setFilter(filter);
} else if (layer.is<SymbolLayer>()) {
layer.as<SymbolLayer>()->setFilter(filter);
} else if (layer.is<CircleLayer>()) {
layer.as<CircleLayer>()->setFilter(filter);
} else if (layer.is<FillExtrusionLayer>()){
layer.as<FillExtrusionLayer>()->setFilter(filter);
} else {
mbgl::Log::Warning(mbgl::Event::JNI, "Layer doesn't support filters");
}

layer.accept(SetFilterEvaluator {std::move(*converted)});
}

void Layer::setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer) {
using namespace mbgl::style;
struct SetSourceLayerEvaluator {
std::string sourceLayer;

std::string layerId = jni::Make<std::string>(env, sourceLayer);

if (layer.is<FillLayer>()) {
layer.as<FillLayer>()->setSourceLayer(layerId);
} else if (layer.is<LineLayer>()) {
layer.as<LineLayer>()->setSourceLayer(layerId);
} else if (layer.is<SymbolLayer>()) {
layer.as<SymbolLayer>()->setSourceLayer(layerId);
} else if (layer.is<CircleLayer>()) {
layer.as<CircleLayer>()->setSourceLayer(layerId);
} else if(layer.is<FillExtrusionLayer>()) {
layer.as<FillExtrusionLayer>()->setSourceLayer(layerId);
} else {
mbgl::Log::Warning(mbgl::Event::JNI, "Layer doesn't support source layer");
void operator()(style::BackgroundLayer&) { Log::Warning(mbgl::Event::JNI, "BackgroundLayer doesn't support source layer"); }
void operator()(style::CustomLayer&) { Log::Warning(mbgl::Event::JNI, "CustomLayer doesn't support source layer"); }
void operator()(style::RasterLayer&) { Log::Warning(mbgl::Event::JNI, "RasterLayer doesn't support source layer"); }

template <class LayerType>
void operator()(LayerType& layer) {
layer.setSourceLayer(sourceLayer);
}
};

void Layer::setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer) {
layer.accept(SetSourceLayerEvaluator {jni::Make<std::string>(env, sourceLayer)});
}

jni::String Layer::getSourceLayer(jni::JNIEnv& env) {
using namespace mbgl::style;
struct GetSourceLayerEvaluator {
std::string noop(std::string layerType) {
Log::Warning(mbgl::Event::JNI, "%s doesn't support source layer", layerType.c_str());
return {};
}

std::string sourceLayerId;
if (layer.is<FillLayer>()) {
sourceLayerId = layer.as<FillLayer>()->getSourceLayer();
} else if (layer.is<LineLayer>()) {
sourceLayerId = layer.as<LineLayer>()->getSourceLayer();
} else if (layer.is<SymbolLayer>()) {
sourceLayerId = layer.as<SymbolLayer>()->getSourceLayer();
} else if (layer.is<CircleLayer>()) {
sourceLayerId = layer.as<CircleLayer>()->getSourceLayer();
} else if (layer.is<FillExtrusionLayer>()) {
sourceLayerId = layer.as<FillExtrusionLayer>()->getSourceLayer();
} else {
mbgl::Log::Warning(mbgl::Event::JNI, "Layer doesn't support source layer");
std::string operator()(style::BackgroundLayer&) { return noop("BackgroundLayer"); }
std::string operator()(style::CustomLayer&) { return noop("CustomLayer"); }
std::string operator()(style::RasterLayer&) { return noop("RasterLayer"); }

template <class LayerType>
std::string operator()(LayerType& layer) {
return layer.getSourceLayer();
}
};

return jni::Make<jni::String>(env, sourceLayerId);
jni::String Layer::getSourceLayer(jni::JNIEnv& env) {
return jni::Make<jni::String>(env, layer.accept(GetSourceLayerEvaluator()));
}

jni::jfloat Layer::getMinZoom(jni::JNIEnv&){
Expand Down
77 changes: 35 additions & 42 deletions platform/android/src/style/layers/layers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,52 +25,45 @@ namespace mbgl {
namespace android {

static Layer* initializeLayerPeer(mbgl::Map& map, mbgl::style::Layer& coreLayer) {
if (coreLayer.is<mbgl::style::BackgroundLayer>()) {
return new BackgroundLayer(map, *coreLayer.as<mbgl::style::BackgroundLayer>());
} else if (coreLayer.is<mbgl::style::CircleLayer>()) {
return new CircleLayer(map, *coreLayer.as<mbgl::style::CircleLayer>());
} else if (coreLayer.is<mbgl::style::FillExtrusionLayer>()) {
return new FillExtrusionLayer(map, *coreLayer.as<mbgl::style::FillExtrusionLayer>());
} else if (coreLayer.is<mbgl::style::FillLayer>()) {
return new FillLayer(map, *coreLayer.as<mbgl::style::FillLayer>());
} else if (coreLayer.is<mbgl::style::LineLayer>()) {
return new LineLayer(map, *coreLayer.as<mbgl::style::LineLayer>());
} else if (coreLayer.is<mbgl::style::RasterLayer>()) {
return new RasterLayer(map, *coreLayer.as<mbgl::style::RasterLayer>());
} else if (coreLayer.is<mbgl::style::SymbolLayer>()) {
return new SymbolLayer(map, *coreLayer.as<mbgl::style::SymbolLayer>());
} else if (coreLayer.is<mbgl::style::CustomLayer>()) {
return new CustomLayer(map, *coreLayer.as<mbgl::style::CustomLayer>());
} else {
return new UnknownLayer(map, coreLayer);
}
}
struct LayerPeerIntitializer {
mbgl::Map& map;

template <class LayerType, class PeerType>
static PeerType* createPeer(Map& map, std::unique_ptr<mbgl::style::Layer> layer) {
return new PeerType(map, std::move(std::unique_ptr<LayerType>(layer.release()->as<LayerType>())));
Layer* operator()(style::BackgroundLayer& layer) { return new BackgroundLayer(map, layer); }
Layer* operator()(style::CircleLayer& layer) { return new CircleLayer(map, layer); }
Layer* operator()(style::FillExtrusionLayer& layer) { return new FillExtrusionLayer(map, layer); }
Layer* operator()(style::FillLayer& layer) { return new FillLayer(map, layer); }
Layer* operator()(style::LineLayer& layer) { return new LineLayer(map, layer); }
Layer* operator()(style::RasterLayer& layer) { return new RasterLayer(map, layer); }
Layer* operator()(style::SymbolLayer& layer) { return new SymbolLayer(map, layer); }
Layer* operator()(style::CustomLayer& layer) { return new CustomLayer(map, layer); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be a template function?

};

Layer* layer = coreLayer.accept(LayerPeerIntitializer {map});
return layer ? layer : new UnknownLayer(map, coreLayer);
}

static Layer* initializeLayerPeer(Map& map, std::unique_ptr<mbgl::style::Layer> coreLayer) {
if (coreLayer->is<style::BackgroundLayer>()) {
return createPeer<style::BackgroundLayer, BackgroundLayer>(map, std::move(coreLayer));
} else if (coreLayer->is<style::CircleLayer>()) {
return createPeer<style::CircleLayer, CircleLayer>(map, std::move(coreLayer));
} else if (coreLayer->is<style::FillExtrusionLayer>()) {
return createPeer<style::FillExtrusionLayer, FillExtrusionLayer>(map, std::move(coreLayer));
} else if (coreLayer->is<style::FillLayer>()) {
return createPeer<style::FillLayer, FillLayer>(map, std::move(coreLayer));
} else if (coreLayer->is<style::LineLayer>()) {
return createPeer<style::LineLayer, LineLayer>(map, std::move(coreLayer));
} else if (coreLayer->is<style::RasterLayer>()) {
return createPeer<style::RasterLayer, RasterLayer>(map, std::move(coreLayer));
} else if (coreLayer->is<style::SymbolLayer>()) {
return createPeer<style::SymbolLayer, SymbolLayer>(map, std::move(coreLayer));
} else if (coreLayer->is<mbgl::style::CustomLayer>()) {
return createPeer<style::SymbolLayer, SymbolLayer>(map, std::move(coreLayer));
} else {
return new UnknownLayer(map, std::move(coreLayer));
struct UniqueLayerPeerIntitializer {
mbgl::Map& map;
std::unique_ptr<style::Layer> layer;

template <class LayerType>
std::unique_ptr<LayerType> cast() {
return std::unique_ptr<LayerType>(layer.release()->as<LayerType>());
}

Layer* operator()(style::BackgroundLayer&) && { return new BackgroundLayer(map, cast<style::BackgroundLayer>()); }
Layer* operator()(style::CircleLayer&) && { return new CircleLayer(map, cast<style::CircleLayer>()); }
Layer* operator()(style::FillExtrusionLayer&) && { return new FillExtrusionLayer(map, cast<style::FillExtrusionLayer>()); }
Layer* operator()(style::FillLayer&) && { return new FillLayer(map, cast<style::FillLayer>()); }
Layer* operator()(style::LineLayer&) && { return new LineLayer(map, cast<style::LineLayer>()); }
Layer* operator()(style::RasterLayer&) && { return new RasterLayer(map, cast<style::RasterLayer>()); }
Layer* operator()(style::SymbolLayer&) && { return new SymbolLayer(map, cast<style::SymbolLayer>()); }
Layer* operator()(style::CustomLayer&) && { return new CustomLayer(map, cast<style::CustomLayer>()); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a template function?

Copy link
Contributor Author

@ivovandongen ivovandongen May 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kkaefer I was hoping the same, but don't quite know how. The classes involved are not the same type, but named the same, eg mbgl::style::LineLayer and mbgl::android::LineLayer. Where the latter is a Peer class wrapping the former.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be done by adding a typedef member to the mbgl::android::LineLayer with a shared name (e.g. using LayerType = style::LineLayer in mbgl::android::LineLayer, then using a function like

template <class PeerType>
Layer* operator(typename PeerType::LayerType&) && {
    return new PeerType(map, cast<typename PeerType::LayerType>());
}

};

static Layer* initializeLayerPeer(Map& map, std::unique_ptr<mbgl::style::Layer> coreLayer) {
Layer* layer = coreLayer->accept(UniqueLayerPeerIntitializer {map, std::move(coreLayer)});
return layer ? layer : new UnknownLayer(map, std::move(coreLayer));
}

jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, Map& map, style::Layer& coreLayer) {
Expand Down