Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
4039694
Very prelim
Jul 7, 2025
705fc66
Merge branch 'main' into feature/2025-07-raw-bucket
Jul 7, 2025
3aa92db
Initial commit
Jul 25, 2025
4e2f4e6
Updates
Jul 25, 2025
20b7985
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
dd26f7c
Merge branch 'main' into feature/2025-07-raw-bucket
Jul 25, 2025
de3897a
Reverting some logging
Jul 25, 2025
f8d5a5b
Merge branch 'feature/2025-07-raw-bucket' of github.com:AtlasProgramm…
Jul 25, 2025
7f3ab5f
Removed unused include
Jul 25, 2025
c8cc544
Removed unused header
Jul 25, 2025
3458614
Initial commit of style filters
Jul 25, 2025
f4d1ef4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
58f352e
Little bit of cleanup
Jul 25, 2025
6594a7e
Merge branch 'feature/2025-07-style-filters' of github.com:AtlasProgr…
Jul 25, 2025
c817bff
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
4a54021
Added feature collections to cmake
Jul 25, 2025
987a384
Removing array type for now
Jul 25, 2025
37f8e67
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
8654fc2
Cleanp
Jul 26, 2025
535927b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2025
faeb360
Changed to filter the loadJSON path as well
Jul 26, 2025
9337cf1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2025
b10ecb0
Minor cleanup
Jul 26, 2025
8c8381b
Merge branch 'feature/2025-07-style-filters' of github.com:AtlasProgr…
Jul 26, 2025
432f16f
Cleanup cruft
Jul 26, 2025
4413910
Added style filter to cmake list
Jul 26, 2025
2c0c768
Added header to fix build error
Jul 26, 2025
b6a59e3
Initial commit of adding support for custom protocols
Jul 26, 2025
73ca452
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 26, 2025
9f9f84c
Cleanup
Jul 27, 2025
b7f85bb
Adding more properties to the platform request
Jul 27, 2025
1ab94b5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 27, 2025
bd0ced9
Cmake update
Jul 27, 2025
85edacf
Merge branch 'main' into feature/2025-07-style-filters
Jul 27, 2025
fb99190
Fix for swift app compile
Jul 27, 2025
e126973
Updates for cmake
Jul 27, 2025
1fa1a0e
Added header back in the right place this time
Jul 27, 2025
10c8c0d
Fix compiler error
Jul 28, 2025
87b27bc
More compiler errors
Jul 28, 2025
d6a7000
Re-ordered headers
Jul 28, 2025
eae8078
Starting to add android implementation
Jul 29, 2025
7d27873
Passing along the byte buffer from the plugin to the native response
Jul 29, 2025
73d9278
Update src/mbgl/plugin/feature_collection.hpp
AtlasProgramming Jul 29, 2025
386b898
Update src/mbgl/plugin/plugin_layer_render.cpp
AtlasProgramming Jul 29, 2025
34d9abf
Updafed with feedback
Jul 29, 2025
b9b1240
Merge branch 'feature/2025-07-raw-bucket' of github.com:AtlasProgramm…
Jul 29, 2025
54f4ba1
Merge pull request #6 from AtlasProgramming/feature/2025-07-custom-pr…
AtlasProgramming Jul 29, 2025
9c3ef30
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 29, 2025
f408282
Updates
Jul 29, 2025
3406120
Added example plugin
Jul 30, 2025
4a8010c
Updated the file source name
Aug 1, 2025
3f0f75e
Merge pull request #3 from AtlasProgramming/feature/2025-07-raw-bucket
AtlasProgramming Aug 1, 2025
f70b365
Merge branch 'maplibre-plus' into feature/2025-07-style-filters
Aug 1, 2025
417260a
Merge pull request #4 from AtlasProgramming/feature/2025-07-style-fil…
AtlasProgramming Aug 1, 2025
a7cf398
Merge branch 'maplibre-plus' into feature/2025-07-custom-protocol
Aug 1, 2025
0f1945b
Merge pull request #5 from AtlasProgramming/feature/2025-07-custom-pr…
AtlasProgramming Aug 1, 2025
b48fabb
Merge branch 'main' into maplibre-plus
Aug 1, 2025
0199769
Clean up from merge
Aug 1, 2025
a75ca03
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 1, 2025
9688d7d
Added a couple of delegate methods to the network delegate
Aug 6, 2025
c6b64c2
Merge branch 'maplibre-plugins' of github.com:AtlasProgramming/maplib…
Aug 6, 2025
f6684f5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 6, 2025
5803016
Merge branch 'main' into maplibre-plugins
Aug 6, 2025
61dfbb3
Removed single feature loaded function
Aug 10, 2025
7f96a34
Merge branch 'maplibre/main' into maplibre/feature/2025-08-plugins
Aug 10, 2025
34031b3
Updates
Sep 14, 2025
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
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -979,11 +979,18 @@ list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_properties.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_factory.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_style_filter.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_render.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_properties.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_layer_factory.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_file_source.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/plugin_style_filter.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection_bucket.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/plugin/feature_collection_bucket.cpp
)


Expand Down
7 changes: 7 additions & 0 deletions bazel/core.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ MLN_LAYER_PLUGIN_HEADERS = [
"src/mbgl/plugin/plugin_layer_impl.hpp",
"src/mbgl/plugin/plugin_layer_render.hpp",
"src/mbgl/plugin/plugin_layer_properties.hpp",
"src/mbgl/plugin/plugin_file_source.hpp",
"src/mbgl/plugin/plugin_style_filter.hpp",
"src/mbgl/plugin/feature_collection_bucket.hpp",
"src/mbgl/plugin/feature_collection.hpp",
]

MLN_LAYER_PLUGIN_SOURCE = [
Expand All @@ -12,6 +16,9 @@ MLN_LAYER_PLUGIN_SOURCE = [
"src/mbgl/plugin/plugin_layer_impl.cpp",
"src/mbgl/plugin/plugin_layer_render.cpp",
"src/mbgl/plugin/plugin_layer_properties.cpp",
"src/mbgl/plugin/plugin_style_filter.cpp",
"src/mbgl/plugin/feature_collection_bucket.cpp",
"src/mbgl/plugin/feature_collection.cpp",
]

MLN_PUBLIC_GENERATED_STYLE_HEADERS = [
Expand Down
3 changes: 2 additions & 1 deletion include/mbgl/storage/file_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ enum FileSourceType : uint8_t {
Network,
Mbtiles,
Pmtiles,
ResourceLoader ///< %Resource loader acts as a proxy and has logic
ResourceLoader, ///< %Resource loader acts as a proxy and has logic
/// for request delegation to Asset, Cache, and other
/// file sources.
Custom // These are the plugin file resource types
};

// TODO: Rename to ResourceProvider to avoid confusion with
Expand Down
6 changes: 6 additions & 0 deletions include/mbgl/storage/file_source_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ class FileSourceManager {
// a FileSourceType invocation has no effect.
virtual FileSourceFactory unRegisterFileSourceFactory(FileSourceType) noexcept;

// Registers a custom file source
virtual void registerCustomFileSource(std::shared_ptr<FileSource>) noexcept;

// Returns an array of custom file sources
virtual std::vector<std::shared_ptr<FileSource>> getCustomFileSources() noexcept;

protected:
FileSourceManager();
class Impl;
Expand Down
4 changes: 4 additions & 0 deletions include/mbgl/style/style.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace style {
class Light;
class Source;
class Layer;
class PluginStyleFilter;

class Style {
public:
Expand Down Expand Up @@ -71,6 +72,9 @@ class Style {
void addLayer(std::unique_ptr<Layer>, const std::optional<std::string>& beforeLayerID = std::nullopt);
std::unique_ptr<Layer> removeLayer(const std::string& layerID);

// Add style parsing filter
void addStyleFilter(std::shared_ptr<mbgl::style::PluginStyleFilter>);

// Private implementation
class Impl;
const std::unique_ptr<Impl> impl;
Expand Down
4 changes: 4 additions & 0 deletions platform/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ objc_library(
srcs = [
"//platform/darwin:app/PluginLayerExample.h",
"//platform/darwin:app/PluginLayerExample.mm",
"//platform/darwin:app/PluginProtocolExample.h",
"//platform/darwin:app/PluginProtocolExample.mm",
"//platform/darwin:app/StyleFilterExample.h",
"//platform/darwin:app/StyleFilterExample.mm",
"//platform/darwin:app/PluginLayerExampleMetalRendering.h",
"//platform/darwin:app/PluginLayerExampleMetalRendering.mm",
"//platform/darwin:app/CustomStyleLayerExample.h",
Expand Down
6 changes: 6 additions & 0 deletions platform/android/MapLibreAndroid/src/cpp/jni_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "native_map_options.hpp"
#include "rendering_stats.hpp"
#include "util/tile_server_options.hpp"
#include "plugin/plugin_file_source.hpp"
#ifndef MBGL_MODULE_OFFLINE_DISABLE
#include "offline/offline_manager.hpp"
#include "offline/offline_region.hpp"
Expand Down Expand Up @@ -107,6 +108,11 @@ void registerNatives(JavaVM* vm) {
Polygon::registerNative(env);
Polyline::registerNative(env);

// Plugins
PluginProtocolHandlerResource::registerNative(env);
PluginProtocolHandlerResponse::registerNative(env);
PluginFileSource::registerNative(env);

// Map
MapRenderer::registerNative(env);
MapRendererRunnable::registerNative(env);
Expand Down
92 changes: 91 additions & 1 deletion platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <mbgl/style/image.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/renderer/query.hpp>
#include <mbgl/plugin/plugin_file_source.hpp>
#include <mbgl/storage/file_source_manager.hpp>

// Java -> C++ conversion
#include "style/android_conversion.hpp"
Expand Down Expand Up @@ -1320,6 +1322,93 @@ void NativeMapView::enableRenderingStatsView(JNIEnv&, jni::jboolean value) {
map->enableRenderingStatsView(value);
}

// Plugins
void NativeMapView::addPluginFileSource(JNIEnv& jniEnv, const jni::Object<PluginFileSource>& pluginFileSource) {
// TODO: Unclear if any of these options are needed for plugins
mbgl::ResourceOptions resourceOptions;

// TODO: Unclear if any of the properties on clientOptions need to be set
mbgl::ClientOptions clientOptions;

android::UniqueEnv _env = android::AttachEnv();

// Set when the source is added to a map.
jni::Global<jni::Object<PluginFileSource>> pluginPeer = jni::NewGlobal(*_env, pluginFileSource);
std::shared_ptr<PluginFileSourceContainer> fileSourceContainer = std::make_shared<PluginFileSourceContainer>();
fileSourceContainer->_fileSource = std::move(pluginPeer);
_pluginFileSources.push_back(fileSourceContainer);

std::shared_ptr<mbgl::PluginFileSource> pluginSource = std::make_shared<mbgl::PluginFileSource>(resourceOptions,
clientOptions);
pluginSource->setOnRequestResourceFunction([fileSourceContainer](const mbgl::Resource& resource) -> mbgl::Response {
mbgl::Response tempResponse;

android::UniqueEnv env = android::AttachEnv();
static auto& javaClass = jni::Class<PluginFileSource>::Singleton(*env);
static auto requestResource =
javaClass.GetMethod<jni::Object<PluginProtocolHandlerResponse>(jni::Object<PluginProtocolHandlerResource>)>(
*env, "requestResource");
auto javaResource = PluginFileSource::createJavaResource(*env, resource);
auto tempResult = fileSourceContainer->_fileSource.Call(*env, requestResource, javaResource);
PluginProtocolHandlerResponse::Update(*env, tempResult, tempResponse);

return tempResponse;
});
pluginSource->setOnCanRequestFunction([fileSourceContainer](const mbgl::Resource& resource) -> bool {
android::UniqueEnv env = android::AttachEnv();
static auto& javaClass = jni::Class<PluginFileSource>::Singleton(*env);
static auto canRequestResource = javaClass.GetMethod<jboolean(jni::Object<PluginProtocolHandlerResource>)>(
*env, "canRequestResource");
auto javaResource = PluginFileSource::createJavaResource(*env, resource);
auto tempResult = fileSourceContainer->_fileSource.Call(*env, canRequestResource, javaResource);
return tempResult;

/*
if (!renderingStats) {
renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env));
}

RenderingStats::Update(*_env, renderingStats, status.renderingStats);

weakReference.Call(*_env,
onDidFinishRenderingFrame,
(jboolean)(status.mode != MapObserver::RenderMode::Partial),
renderingStats);
*/
/*
static auto resourceURLField = javaClass.GetField<jni::Object<PluginProtocolHandlerResource>>(env,
"resource"); auto str = jni::Make<jni::String>(env, resource.url); // wrap the jstring javaObject.Set(env,
resourceURLField, str);

fileSourceContainer->_fileSource.Set(env, )
*/
});
auto fileSourceManager = mbgl::FileSourceManager::get();
fileSourceManager->registerCustomFileSource(pluginSource);

/*
android::UniqueEnv _env = android::AttachEnv();
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
static auto onDidFinishRenderingFrame = javaClass.GetMethod<void(jboolean,
jni::Object<RenderingStats>)>(
*_env, "onDidFinishRenderingFrame");
auto weakReference = javaPeer.get(*_env);
if (weakReference) {
if (!renderingStats) {
renderingStats = jni::NewGlobal(*_env, RenderingStats::Create(*_env));
}

RenderingStats::Update(*_env, renderingStats, status.renderingStats);

weakReference.Call(*_env,
onDidFinishRenderingFrame,
(jboolean)(status.mode != MapObserver::RenderMode::Partial),
renderingStats);
}

*/
}

// Static methods //

void NativeMapView::registerNative(jni::JNIEnv& env) {
Expand Down Expand Up @@ -1442,7 +1531,8 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::getTileLodZoomShift, "nativeGetTileLodZoomShift"),
METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"),
METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"),
METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"));
METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"),
METHOD(&NativeMapView::addPluginFileSource, "nativeAddPluginFileSource"));
}

void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {};
Expand Down
8 changes: 7 additions & 1 deletion platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "style/light.hpp"
#include "native_map_options.hpp"
#include "bitmap.hpp"

#include "plugin/plugin_file_source.hpp"
#include <exception>
#include <string>
#include <jni.h>
Expand Down Expand Up @@ -325,6 +325,9 @@ class NativeMapView : public MapObserver {
jni::jboolean isRenderingStatsViewEnabled(JNIEnv&);
void enableRenderingStatsView(JNIEnv&, jni::jboolean);

// Plugins
void addPluginFileSource(JNIEnv&, const jni::Object<mbgl::android::PluginFileSource>&);

// Shader compilation
void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override;
void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override;
Expand Down Expand Up @@ -364,6 +367,9 @@ class NativeMapView : public MapObserver {

// Ensure these are initialised last
std::unique_ptr<mbgl::Map> map;

// List of plugin file source
std::vector<std::shared_ptr<mbgl::android::PluginFileSourceContainer>> _pluginFileSources;
};

} // namespace android
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

#include "plugin_file_source.hpp"

using namespace mbgl::android;

// Putting these here (should probably move out to a more dedicated JNI place within
// the native repo at some point, but this means we don't have to update
// the jni.hpp dependency
namespace jni {

struct ByteBufferTag {
static constexpr auto Name() { return "java/nio/ByteBuffer"; }
};

template <>
struct TagTraits<ByteBufferTag> {
using SuperType = Object<ObjectTag>;
using UntaggedType = jobject;
};

} // namespace jni

void PluginFileSource::registerNative(jni::JNIEnv& env) {
jni::Class<PluginFileSource>::Singleton(env);
}

jni::Global<jni::Object<PluginProtocolHandlerResource>> PluginFileSource::createJavaResource(
jni::JNIEnv& env, const mbgl::Resource& resource) {
jni::Global<jni::Object<PluginProtocolHandlerResource>> tempResult = jni::NewGlobal(
env, PluginProtocolHandlerResource::Create(env));
PluginProtocolHandlerResource::Update(env, tempResult, resource);
return tempResult;
}

void PluginProtocolHandlerResource::registerNative(jni::JNIEnv& env) {
jni::Class<PluginProtocolHandlerResource>::Singleton(env);
}

jni::Local<jni::Object<PluginProtocolHandlerResource>> PluginProtocolHandlerResource::Create(jni::JNIEnv& env) {
auto& javaClass = jni::Class<PluginProtocolHandlerResource>::Singleton(env);
auto constructor = javaClass.GetConstructor(env);
return javaClass.New(env, constructor);
}

void PluginProtocolHandlerResource::Update(jni::JNIEnv& env,
jni::Object<PluginProtocolHandlerResource>& javaObject,
const mbgl::Resource& resource) {
static auto& javaClass = jni::Class<PluginProtocolHandlerResource>::Singleton(env);

static auto resourceKindField = javaClass.GetField<jni::jint>(env, "kind");
javaObject.Set(env, resourceKindField, static_cast<jni::jint>(resource.kind));

static auto resourceURLField = javaClass.GetField<jni::String>(env, "resourceURL");
auto str = jni::Make<jni::String>(env, resource.url); // wrap the jstring
javaObject.Set(env, resourceURLField, str);
}

void PluginProtocolHandlerResponse::registerNative(jni::JNIEnv& env) {
jni::Class<PluginProtocolHandlerResponse>::Singleton(env);
}

jni::Local<jni::Object<PluginProtocolHandlerResponse>> PluginProtocolHandlerResponse::Create(jni::JNIEnv& env) {
auto& javaClass = jni::Class<PluginProtocolHandlerResponse>::Singleton(env);
auto constructor = javaClass.GetConstructor(env);
return javaClass.New(env, constructor);
}

void PluginProtocolHandlerResponse::Update(jni::JNIEnv& env,
[[maybe_unused]] jni::Object<PluginProtocolHandlerResponse>& javaObject,
[[maybe_unused]] mbgl::Response& response) {
static auto& javaClass = jni::Class<PluginProtocolHandlerResponse>::Singleton(env);
static auto dataField = javaClass.GetField<jni::Object<jni::ByteBufferTag>>(env, "data");
auto objectValue = javaObject.Get(env, dataField);
auto objectRef = jobject(objectValue.get());
void* bufPtr = env.GetDirectBufferAddress(objectRef);
jsize length = env.GetDirectBufferCapacity(objectRef);
response.data = std::make_shared<std::string>((const char*)bufPtr, length);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include <jni/jni.hpp>
#include <mbgl/plugin/plugin_file_source.hpp>

namespace mbgl {
namespace android {

class PluginProtocolHandlerResource {
public:
static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResource"; };
static void registerNative(jni::JNIEnv &);

static jni::Local<jni::Object<PluginProtocolHandlerResource>> Create(jni::JNIEnv &);
static void Update(jni::JNIEnv &, jni::Object<PluginProtocolHandlerResource> &, const mbgl::Resource &);
};

class PluginProtocolHandlerResponse {
public:
static constexpr auto Name() { return "org/maplibre/android/plugin/PluginProtocolHandlerResponse"; };
static void registerNative(jni::JNIEnv &);

static jni::Local<jni::Object<PluginProtocolHandlerResponse>> Create(jni::JNIEnv &);
static void Update(jni::JNIEnv &, jni::Object<PluginProtocolHandlerResponse> &, mbgl::Response &);
};

class PluginFileSource {
public:
static constexpr auto Name() { return "org/maplibre/android/plugin/PluginFileSource"; };

// static mbgl::PluginFileSource getFileSource(jni::JNIEnv&, const jni::Object<PluginFileSource>&);

static jni::Global<jni::Object<PluginProtocolHandlerResource>> createJavaResource(jni::JNIEnv &env,
const mbgl::Resource &resource);

static void registerNative(jni::JNIEnv &);
};

class PluginFileSourceContainer {
public:
jni::Global<jni::Object<PluginFileSource>> _fileSource;
};

} // namespace android
} // namespace mbgl
Loading