[build] remove local c++ src folder, using upstream for now (#27)

This commit is contained in:
Tobrun
2019-10-25 12:06:26 +02:00
committed by GitHub
parent 77e7e0e38b
commit 8a6dba47ed
201 changed files with 0 additions and 15502 deletions

View File

@@ -1,67 +0,0 @@
#include "android_renderer_backend.hpp"
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <EGL/egl.h>
#include <cassert>
namespace mbgl {
namespace android {
class AndroidGLRenderableResource final : public mbgl::gl::RenderableResource {
public:
AndroidGLRenderableResource(AndroidRendererBackend& backend_) : backend(backend_) {
}
void bind() override {
assert(gfx::BackendScope::exists());
backend.setFramebufferBinding(0);
backend.setViewport(0, 0, backend.getSize());
}
private:
AndroidRendererBackend& backend;
};
AndroidRendererBackend::AndroidRendererBackend()
: gl::RendererBackend(gfx::ContextMode::Unique),
mbgl::gfx::Renderable({ 64, 64 }, std::make_unique<AndroidGLRenderableResource>(*this)) {
}
AndroidRendererBackend::~AndroidRendererBackend() = default;
gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) {
assert(gfx::BackendScope::exists());
return eglGetProcAddress(name);
}
void AndroidRendererBackend::updateViewPort() {
assert(gfx::BackendScope::exists());
setViewport(0, 0, size);
}
void AndroidRendererBackend::resizeFramebuffer(int width, int height) {
size = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
}
PremultipliedImage AndroidRendererBackend::readFramebuffer() {
assert(gfx::BackendScope::exists());
return gl::RendererBackend::readFramebuffer(size);
}
void AndroidRendererBackend::updateAssumedState() {
assumeFramebufferBinding(0);
assumeViewport(0, 0, size);
}
void AndroidRendererBackend::markContextLost() {
if (context) {
getContext<gl::Context>().setCleanupOnDestruction(false);
}
}
} // namespace android
} // namspace mbgl

View File

@@ -1,43 +0,0 @@
#pragma once
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gl/renderer_backend.hpp>
namespace mbgl {
namespace android {
class AndroidRendererBackend : public gl::RendererBackend, public mbgl::gfx::Renderable {
public:
AndroidRendererBackend();
~AndroidRendererBackend() override;
void updateViewPort();
// Ensures the current context is not cleaned up when destroyed
void markContextLost();
void resizeFramebuffer(int width, int height);
PremultipliedImage readFramebuffer();
// mbgl::gfx::RendererBackend implementation
public:
mbgl::gfx::Renderable& getDefaultRenderable() override {
return *this;
}
protected:
void activate() override {
// no-op
}
void deactivate() override {
// no-op
}
// mbgl::gl::RendererBackend implementation
protected:
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void updateAssumedState() override;
};
} // namespace android
} // namespace mbgl

View File

@@ -1,143 +0,0 @@
#include "android_renderer_frontend.hpp"
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/geojson.hpp>
#include "android_renderer_backend.hpp"
namespace mbgl {
namespace android {
// Forwards RendererObserver signals to the given
// Delegate RendererObserver on the given RunLoop
class ForwardingRendererObserver : public RendererObserver {
public:
ForwardingRendererObserver(util::RunLoop& mapRunLoop, RendererObserver& delegate_)
: mailbox(std::make_shared<Mailbox>(mapRunLoop))
, delegate(delegate_, mailbox) {
}
~ForwardingRendererObserver() {
mailbox->close();
}
void onInvalidate() override {
delegate.invoke(&RendererObserver::onInvalidate);
}
void onResourceError(std::exception_ptr err) override {
delegate.invoke(&RendererObserver::onResourceError, err);
}
void onWillStartRenderingMap() override {
delegate.invoke(&RendererObserver::onWillStartRenderingMap);
}
void onWillStartRenderingFrame() override {
delegate.invoke(&RendererObserver::onWillStartRenderingFrame);
}
void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded, bool placementChanged) override {
delegate.invoke(&RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded, placementChanged);
}
void onDidFinishRenderingMap() override {
delegate.invoke(&RendererObserver::onDidFinishRenderingMap);
}
void onStyleImageMissing(const std::string& id, StyleImageMissingCallback done) override {
delegate.invoke(&RendererObserver::onStyleImageMissing, id, done);
}
void onRemoveUnusedStyleImages(const std::vector<std::string>& ids) override {
delegate.invoke(&RendererObserver::onRemoveUnusedStyleImages, ids);
}
private:
std::shared_ptr<Mailbox> mailbox;
ActorRef<RendererObserver> delegate;
};
AndroidRendererFrontend::AndroidRendererFrontend(MapRenderer& mapRenderer_)
: mapRenderer(mapRenderer_)
, mapRunLoop(util::RunLoop::Get())
, updateAsyncTask(std::make_unique<util::AsyncTask>([this]() {
mapRenderer.update(std::move(updateParams));
mapRenderer.requestRender();
})) {
}
AndroidRendererFrontend::~AndroidRendererFrontend() = default;
void AndroidRendererFrontend::reset() {
mapRenderer.reset();
}
void AndroidRendererFrontend::setObserver(RendererObserver& observer) {
assert (util::RunLoop::Get());
// Don't call the Renderer directly, but use MapRenderer#setObserver to make sure
// the Renderer may be re-initialised without losing the RendererObserver reference.
mapRenderer.setObserver(std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer));
}
void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
updateParams = std::move(params);
updateAsyncTask->send();
}
void AndroidRendererFrontend::reduceMemoryUse() {
mapRenderer.actor().invoke(&Renderer::reduceMemoryUse);
}
std::vector<Feature> AndroidRendererFrontend::querySourceFeatures(const std::string& sourceID,
const SourceQueryOptions& options) const {
// Waits for the result from the orchestration thread and returns
return mapRenderer.actor().ask(&Renderer::querySourceFeatures, sourceID, options).get();
}
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenBox& box,
const RenderedQueryOptions& options) const {
// Select the right overloaded method
std::vector<Feature> (Renderer::*fn)(const ScreenBox&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures;
// Waits for the result from the orchestration thread and returns
return mapRenderer.actor().ask(fn, box, options).get();
}
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenCoordinate& point,
const RenderedQueryOptions& options) const {
// Select the right overloaded method
std::vector<Feature> (Renderer::*fn)(const ScreenCoordinate&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures;
// Waits for the result from the orchestration thread and returns
return mapRenderer.actor().ask(fn, point, options).get();
}
AnnotationIDs AndroidRendererFrontend::queryPointAnnotations(const ScreenBox& box) const {
// Waits for the result from the orchestration thread and returns
return mapRenderer.actor().ask(&Renderer::queryPointAnnotations, box).get();
}
AnnotationIDs AndroidRendererFrontend::queryShapeAnnotations(const ScreenBox& box) const {
// Waits for the result from the orchestration thread and returns
return mapRenderer.actor().ask(&Renderer::queryShapeAnnotations, box).get();
}
FeatureExtensionValue AndroidRendererFrontend::queryFeatureExtensions(const std::string& sourceID,
const Feature& feature,
const std::string& extension,
const std::string& extensionField,
const optional<std::map<std::string, mbgl::Value>>& args) const {
return mapRenderer.actor().ask(&Renderer::queryFeatureExtensions, sourceID, feature, extension, extensionField, args).get();
}
} // namespace android
} // namespace mbgl

View File

@@ -1,68 +0,0 @@
#pragma once
#include <mbgl/actor/actor.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/renderer/renderer_frontend.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/run_loop.hpp>
#include <functional>
#include <memory>
#include <vector>
#include <string>
#include <mbgl/util/geojson.hpp>
#include "map_renderer.hpp"
namespace mbgl {
class RenderedQueryOptions;
class SourceQueryOptions;
namespace util {
class AsyncTask;
} // namespace util
namespace android {
class AndroidRendererFrontend : public RendererFrontend {
public:
AndroidRendererFrontend(MapRenderer&);
~AndroidRendererFrontend() override;
void reset() override;
void setObserver(RendererObserver&) override;
void update(std::shared_ptr<UpdateParameters>) override;
// Feature querying
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions&) const;
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions&) const;
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
AnnotationIDs queryPointAnnotations(const ScreenBox& box) const;
AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
// Feature extension query
FeatureExtensionValue
queryFeatureExtensions(const std::string& sourceID,
const Feature& feature,
const std::string& extension,
const std::string& extensionField,
const optional<std::map<std::string, mbgl::Value>>& args) const;
// Memory
void reduceMemoryUse();
private:
MapRenderer& mapRenderer;
util::RunLoop* mapRunLoop;
std::unique_ptr<util::AsyncTask> updateAsyncTask;
std::shared_ptr<UpdateParameters> updateParams;
};
} // namespace android
} // namespace mbgl

View File

@@ -1,23 +0,0 @@
#include "marker.hpp"
namespace mbgl {
namespace android {
mbgl::Point<double> Marker::getPosition(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
static auto& javaClass = jni::Class<Marker>::Singleton(env);
static auto positionField = javaClass.GetField<jni::Object<LatLng>>(env, "position");
return LatLng::getGeometry(env, marker.Get(env, positionField));
}
std::string Marker::getIconId(jni::JNIEnv& env, const jni::Object<Marker>& marker) {
static auto& javaClass = jni::Class<Marker>::Singleton(env);
static auto iconIdField = javaClass.GetField<jni::String>(env, "iconId");
return jni::Make<std::string>(env, marker.Get(env, iconIdField));
}
void Marker::registerNative(jni::JNIEnv& env) {
jni::Class<Marker>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,28 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <jni/jni.hpp>
#include <string>
#include "../geometry/lat_lng.hpp"
namespace mbgl {
namespace android {
class Marker : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Marker"; };
static mbgl::Point<double> getPosition(jni::JNIEnv&, const jni::Object<Marker>&);
static std::string getIconId(jni::JNIEnv&, const jni::Object<Marker>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,34 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <jni/jni.hpp>
#include "../geometry/lat_lng.hpp"
#include "../java/util.hpp"
namespace mbgl {
namespace android {
class MultiPoint : protected mbgl::util::noncopyable {
protected:
template <class Geometry>
static Geometry toGeometry(JNIEnv& env, const jni::Object<java::util::List>& pointsList) {
auto jarray = java::util::List::toArray<LatLng>(env, pointsList);
std::size_t size = jarray.Length(env);
Geometry geometry;
geometry.reserve(size);
for (std::size_t i = 0; i < size; i++) {
geometry.push_back(LatLng::getGeometry(env, jarray.Get(env, i)));
}
return geometry;
}
};
} // namespace android
} // namespace mbgl

View File

@@ -1,40 +0,0 @@
#include "polygon.hpp"
#include "../conversion/color.hpp"
namespace mbgl {
namespace android {
mbgl::FillAnnotation Polygon::toAnnotation(jni::JNIEnv& env, const jni::Object<Polygon>& polygon) {
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
static auto holes = javaClass.GetField<jni::Object<java::util::List>>(env, "holes");
static auto alpha = javaClass.GetField<float>(env, "alpha");
static auto fillColor = javaClass.GetField<int>(env, "fillColor");
static auto strokeColor = javaClass.GetField<int>(env, "strokeColor");
mbgl::Polygon<double> geometry {
MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, polygon.Get(env, points))
};
auto jHoleListsArray = java::util::List::toArray<java::util::List>(env, polygon.Get(env, holes));
std::size_t jHoleListsSize = jHoleListsArray.Length(env);
for (std::size_t i = 0; i < jHoleListsSize; i++) {
geometry.push_back(MultiPoint::toGeometry<mbgl::LinearRing<double>>(env, jHoleListsArray.Get(env, i)));
}
mbgl::FillAnnotation annotation { geometry };
annotation.opacity = polygon.Get(env, alpha);
annotation.color = *conversion::convert<mbgl::Color>(env, polygon.Get(env, fillColor));
annotation.outlineColor = *conversion::convert<mbgl::Color>(env, polygon.Get(env, strokeColor));
return annotation;
}
void Polygon::registerNative(jni::JNIEnv& env) {
jni::Class<Polygon>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,21 +0,0 @@
#pragma once
#include <mbgl/annotation/annotation.hpp>
#include "multi_point.hpp"
namespace mbgl {
namespace android {
class Polygon : private MultiPoint {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polygon"; };
static mbgl::FillAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polygon>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,31 +0,0 @@
#include "polyline.hpp"
#include "../conversion/color.hpp"
namespace mbgl {
namespace android {
mbgl::LineAnnotation Polyline::toAnnotation(jni::JNIEnv& env, const jni::Object<Polyline>& polyline) {
static auto& javaClass = jni::Class<Polyline>::Singleton(env);
static auto points = javaClass.GetField<jni::Object<java::util::List>>(env, "points");
static auto alpha = javaClass.GetField<float>(env, "alpha");
static auto color = javaClass.GetField<int>(env, "color");
static auto width = javaClass.GetField<float>(env, "width");
mbgl::LineAnnotation annotation {
MultiPoint::toGeometry<mbgl::LineString<double>>(env, polyline.Get(env, points))
};
annotation.opacity = polyline.Get(env, alpha);
annotation.color = *conversion::convert<mbgl::Color>(env, polyline.Get(env, color));
annotation.width = polyline.Get(env, width);
return annotation;
}
void Polyline::registerNative(jni::JNIEnv& env) {
jni::Class<Polyline>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,21 +0,0 @@
#pragma once
#include <mbgl/annotation/annotation.hpp>
#include "multi_point.hpp"
namespace mbgl {
namespace android {
class Polyline : private MultiPoint {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/annotations/Polyline"; };
static mbgl::LineAnnotation toAnnotation(jni::JNIEnv&, const jni::Object<Polyline>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,14 +0,0 @@
#pragma once
namespace mbgl {
namespace android {
class AssetManager {
public:
static constexpr auto Name() {
return "android/content/res/AssetManager";
};
};
} // namespace android
} // namespace mbgl

View File

@@ -1,57 +0,0 @@
#include "asset_manager_file_source.hpp"
#include <mbgl/storage/file_source_request.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/url.hpp>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
namespace mbgl {
class AssetManagerFileSource::Impl {
public:
Impl(ActorRef<Impl>, AAssetManager* assetManager_) : assetManager(assetManager_) {
}
void request(const std::string& url, ActorRef<FileSourceRequest> req) {
// Note: AssetManager already prepends "assets" to the filename.
const std::string path = mbgl::util::percentDecode(url.substr(8));
Response response;
if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) {
response.data = std::make_shared<std::string>(
reinterpret_cast<const char*>(AAsset_getBuffer(asset)), AAsset_getLength64(asset));
AAsset_close(asset);
} else {
response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound,
"Could not read asset");
}
req.invoke(&FileSourceRequest::setResponse, response);
}
private:
AAssetManager* assetManager;
};
AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env, const jni::Object<android::AssetManager>& assetManager_)
: assetManager(jni::NewGlobal(env, assetManager_)),
impl(std::make_unique<util::Thread<Impl>>("AssetManagerFileSource",
AAssetManager_fromJava(&env, jni::Unwrap(assetManager.get())))) {
}
AssetManagerFileSource::~AssetManagerFileSource() = default;
std::unique_ptr<AsyncRequest> AssetManagerFileSource::request(const Resource& resource, Callback callback) {
auto req = std::make_unique<FileSourceRequest>(std::move(callback));
impl->actor().invoke(&Impl::request, resource.url, req->actor());
return std::move(req);
}
} // namespace mbgl

View File

@@ -1,29 +0,0 @@
#pragma once
#include <mbgl/storage/file_source.hpp>
#include "asset_manager.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace util {
template <typename T> class Thread;
} // namespace util
class AssetManagerFileSource : public FileSource {
public:
AssetManagerFileSource(jni::JNIEnv&, const jni::Object<android::AssetManager>&);
~AssetManagerFileSource() override;
std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override;
private:
class Impl;
jni::Global<jni::Object<android::AssetManager>> assetManager;
std::unique_ptr<util::Thread<Impl>> impl;
};
} // namespace mbgl

View File

@@ -1,62 +0,0 @@
#include "run_loop_impl.hpp"
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/run_loop.hpp>
#include <atomic>
#include <functional>
namespace mbgl {
namespace util {
class AsyncTask::Impl : public RunLoop::Impl::Runnable {
public:
Impl(std::function<void()>&& fn)
: queued(true), task(std::move(fn)) {
}
~Impl() {
loop->removeRunnable(this);
}
void maySend() {
if (queued) {
queued = false;
loop->addRunnable(this);
}
}
TimePoint dueTime() const override {
return due;
}
void runTask() override {
loop->removeRunnable(this);
queued = true;
task();
}
private:
// Always expired, run immediately.
const TimePoint due = Clock::now();
RunLoop::Impl* loop = reinterpret_cast<RunLoop::Impl*>(RunLoop::getLoopHandle());
// TODO: Use std::atomic_flag if we ever drop
// support for ARMv5
std::atomic<bool> queued;
std::function<void()> task;
};
AsyncTask::AsyncTask(std::function<void()>&& fn)
: impl(std::make_unique<Impl>(std::move(fn))) {
}
AsyncTask::~AsyncTask() = default;
void AsyncTask::send() {
impl->maySend();
}
} // namespace util
} // namespace mbgl

View File

@@ -1,22 +0,0 @@
#include "attach_env.hpp"
#include "jni.hpp"
namespace mbgl {
namespace android {
UniqueEnv AttachEnv() {
JNIEnv* env = nullptr;
jint err = theJVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
switch (err) {
case JNI_OK:
return UniqueEnv(env, JNIEnvDeleter(*theJVM, false));
case JNI_EDETACHED:
return UniqueEnv(jni::AttachCurrentThread(*theJVM).release(), JNIEnvDeleter(*theJVM, true));
default:
throw std::system_error(err, jni::ErrorCategory());
}
}
}
}

View File

@@ -1,31 +0,0 @@
#pragma once
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class JNIEnvDeleter {
private:
jni::JavaVM* vm = nullptr;
bool detach = false;
public:
JNIEnvDeleter() = default;
JNIEnvDeleter(jni::JavaVM& v, bool d)
: vm(&v), detach(d) {}
void operator()(jni::JNIEnv* p) const {
if (p && detach) {
assert(vm);
vm->DetachCurrentThread();
}
}
};
using UniqueEnv = std::unique_ptr<jni::JNIEnv, JNIEnvDeleter>;
UniqueEnv AttachEnv();
}
}

View File

@@ -1,124 +0,0 @@
#include "bitmap.hpp"
#include <android/bitmap.h>
#include <mbgl/util/logging.hpp>
namespace mbgl {
namespace android {
class PixelGuard {
public:
PixelGuard(jni::JNIEnv& env_, const jni::Object<Bitmap>& bitmap_) : env(env_), bitmap(bitmap_) {
const int result = AndroidBitmap_lockPixels(&env, jni::Unwrap(*bitmap),
reinterpret_cast<void**>(&address));
if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
throw std::runtime_error("bitmap decoding: could not lock pixels");
}
}
~PixelGuard() {
const int result = AndroidBitmap_unlockPixels(&env, jni::Unwrap(*bitmap));
if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
Log::Warning(mbgl::Event::General, "Bitmap decoding: could not unlock pixels");
}
}
auto* get() {
return address;
}
private:
jni::JNIEnv& env;
const jni::Object<Bitmap>& bitmap;
uint8_t* address;
};
jni::Local<jni::Object<Bitmap::Config>> Bitmap::Config::Create(jni::JNIEnv& env, Value value) {
static auto& _class = jni::Class<Config>::Singleton(env);
switch (value) {
case ALPHA_8:
return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ALPHA_8"));
case ARGB_4444:
return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ARGB_4444"));
case ARGB_8888:
return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "ARGB_8888"));
case RGB_565:
return _class.Get(env, _class.GetStaticField<jni::Object<Config>>(env, "RGB_565"));
default:
throw std::runtime_error("invalid enum value for Bitmap.Config");
}
}
void Bitmap::registerNative(jni::JNIEnv& env) {
jni::Class<Bitmap>::Singleton(env);
jni::Class<Bitmap::Config>::Singleton(env);
}
jni::Local<jni::Object<Bitmap>> Bitmap::CreateBitmap(jni::JNIEnv& env,
jni::jint width,
jni::jint height,
const jni::Object<Config>& config) {
static auto& _class = jni::Class<Bitmap>::Singleton(env);
static auto method = _class.GetStaticMethod<jni::Object<Bitmap> (jni::jint, jni::jint, jni::Object<Config>)>(env, "createBitmap");
return _class.Call(env, method, width, height, config);
}
PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) {
AndroidBitmapInfo info;
const int result = AndroidBitmap_getInfo(&env, jni::Unwrap(*bitmap), &info);
if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
throw std::runtime_error("bitmap decoding: couldn't get bitmap info");
}
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
return Bitmap::GetImage(env, Bitmap::Copy(env, bitmap));
}
PixelGuard guard(env, bitmap);
// Copy the Android Bitmap into the PremultipliedImage.
auto pixels =
std::make_unique<uint8_t[]>(info.width * info.height * PremultipliedImage::channels);
for (uint32_t y = 0; y < info.height; y++) {
auto begin = guard.get() + y * info.stride;
std::copy(begin, begin + info.width * PremultipliedImage::channels,
pixels.get() + y * info.width * PremultipliedImage::channels);
}
return { Size{ info.width, info.height }, std::move(pixels) };
}
jni::Local<jni::Object<Bitmap>> Bitmap::CreateBitmap(jni::JNIEnv& env, const PremultipliedImage& image) {
auto bitmap = CreateBitmap(env, image.size.width, image.size.height, Config::ARGB_8888);
AndroidBitmapInfo info;
const int result = AndroidBitmap_getInfo(&env, jni::Unwrap(*bitmap), &info);
if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
// TODO: more specific information
throw std::runtime_error("bitmap creation: couldn't get bitmap info");
}
assert(info.width == image.size.width);
assert(info.height == image.size.height);
assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888);
PixelGuard guard(env, bitmap);
// Copy the PremultipliedImage into the Android Bitmap
for (uint32_t y = 0; y < image.size.height; y++) {
auto begin = image.data.get() + y * image.stride();
std::copy(begin, begin + image.stride(), guard.get() + y * info.stride);
}
return bitmap;
}
jni::Local<jni::Object<Bitmap>> Bitmap::Copy(jni::JNIEnv& env, const jni::Object<Bitmap>& bitmap) {
static auto& klass = jni::Class<Bitmap>::Singleton(env);
static auto copy = klass.GetMethod<jni::Object<Bitmap> (jni::Object<Config>, jni::jboolean)>(env, "copy");
return bitmap.Call(env, copy, Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888), jni::jni_false);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,43 +0,0 @@
#pragma once
#include <mbgl/util/image.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class Bitmap {
public:
class Config {
public:
static constexpr auto Name() { return "android/graphics/Bitmap$Config"; };
enum Value {
ALPHA_8,
ARGB_4444,
ARGB_8888,
RGB_565,
};
static jni::Local<jni::Object<Config>> Create(jni::JNIEnv&, Value);
};
static constexpr auto Name() { return "android/graphics/Bitmap"; };
static void registerNative(jni::JNIEnv&);
static jni::Local<jni::Object<Bitmap>>
CreateBitmap(jni::JNIEnv&, jni::jint width, jni::jint height, const jni::Object<Config>&);
static jni::Local<jni::Object<Bitmap>>
CreateBitmap(jni::JNIEnv& env, jni::jint width, jni::jint height, Config::Value config) {
return CreateBitmap(env, width, height, Config::Create(env, config));
}
static PremultipliedImage GetImage(jni::JNIEnv&, const jni::Object<Bitmap>&);
static jni::Local<jni::Object<Bitmap>> CreateBitmap(jni::JNIEnv&, const PremultipliedImage&);
static jni::Local<jni::Object<Bitmap>> Copy(jni::JNIEnv&, const jni::Object<Bitmap>&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,25 +0,0 @@
#include "bitmap_factory.hpp"
namespace mbgl {
namespace android {
void BitmapFactory::registerNative(jni::JNIEnv& env) {
jni::Class<BitmapFactory>::Singleton(env);
}
jni::Local<jni::Object<Bitmap>> BitmapFactory::DecodeByteArray(jni::JNIEnv& env,
jni::Array<jni::jbyte>& data,
jni::jint offset,
jni::jint length) {
static auto& _class = jni::Class<BitmapFactory>::Singleton(env);
// Images are loaded with ARGB_8888 config, and premultiplied by default, which is exactly
// what we want, so we're not providing a BitmapFactory.Options object.
using Signature = jni::Object<Bitmap> (jni::Array<jni::jbyte>, jni::jint, jni::jint);
static auto method = _class.GetStaticMethod<Signature>(env, "decodeByteArray");
return _class.Call(env, method, data, offset, length);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,20 +0,0 @@
#pragma once
#include <jni/jni.hpp>
#include "bitmap.hpp"
namespace mbgl {
namespace android {
class BitmapFactory {
public:
static constexpr auto Name() { return "android/graphics/BitmapFactory"; };
static void registerNative(jni::JNIEnv&);
static jni::Local<jni::Object<Bitmap>>
DecodeByteArray(jni::JNIEnv&, jni::Array<jni::jbyte>& data, jni::jint offset, jni::jint length);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,41 +0,0 @@
#include "connectivity_listener.hpp"
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/logging.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
/**
* Invoked when the construction is initiated from the jvm
*/
ConnectivityListener::ConnectivityListener(jni::JNIEnv&) {}
ConnectivityListener::~ConnectivityListener() {}
void ConnectivityListener::onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean connected) {
NetworkStatus::Set(connected ? NetworkStatus::Status::Online : NetworkStatus::Status::Offline);
}
void ConnectivityListener::registerNative(jni::JNIEnv& env) {
// Lookup the class
static auto& javaClass = jni::Class<ConnectivityListener>::Singleton(env);
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
// Register the peer
jni::RegisterNativePeer<ConnectivityListener>(
env,
javaClass,
"nativePtr",
std::make_unique<ConnectivityListener, JNIEnv&>,
"initialize",
"finalize",
METHOD(&ConnectivityListener::onConnectivityStateChanged, "nativeOnConnectivityStateChanged")
);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,29 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class ConnectivityListener : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/net/NativeConnectivityListener"; };
static void registerNative(jni::JNIEnv&);
/*
* Called when a Java object was created from the jvm side
*/
ConnectivityListener(jni::JNIEnv&);
~ConnectivityListener();
void onConnectivityStateChanged(jni::JNIEnv&, jni::jboolean);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,32 +0,0 @@
#include "collection.hpp"
#include "constant.hpp"
namespace mbgl {
namespace android {
namespace conversion {
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array) {
std::size_t len = array.Length(env);
std::vector<std::string> vector;
vector.reserve(len);
for (std::size_t i = 0; i < len; i++) {
vector.push_back(jni::Make<std::string>(env, array.Get(env, i)));
}
return vector;
}
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>& vector) {
auto result = jni::Array<jni::String>::New(env, vector.size());
for (std::size_t i = 0; i < vector.size(); i++) {
result.Set(env, i, jni::Make<jni::String>(env, vector.at(i)));
}
return result;
}
}
}
}

View File

@@ -1,18 +0,0 @@
#pragma once
#include "conversion.hpp"
#include <jni/jni.hpp>
#include <vector>
namespace mbgl {
namespace android {
namespace conversion {
std::vector<std::string> toVector(JNIEnv& env, const jni::Array<jni::String>& array);
jni::Local<jni::Array<jni::String>> toArray(JNIEnv& env, const std::vector<std::string>&);
}
}
}

View File

@@ -1,17 +0,0 @@
#include "color.hpp"
namespace mbgl {
namespace android {
namespace conversion {
Result<mbgl::Color> Converter<mbgl::Color, int>::operator()(jni::JNIEnv&, const int& color) const {
float r = (color >> 16) & 0xFF;
float g = (color >> 8) & 0xFF;
float b = (color) & 0xFF;
float a = (color >> 24) & 0xFF;
return { mbgl::Color( r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f ) };
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -1,18 +0,0 @@
#pragma once
#include "conversion.hpp"
#include <mbgl/util/color.hpp>
namespace mbgl {
namespace android {
namespace conversion {
template <>
struct Converter<mbgl::Color, int> {
Result<mbgl::Color> operator()(jni::JNIEnv&, const int& color) const;
};
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -1,57 +0,0 @@
#include "constant.hpp"
#include "collection.hpp"
#include "../style/formatted.hpp"
#include <mbgl/util/string.hpp>
namespace mbgl {
namespace android {
namespace conversion {
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, bool>::operator()(jni::JNIEnv& env, const bool& value) const {
return jni::Box(env, value ? jni::jni_true : jni::jni_false);
}
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, float>::operator()(jni::JNIEnv& env, const float& value) const {
return jni::Box(env, value);
}
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, double>::operator()(jni::JNIEnv& env, const double& value) const {
return jni::Box(env, value);
}
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::string>::operator()(jni::JNIEnv& env, const std::string& value) const {
return jni::Make<jni::String>(env, value);
}
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, Color>::operator()(jni::JNIEnv& env, const Color& value) const {
return jni::Make<jni::String>(env, value.stringify());
}
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, style::expression::Formatted>::operator()(jni::JNIEnv& env, const style::expression::Formatted& value) const {
return Formatted::New(env, value);
}
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<std::string>>::operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const {
auto result = jni::Array<jni::String>::New(env, value.size());
for (std::size_t i = 0; i < value.size(); i++) {
result.Set(env, i, jni::Make<jni::String>(env, value.at(i)));
}
return result;
}
Result<jni::Local<jni::Object<>>> Converter<jni::Local<jni::Object<>>, std::vector<float>>::operator()(jni::JNIEnv& env, const std::vector<float>& value) const {
auto result = jni::Array<jni::Float>::New(env, value.size());
for (std::size_t i = 0; i < value.size(); i++) {
result.Set(env, i, jni::Box(env, value.at(i)));
}
return result;
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -1,104 +0,0 @@
#pragma once
#include "conversion.hpp"
#include <mbgl/util/color.hpp>
#include <mbgl/util/enum.hpp>
#include <mbgl/style/expression/formatted.hpp>
#include <jni/jni.hpp>
#include <string>
#include <array>
#include <vector>
namespace mbgl {
namespace android {
namespace conversion {
template <>
struct Converter<jni::Local<jni::Object<>>, bool> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const bool& value) const;
};
template <>
struct Converter<jni::Local<jni::Object<>>, float> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const float& value) const;
};
template <>
struct Converter<jni::Local<jni::Object<>>, double> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const double& value) const;
};
/**
* All integrals. java is limited to 64 bit signed, so...
* TODO: use BigDecimal for > 64 / unsigned?
*/
template<typename T>
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if<std::is_integral<T>::value>::type> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
return jni::Box(env, jni::jlong(value));
}
};
// TODO: convert integral types to primitive jni types
template <>
struct Converter<jni::Local<jni::Object<>>, std::string> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::string& value) const;
};
template <>
struct Converter<jni::Local<jni::Object<>>, Color> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const Color& value) const;
};
template <>
struct Converter<jni::Local<jni::Object<>>, style::expression::Formatted> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const style::expression::Formatted& value) const;
};
template <std::size_t N>
struct Converter<jni::Local<jni::Object<>>, std::array<float, N>> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::array<float, N>& value) const {
std::vector<float> v;
for (const float& id : value) {
v.push_back(id);
}
return convert<jni::Local<jni::Object<>>, std::vector<float>>(env, v);
}
};
template <>
struct Converter<jni::Local<jni::Object<>>, std::vector<std::string>> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<std::string>& value) const;
};
template <>
struct Converter<jni::Local<jni::Object<>>, std::vector<float>> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<float>& value) const;
};
template <class T>
struct Converter<jni::Local<jni::Object<>>, T, typename std::enable_if_t<std::is_enum<T>::value>> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const T& value) const {
return convert<jni::Local<jni::Object<>>, std::string>(env, Enum<T>::toString(value));
}
};
template <class T>
struct Converter<jni::Local<jni::Object<>>, std::vector<T>, typename std::enable_if_t<std::is_enum<T>::value>> {
Result<jni::Local<jni::Object<>>> operator()(jni::JNIEnv& env, const std::vector<T>& value) const {
auto result = jni::Array<jni::String>::New(env, value.size());
for (std::size_t i = 0; i < value.size(); ++i) {
result.Set(env, i, jni::Make<jni::String>(env, Enum<T>::toString(value.at(i))));
}
return result;
}
};
} // namespace conversion
} // namespace android
} // namespace mbgl

View File

@@ -1,50 +0,0 @@
#pragma once
#include <mbgl/util/variant.hpp>
#include <jni/jni.hpp>
#include <string>
namespace mbgl {
namespace android {
namespace conversion {
struct Error { std::string message; };
template <class T>
class Result : private variant<T, Error> {
public:
using variant<T, Error>::variant;
explicit operator bool() const {
return this->template is<T>();
}
T& operator*() {
assert(this->template is<T>());
return this->template get<T>();
}
const T& operator*() const {
assert(this->template is<T>());
return this->template get<T>();
}
const Error& error() const {
assert(this->template is<Error>());
return this->template get<Error>();
}
};
template <class T, class V, class Enable = void>
struct Converter;
template <class T, typename V, class...Args>
Result<T> convert(jni::JNIEnv& env, const V& value, Args&&...args) {
return Converter<T, V>()(env, value, std::forward<Args>(args)...);
}
} // namespace conversion
} // namespace android
} // namespace mbgl

View File

@@ -1,238 +0,0 @@
#include <jni.h>
#include <GLES2/gl2.h>
#include <sstream>
#include <android/log.h>
#include <mbgl/style/layers/custom_layer.hpp>
// DEBUGGING
const char* LOG_TAG = "Custom Layer Example";
const char* stringFromError(GLenum err) {
switch (err) {
case GL_INVALID_ENUM:
return "GL_INVALID_ENUM";
case GL_INVALID_VALUE:
return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION:
return "GL_INVALID_OPERATION";
case GL_INVALID_FRAMEBUFFER_OPERATION:
return "GL_INVALID_FRAMEBUFFER_OPERATION";
case GL_OUT_OF_MEMORY:
return "GL_OUT_OF_MEMORY";
#ifdef GL_TABLE_TOO_LARGE
case GL_TABLE_TOO_LARGE:
return "GL_TABLE_TOO_LARGE";
#endif
#ifdef GL_STACK_OVERFLOW
case GL_STACK_OVERFLOW:
return "GL_STACK_OVERFLOW";
#endif
#ifdef GL_STACK_UNDERFLOW
case GL_STACK_UNDERFLOW:
return "GL_STACK_UNDERFLOW";
#endif
#ifdef GL_CONTEXT_LOST
case GL_CONTEXT_LOST:
return "GL_CONTEXT_LOST";
#endif
default:
return "GL_UNKNOWN";
}
}
struct Error : std::runtime_error {
using std::runtime_error::runtime_error;
};
void checkError(const char *cmd, const char *file, int line) {
GLenum err = GL_NO_ERROR;
if ((err = glGetError()) != GL_NO_ERROR) {
std::ostringstream message;
message << cmd << ": Error " << stringFromError(err);
// Check for further errors
while ((err = glGetError()) != GL_NO_ERROR) {
message << ", " << stringFromError(err);
}
message << " at " << file << ":" << line;
__android_log_write(ANDROID_LOG_ERROR, LOG_TAG, message.str().c_str());
throw Error(message.str());
}
}
#ifndef NDEBUG
#define GL_CHECK_ERROR(cmd) ([&]() { struct __MBGL_C_E { ~__MBGL_C_E() noexcept(false) { checkError(#cmd, __FILE__, __LINE__); } } __MBGL_C_E; return cmd; }())
#else
#define GL_CHECK_ERROR(cmd) (cmd)
#endif
void checkLinkStatus(GLuint program) {
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
if (isLinked == GL_FALSE) {
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
GLchar infoLog[maxLength];
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
__android_log_write(ANDROID_LOG_ERROR, LOG_TAG, &infoLog[0]);
throw Error(infoLog);
}
}
void checkCompileStatus(GLuint shader) {
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE) {
GLint maxLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
// The maxLength includes the NULL character
GLchar errorLog[maxLength];
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
__android_log_write(ANDROID_LOG_ERROR, LOG_TAG, &errorLog[0]);
throw Error(errorLog);
}
}
// /DEBUGGING
static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
static const GLchar * fragmentShaderSource = "uniform highp vec4 fill_color; void main() { gl_FragColor = fill_color; }";
class ExampleCustomLayer: mbgl::style::CustomLayerHost {
public:
~ExampleCustomLayer() {
}
void initialize() {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Initialize");
// Debug info
int maxAttrib;
GL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrib));
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Max vertex attributes: %i", maxAttrib);
program = GL_CHECK_ERROR(glCreateProgram());
vertexShader = GL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER));
fragmentShader = GL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER));
GL_CHECK_ERROR(glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr));
GL_CHECK_ERROR(glCompileShader(vertexShader));
checkCompileStatus(vertexShader);
GL_CHECK_ERROR(glAttachShader(program, vertexShader));
GL_CHECK_ERROR(glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr));
GL_CHECK_ERROR(glCompileShader(fragmentShader));
checkCompileStatus(fragmentShader);
GL_CHECK_ERROR(glAttachShader(program, fragmentShader));
GL_CHECK_ERROR(glLinkProgram(program));
checkLinkStatus(program);
a_pos = GL_CHECK_ERROR(glGetAttribLocation(program, "a_pos"));
fill_color = GL_CHECK_ERROR(glGetUniformLocation(program, "fill_color"));
GLfloat background[] = { -1, -1, 1, -1, -1, 1, 1, 1 };
GL_CHECK_ERROR(glGenBuffers(1, &buffer));
GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW));
}
void render(const mbgl::style::CustomLayerRenderParameters&) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Render");
glUseProgram(program);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glEnableVertexAttribArray(a_pos);
glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glUniform4fv(fill_color, 1, color);
GL_CHECK_ERROR(glUseProgram(program));
GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
GL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
GL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL));
GL_CHECK_ERROR(glDisable(GL_STENCIL_TEST));
GL_CHECK_ERROR(glDisable(GL_DEPTH_TEST));
GL_CHECK_ERROR(glUniform4fv(fill_color, 1, color));
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
void contextLost() {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "ContextLost");
program = 0;
}
void deinitialize() {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "DeInitialize");
if (program) {
glDeleteBuffers(1, &buffer);
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteProgram(program);
}
}
GLuint program = 0;
GLuint vertexShader = 0;
GLuint fragmentShader = 0;
GLuint buffer = 0;
GLuint a_pos = 0;
GLuint fill_color = 0;
static GLfloat color[];
};
GLfloat ExampleCustomLayer::color[] = { 0.0f, 1.0f, 0.0f, 1.0f };
jlong JNICALL nativeCreateContext(JNIEnv*, jobject) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeCreateContext");
auto exampleCustomLayer = std::make_unique<ExampleCustomLayer>();
return reinterpret_cast<jlong>(exampleCustomLayer.release());
}
void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "nativeSetColor: %.2f, %.2f, %.2f, %.2f", red, green, blue, alpha);
ExampleCustomLayer::color[0] = red;
ExampleCustomLayer::color[1] = green;
ExampleCustomLayer::color[2] = blue;
ExampleCustomLayer::color[3] = alpha;
}
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "OnLoad");
JNIEnv *env = nullptr;
vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
jclass customLayerClass = env->FindClass("com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer");
JNINativeMethod methods[] = {
{"createContext", "()J", reinterpret_cast<void *>(&nativeCreateContext)},
{"setColor", "(FFFF)V", reinterpret_cast<void *>(&nativeSetColor)}
};
if (env->RegisterNatives(customLayerClass, methods, 2) < 0) {
env->ExceptionDescribe();
return JNI_ERR;
}
return JNI_VERSION_1_6;
}
extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *) {
}

View File

@@ -1,207 +0,0 @@
#include "file_source.hpp"
#include "attach_env.hpp"
#include "mapbox.hpp"
#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/storage/resource_transform.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/storage/sqlite3.hpp>
#include "asset_manager_file_source.hpp"
namespace mbgl {
std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) {
auto env{android::AttachEnv()};
std::shared_ptr<DefaultFileSource> fileSource;
if (android::Mapbox::hasInstance(*env)) {
auto assetManager = android::Mapbox::getAssetManager(*env);
fileSource = std::make_shared<DefaultFileSource>(options.cachePath(),
std::make_unique<AssetManagerFileSource>(*env, assetManager));
} else {
fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), options.assetPath());
}
fileSource->setAccessToken(options.accessToken());
return fileSource;
}
namespace android {
// FileSource //
FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const jni::String& _cachePath) {
std::string path = jni::Make<std::string>(_env, _cachePath);
mapbox::sqlite::setTempPath(path);
resourceOptions.withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "")
.withCachePath(path + DATABASE_FILE);
// Create a core default file source
fileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(resourceOptions));
}
FileSource::~FileSource() {
}
jni::Local<jni::String> FileSource::getAccessToken(jni::JNIEnv& env) {
return jni::Make<jni::String>(env, fileSource->getAccessToken());
}
void FileSource::setAccessToken(jni::JNIEnv& env, const jni::String& token) {
fileSource->setAccessToken(token ? jni::Make<std::string>(env, token) : "");
}
void FileSource::setAPIBaseUrl(jni::JNIEnv& env, const jni::String& url) {
fileSource->setAPIBaseURL(jni::Make<std::string>(env, url));
}
void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& transformCallback) {
if (transformCallback) {
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, transformCallback);
resourceTransform = std::make_unique<Actor<ResourceTransform>>(
*Scheduler::GetCurrent(),
// Capture the ResourceTransformCallback object as a managed global into
// the lambda. It is released automatically when we're setting a new ResourceTransform in
// a subsequent call.
// Note: we're converting it to shared_ptr because this lambda is converted to a std::function,
// which requires copyability of its captured variables.
[callback = std::make_shared<decltype(global)>(std::move(global))](mbgl::Resource::Kind kind,
const std::string& url_) {
android::UniqueEnv _env = android::AttachEnv();
return FileSource::ResourceTransformCallback::onURL(*_env, *callback, int(kind), url_);
});
fileSource->setResourceTransform(resourceTransform->self());
} else {
// Reset the callback
resourceTransform.reset();
fileSource->setResourceTransform({});
}
}
void FileSource::setResourceCachePath(jni::JNIEnv& env, const jni::String& path,
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& _callback) {
if (pathChangeCallback) {
FileSource::ResourcesCachePathChangeCallback::onError(env, _callback, jni::Make<jni::String>(env, "Another resources cache path change is in progress"));
return;
}
std::string newPath = jni::Make<std::string>(env, path);
mapbox::sqlite::setTempPath(newPath);
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, _callback);
pathChangeCallback = std::make_unique<Actor<PathChangeCallback>>(*Scheduler::GetCurrent(),
[this, callback = std::make_shared<decltype(global)>(std::move(global)), newPath] {
android::UniqueEnv _env = android::AttachEnv();
FileSource::ResourcesCachePathChangeCallback::onSuccess(*_env, *callback, jni::Make<jni::String>(*_env, newPath));
pathChangeCallback.reset();
});
fileSource->setResourceCachePath(newPath + DATABASE_FILE, pathChangeCallback->self());
}
void FileSource::resume(jni::JNIEnv&) {
if (!activationCounter) {
activationCounter = optional<int>(1) ;
return;
}
activationCounter.value()++;
if (activationCounter == 1) {
fileSource->resume();
}
}
void FileSource::pause(jni::JNIEnv&) {
if (activationCounter) {
activationCounter.value()--;
if (activationCounter == 0) {
fileSource->pause();
}
}
}
jni::jboolean FileSource::isResumed(jni::JNIEnv&) {
if (activationCounter) {
return (jboolean) (activationCounter > 0);
}
return (jboolean) false;
}
FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
return reinterpret_cast<FileSource *>(jFileSource.Get(env, field));
}
mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) {
FileSource* fileSource = FileSource::getNativePeer(env, jFileSource);
assert(fileSource != nullptr);
return fileSource->resourceOptions.clone();
}
// FileSource::ResourcesCachePathChangeCallback //
void FileSource::ResourcesCachePathChangeCallback::onSuccess(jni::JNIEnv& env,
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
const jni::String& path) {
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onSuccess");
callback.Call(env, method, path);
}
void FileSource::ResourcesCachePathChangeCallback::onError(jni::JNIEnv& env,
const jni::Object<FileSource::ResourcesCachePathChangeCallback>& callback,
const jni::String& message) {
static auto& javaClass = jni::Class<FileSource::ResourcesCachePathChangeCallback>::Singleton(env);
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
callback.Call(env, method, message);
}
void FileSource::registerNative(jni::JNIEnv& env) {
// Ensure the classes are cached. If they're requested for the
// first time on a background thread, Android's class loader heuristics will fail.
// https://developer.android.com/training/articles/perf-jni#faq_FindClass
jni::Class<ResourceTransformCallback>::Singleton(env);
jni::Class<ResourcesCachePathChangeCallback>::Singleton(env);
static auto& javaClass = jni::Class<FileSource>::Singleton(env);
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
// Register the peer
jni::RegisterNativePeer<FileSource>(env,
javaClass,
"nativePtr",
jni::MakePeer<FileSource, const jni::String&, const jni::String&>,
"initialize",
"finalize",
METHOD(&FileSource::getAccessToken, "getAccessToken"),
METHOD(&FileSource::setAccessToken, "setAccessToken"),
METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"),
METHOD(&FileSource::setResourceTransform, "setResourceTransform"),
METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"),
METHOD(&FileSource::resume, "activate"),
METHOD(&FileSource::pause, "deactivate"),
METHOD(&FileSource::isResumed, "isActivated"));
}
// FileSource::ResourceTransformCallback //
std::string FileSource::ResourceTransformCallback::onURL(jni::JNIEnv& env, const jni::Object<FileSource::ResourceTransformCallback>& callback, int kind, std::string url_) {
static auto& javaClass = jni::Class<FileSource::ResourceTransformCallback>::Singleton(env);
static auto method = javaClass.GetMethod<jni::String (jni::jint, jni::String)>(env, "onURL");
return jni::Make<std::string>(env,
callback.Call(env, method, kind,
jni::Make<jni::String>(env, url_)));
}
} // namespace android
} // namespace mbgl

View File

@@ -1,81 +0,0 @@
#pragma once
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/resource_options.hpp>
#include "asset_manager.hpp"
#include <jni/jni.hpp>
namespace mbgl {
template <typename T> class Actor;
class ResourceTransform;
using mbgl::PathChangeCallback;
namespace android {
/**
* Peer class for the Android FileSource holder. Ensures that a single DefaultFileSource is used
*/
class FileSource {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource"; };
struct ResourceTransformCallback {
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourceTransformCallback"; }
static std::string onURL(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&, int, std::string);
};
struct ResourcesCachePathChangeCallback {
static constexpr auto Name() { return "com/mapbox/mapboxsdk/storage/FileSource$ResourcesCachePathChangeCallback";}
static void onSuccess(jni::JNIEnv&,
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
const jni::String&);
static void onError(jni::JNIEnv&,
const jni::Object<FileSource::ResourcesCachePathChangeCallback>&,
const jni::String&);
};
FileSource(jni::JNIEnv&, const jni::String&, const jni::String&);
~FileSource();
jni::Local<jni::String> getAccessToken(jni::JNIEnv&);
void setAccessToken(jni::JNIEnv&, const jni::String&);
void setAPIBaseUrl(jni::JNIEnv&, const jni::String&);
void setResourceTransform(jni::JNIEnv&, const jni::Object<FileSource::ResourceTransformCallback>&);
void setResourceCachePath(jni::JNIEnv&, const jni::String&, const jni::Object<FileSource::ResourcesCachePathChangeCallback>&);
void resume(jni::JNIEnv&);
void pause(jni::JNIEnv&);
jni::jboolean isResumed(jni::JNIEnv&);
static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object<FileSource>&);
static mbgl::ResourceOptions getSharedResourceOptions(jni::JNIEnv&, const jni::Object<FileSource>&);
static void registerNative(jni::JNIEnv&);
private:
const std::string DATABASE_FILE = "/mbgl-offline.db";
optional<int> activationCounter;
mbgl::ResourceOptions resourceOptions;
std::unique_ptr<Actor<ResourceTransform>> resourceTransform;
std::unique_ptr<Actor<PathChangeCallback>> pathChangeCallback;
std::shared_ptr<mbgl::DefaultFileSource> fileSource;
};
} // namespace android
} // namespace mbgl

View File

@@ -1,79 +0,0 @@
#include "feature.hpp"
#include "geometry.hpp"
#include "../gson/json_object.hpp"
#include <mbgl/util/string.hpp>
namespace mbgl {
namespace android {
namespace geojson {
using namespace gson;
mbgl::Feature Feature::convert(jni::JNIEnv& env, const jni::Object<Feature>& jFeature) {
static auto& javaClass = jni::Class<Feature>::Singleton(env);
static auto id = javaClass.GetMethod<jni::String ()>(env, "id");
static auto geometry = javaClass.GetMethod<jni::Object<Geometry> ()>(env, "geometry");
static auto properties = javaClass.GetMethod<jni::Object<gson::JsonObject> ()>(env, "properties");
auto jId = jFeature.Call(env, id);
using mbid = mapbox::feature::identifier;
return mbgl::Feature {
Geometry::convert(env, jFeature.Call(env, geometry)),
JsonObject::convert(env, jFeature.Call(env, properties)),
jId ? mbid { jni::Make<std::string>(env, jId) } : mbid { mapbox::feature::null_value }
};
}
/**
* Turn feature identifier into std::string
*/
class FeatureIdVisitor {
public:
template<class T>
std::string operator()(const T& i) const {
return util::toString(i);
}
std::string operator()(const std::string& i) const {
return i;
}
std::string operator()(const std::nullptr_t&) const {
return {};
}
std::string operator()(const mapbox::feature::null_value_t&) const {
return {};
}
};
jni::Local<jni::Object<Feature>> convertFeature(jni::JNIEnv& env, const mbgl::Feature& value) {
static auto& javaClass = jni::Class<Feature>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<Feature> (jni::Object<Geometry>, jni::Object<JsonObject>, jni::String)>(env, "fromGeometry");
return javaClass.Call(env, method,
Geometry::New(env, value.geometry),
JsonObject::New(env, value.properties),
jni::Make<jni::String>(env, value.id.is<mbgl::NullValue>() ? std::string {} : value.id.match(FeatureIdVisitor())));
}
jni::Local<jni::Array<jni::Object<Feature>>> Feature::convert(jni::JNIEnv& env, const std::vector<mbgl::Feature>& value) {
auto features = jni::Array<jni::Object<Feature>>::New(env, value.size());
for (size_t i = 0; i < value.size(); i = i + 1) {
features.Set(env, i, convertFeature(env, value.at(i)));
}
return features;
}
void Feature::registerNative(jni::JNIEnv& env) {
jni::Class<Feature>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,23 +0,0 @@
#pragma once
#include <mbgl/util/feature.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class Feature {
public:
static constexpr auto Name() { return "com/mapbox/geojson/Feature"; };
static mbgl::Feature convert(jni::JNIEnv&, const jni::Object<Feature>&);
static jni::Local<jni::Array<jni::Object<Feature>>> convert(jni::JNIEnv&, const std::vector<mbgl::Feature>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,37 +0,0 @@
#include "feature_collection.hpp"
#include "feature.hpp"
namespace mbgl {
namespace android {
namespace geojson {
mbgl::FeatureCollection FeatureCollection::convert(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) {
auto collection = mbgl::FeatureCollection();
if (jCollection) {
auto jFeatureList = FeatureCollection::features(env, jCollection);
auto jFeatures = java::util::List::toArray<Feature>(env, jFeatureList);
auto size = size_t(jFeatures.Length(env));
collection.reserve(size);
for (size_t i = 0; i < size; i++) {
collection.push_back(Feature::convert(env, jFeatures.Get(env, i)));
}
}
return collection;
}
jni::Local<jni::Object<java::util::List>> FeatureCollection::features(jni::JNIEnv& env, const jni::Object<FeatureCollection>& jCollection) {
static auto& javaClass = jni::Class<FeatureCollection>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "features");
return jCollection.Call(env, method);
}
void FeatureCollection::registerNative(jni::JNIEnv& env) {
jni::Class<FeatureCollection>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,26 +0,0 @@
#pragma once
#include "../java/util.hpp"
#include <mbgl/util/geojson.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class FeatureCollection {
public:
static constexpr auto Name() { return "com/mapbox/geojson/FeatureCollection"; };
static mbgl::FeatureCollection convert(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
static jni::Local<jni::Object<java::util::List>> features(jni::JNIEnv&, const jni::Object<FeatureCollection>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,97 +0,0 @@
#include "geometry.hpp"
#include "point.hpp"
#include "multi_point.hpp"
#include "line_string.hpp"
#include "multi_line_string.hpp"
#include "polygon.hpp"
#include "multi_polygon.hpp"
#include "geometry_collection.hpp"
#include <string>
namespace mbgl {
namespace android {
namespace geojson {
/**
* Turn mapbox::geometry type into Java GeoJson Geometries
*/
class GeometryEvaluator {
public:
jni::JNIEnv& env;
jni::Local<jni::Object<Geometry>> operator()(const mbgl::EmptyGeometry &) const {
// FIXME: mapbox-java needs to have its own Empty type.
return GeometryCollection::New(env, {});
}
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Point<double> &geometry) const {
return Point::New(env, geometry);
}
jni::Local<jni::Object<Geometry>> operator()(const mbgl::LineString<double> &geometry) const {
return LineString::New(env, geometry);
}
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiLineString<double> &geometry) const {
return MultiLineString::New(env, geometry);
}
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPoint<double> &geometry) const {
return MultiPoint::New(env, geometry);
}
jni::Local<jni::Object<Geometry>> operator()(const mbgl::Polygon<double> &geometry) const {
return Polygon::New(env, geometry);
}
jni::Local<jni::Object<Geometry>> operator()(const mbgl::MultiPolygon<double> &geometry) const {
return MultiPolygon::New(env, geometry);
}
jni::Local<jni::Object<Geometry>> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const {
return GeometryCollection::New(env, geometry);
}
};
jni::Local<jni::Object<Geometry>> Geometry::New(jni::JNIEnv& env, mbgl::Geometry<double> geometry) {
GeometryEvaluator evaluator { env } ;
return mbgl::Geometry<double>::visit(geometry, evaluator);
}
mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) {
auto type = Geometry::getType(env, jGeometry);
if (type == Point::Type()) {
return { Point::convert(env, jni::Cast(env, jni::Class<Point>::Singleton(env), jGeometry)) };
} else if (type == MultiPoint::Type()) {
return { MultiPoint::convert(env, jni::Cast(env, jni::Class<MultiPoint>::Singleton(env), jGeometry)) };
} else if (type == LineString::Type()) {
return { LineString::convert(env, jni::Cast(env, jni::Class<LineString>::Singleton(env), jGeometry)) };
} else if (type == MultiLineString::Type()) {
return { MultiLineString::convert(env, jni::Cast(env, jni::Class<MultiLineString>::Singleton(env), jGeometry)) };
} else if (type == Polygon::Type()) {
return { Polygon::convert(env, jni::Cast(env, jni::Class<Polygon>::Singleton(env), jGeometry)) };
} else if (type == MultiPolygon::Type()) {
return { MultiPolygon::convert(env, jni::Cast(env, jni::Class<MultiPolygon>::Singleton(env), jGeometry)) };
} else if (type == GeometryCollection::Type()) {
return { GeometryCollection::convert(env, jni::Cast(env, jni::Class<GeometryCollection>::Singleton(env), jGeometry)) };
}
throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type);
}
std::string Geometry::getType(jni::JNIEnv &env, const jni::Object<Geometry>& jGeometry) {
static auto& javaClass = jni::Class<Geometry>::Singleton(env);
static auto method = javaClass.GetMethod<jni::String ()>(env, "type");
return jni::Make<std::string>(env, jGeometry.Call(env, method));
}
void Geometry::registerNative(jni::JNIEnv &env) {
jni::Class<Geometry>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,28 +0,0 @@
#pragma once
#include <mbgl/util/geometry.hpp>
#include "../java/util.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class Geometry {
public:
static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; };
static jni::Local<jni::Object<Geometry>> New(jni::JNIEnv&, mbgl::Geometry<double>);
static mbgl::Geometry<double> convert(jni::JNIEnv&, const jni::Object<Geometry>&);
static std::string getType(jni::JNIEnv&, const jni::Object<Geometry>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,47 +0,0 @@
#include "geometry_collection.hpp"
#include "../java/util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
jni::Local<jni::Object<GeometryCollection>> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) {
// Create an array of geometries
auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size());
for (size_t i = 0; i < collection.size(); i++) {
jarray.Set(env, i, Geometry::New(env, collection.at(i)));
}
// create the GeometryCollection
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection> (jni::Object<java::util::List>)>(env, "fromGeometries");
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
}
mapbox::geometry::geometry_collection<double> GeometryCollection::convert(jni::JNIEnv &env, const jni::Object<GeometryCollection>& jCollection) {
// Get geometries
static auto& javaClass = jni::Class<GeometryCollection>::Singleton(env);
static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "geometries");
// Turn into array
auto jarray = java::util::List::toArray<Geometry>(env, jCollection.Call(env, getGeometries));
// Convert each geometry
mapbox::geometry::geometry_collection<double> collection{};
auto size = jarray.Length(env);
for (jni::jsize i = 0; i < size; i++) {
collection.push_back(Geometry::convert(env, jarray.Get(env, i)));
}
return collection;
}
void GeometryCollection::registerNative(jni::JNIEnv &env) {
jni::Class<GeometryCollection>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,26 +0,0 @@
#pragma once
#include "geometry.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class GeometryCollection {
public:
using SuperTag = Geometry;
static constexpr auto Name() { return "com/mapbox/geojson/GeometryCollection"; };
static constexpr auto Type() { return "GeometryCollection"; };
static jni::Local<jni::Object<GeometryCollection>> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection<double>&);
static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, const jni::Object<GeometryCollection>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,55 +0,0 @@
#include "line_string.hpp"
#include "point.hpp"
#include "util.hpp"
#include "../java/util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
jni::Local<jni::Object<LineString>> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) {
static auto& javaClass = jni::Class<LineString>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(env, "fromLngLats");
return javaClass.Call(env, method, asPointsList(env, lineString));
}
mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) {
mapbox::geojson::line_string lineString;
if (jLineString) {
lineString = LineString::convert(env, LineString::coordinates(env, jLineString));
}
return lineString;
}
mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<Point>*/>& jPointList) {
mapbox::geojson::line_string lineString;
if (jPointList) {
auto jPointArray = java::util::List::toArray<Point>(env, jPointList);
auto size = jPointArray.Length(env);
lineString.reserve(size);
for (std::size_t i = 0; i < size; i++) {
lineString.push_back(Point::convert(env, jPointArray.Get(env, i)));
}
}
return lineString;
}
jni::Local<jni::Object<java::util::List>> LineString::coordinates(jni::JNIEnv &env, const jni::Object<LineString>& jLineString) {
static auto& javaClass = jni::Class<LineString>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
return jLineString.Call(env, method);
}
void LineString::registerNative(jni::JNIEnv &env) {
jni::Class<LineString>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,36 +0,0 @@
#pragma once
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/noncopyable.hpp>
#include "geometry.hpp"
#include "../java/util.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class LineString {
public:
using SuperTag = Geometry;
static constexpr auto Name() { return "com/mapbox/geojson/LineString"; };
static constexpr auto Type() { return "LineString"; };
static jni::Local<jni::Object<LineString>> New(jni::JNIEnv&, const mbgl::LineString<double>&);
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<LineString>&);
static mapbox::geojson::line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<Point>*/>&);
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<LineString>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,56 +0,0 @@
#include "multi_line_string.hpp"
#include "line_string.hpp"
#include "util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
jni::Local<jni::Object<MultiLineString>> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) {
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString> (jni::Object<java::util::List>)>(env, "fromLngLats");
return javaClass.Call(env, method, asPointsListsList(env, multiLineString));
}
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<MultiLineString>& jMultiLineString) {
mapbox::geojson::multi_line_string multiLineString;
if (jMultiLineString) {
multiLineString = MultiLineString::convert(env, MultiLineString::coordinates(env, jMultiLineString));
}
return multiLineString;
}
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) {
mapbox::geojson::multi_line_string multiLineString;
if (jPointListsList) {
auto jPositionListsArray = java::util::List::toArray<java::util::List>(env, jPointListsList);
auto size = jPositionListsArray.Length(env);
multiLineString.reserve(size);
for (std::size_t i = 0; i < size; i++) {
multiLineString.push_back(LineString::convert(env, jPositionListsArray.Get(env, i)));
}
}
return multiLineString;
}
jni::Local<jni::Object<java::util::List>> MultiLineString::coordinates(jni::JNIEnv &env, const jni::Object<MultiLineString>& jLineString) {
static auto& javaClass = jni::Class<MultiLineString>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
return jLineString.Call(env, method);
}
void MultiLineString::registerNative(jni::JNIEnv &env) {
jni::Class<MultiLineString>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,34 +0,0 @@
#pragma once
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/noncopyable.hpp>
#include "../java/util.hpp"
#include "geometry.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class MultiLineString {
public:
using SuperTag = Geometry;
static constexpr auto Name() { return "com/mapbox/geojson/MultiLineString"; };
static constexpr auto Type() { return "MultiLineString"; };
static jni::Local<jni::Object<MultiLineString>> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&);
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<MultiLineString>&);
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&);
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiLineString>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,41 +0,0 @@
#include "multi_point.hpp"
#include "line_string.hpp"
#include "util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
jni::Local<jni::Object<MultiPoint>> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) {
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(env, "fromLngLats");
return javaClass.Call(env, method, asPointsList(env, multiPoint));
}
mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) {
mapbox::geojson::multi_point multiPoint;
if (jMultiPoint) {
multiPoint = convertExplicit<mapbox::geojson::multi_point>(
LineString::convert(env, MultiPoint::coordinates(env, jMultiPoint)));
}
return multiPoint;
}
jni::Local<jni::Object<java::util::List>> MultiPoint::coordinates(jni::JNIEnv& env, const jni::Object<MultiPoint>& jMultiPoint) {
static auto& javaClass = jni::Class<MultiPoint>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
return jMultiPoint.Call(env, method);
}
void MultiPoint::registerNative(jni::JNIEnv &env) {
jni::Class<MultiPoint>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,33 +0,0 @@
#pragma once
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/noncopyable.hpp>
#include "geometry.hpp"
#include "../java/util.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class MultiPoint {
public:
using SuperTag = Geometry;
static constexpr auto Name() { return "com/mapbox/geojson/MultiPoint"; };
static constexpr auto Type() { return "MultiPoint"; };
static jni::Local<jni::Object<MultiPoint>> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&);
static mapbox::geojson::multi_point convert(jni::JNIEnv&, const jni::Object<MultiPoint>&);
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPoint>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,53 +0,0 @@
#include "multi_polygon.hpp"
#include "polygon.hpp"
#include "util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
jni::Local<jni::Object<MultiPolygon>> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) {
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size());
for (size_t i = 0; i < multiPolygon.size(); i++) {
jarray.Set(env, i, asPointsListsList(env, multiPolygon.at(i)));
}
return javaClass.Call(env, method, java::util::Arrays::asList(env, jarray));
}
mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jMultiPolygon) {
mapbox::geojson::multi_polygon multiPolygon;
if (jMultiPolygon) {
auto jPointListsListList = MultiPolygon::coordinates(env, jMultiPolygon);
auto jPointListsListArray = java::util::List::toArray<java::util::List>(env, jPointListsListList);
auto size = jPointListsListArray.Length(env);
multiPolygon.reserve(size);
for (size_t i = 0; i < size; i++) {
multiPolygon.push_back(Polygon::convert(env, jPointListsListArray.Get(env, i)));
}
}
return multiPolygon;
}
jni::Local<jni::Object<java::util::List>> MultiPolygon::coordinates(jni::JNIEnv& env, const jni::Object<MultiPolygon>& jPolygon) {
static auto& javaClass = jni::Class<MultiPolygon>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
return jPolygon.Call(env, method);
}
void MultiPolygon::registerNative(jni::JNIEnv &env) {
jni::Class<MultiPolygon>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,32 +0,0 @@
#pragma once
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/noncopyable.hpp>
#include "../java/util.hpp"
#include "geometry.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class MultiPolygon {
public:
using SuperTag = Geometry;
static constexpr auto Name() { return "com/mapbox/geojson/MultiPolygon"; };
static constexpr auto Type() { return "MultiPolygon"; };
static jni::Local<jni::Object<MultiPolygon>> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&);
static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<MultiPolygon>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,34 +0,0 @@
#include "point.hpp"
namespace mbgl {
namespace android {
namespace geojson {
jni::Local<jni::Object<Point>> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) {
static auto& javaClass = jni::Class<Point>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<Point> (jni::jdouble, jni::jdouble)>(env, "fromLngLat");
return javaClass.Call(env, method, point.x, point.y);
}
mbgl::Point<double> Point::convert(jni::JNIEnv &env, const jni::Object<Point>& jPoint) {
static auto& javaClass = jni::Class<Point>::Singleton(env);
static auto longitude = javaClass.GetMethod<jni::jdouble ()>(env, "longitude");
static auto latitude = javaClass.GetMethod<jni::jdouble ()>(env, "latitude");
if (!jPoint) {
return {};
}
return {
jPoint.Call(env, longitude),
jPoint.Call(env, latitude)
};
}
void Point::registerNative(jni::JNIEnv &env) {
jni::Class<Point>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,27 +0,0 @@
#pragma once
#include <mbgl/util/geometry.hpp>
#include "geometry.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class Point {
public:
using SuperTag = Geometry;
static constexpr auto Name() { return "com/mapbox/geojson/Point"; };
static constexpr auto Type() { return "Point"; };
static jni::Local<jni::Object<Point>> New(jni::JNIEnv&, const mbgl::Point<double>&);
static mbgl::Point<double> convert(jni::JNIEnv&, const jni::Object<Point>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,55 +0,0 @@
#include "polygon.hpp"
#include "multi_line_string.hpp"
#include "util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
jni::Local<jni::Object<Polygon>> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) {
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<Polygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
return javaClass.Call(env, method, asPointsListsList(env, polygon));
}
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) {
mapbox::geojson::polygon polygon;
if (jPolygon) {
polygon = Polygon::convert(env, Polygon::coordinates(env, jPolygon));
}
return polygon;
}
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, const jni::Object<java::util::List/*<java::util::List<Point>>*/>& jPointListsList) {
mapbox::geojson::polygon polygon;
if (jPointListsList) {
auto multiLine = MultiLineString::convert(env, jPointListsList);
polygon.reserve(multiLine.size());
for (auto&& line : multiLine) {
polygon.emplace_back(convertExplicit<mapbox::geojson::linear_ring>(std::move(line)));
}
}
return polygon;
}
jni::Local<jni::Object<java::util::List>> Polygon::coordinates(jni::JNIEnv &env, const jni::Object<Polygon>& jPolygon) {
static auto& javaClass = jni::Class<Polygon>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "coordinates");
return jPolygon.Call(env, method);
}
void Polygon::registerNative(jni::JNIEnv &env) {
jni::Class<Polygon>::Singleton(env);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,35 +0,0 @@
#pragma once
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/noncopyable.hpp>
#include "geometry.hpp"
#include "../java/util.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
class Polygon {
public:
using SuperTag = Geometry;
static constexpr auto Name() { return "com/mapbox/geojson/Polygon"; };
static constexpr auto Type() { return "Polygon"; };
static jni::Local<jni::Object<Polygon>> New(jni::JNIEnv&, const mbgl::Polygon<double>&);
static mapbox::geojson::polygon convert(jni::JNIEnv &, const jni::Object<Polygon>&);
static mapbox::geojson::polygon convert(jni::JNIEnv&, const jni::Object<java::util::List/*<java::util::List<Point>>*/>&);
static jni::Local<jni::Object<java::util::List>> coordinates(jni::JNIEnv&, const jni::Object<Polygon>&);
static void registerNative(jni::JNIEnv &);
};
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,52 +0,0 @@
#pragma once
#include "point.hpp"
#include <type_traits>
namespace mbgl {
namespace android {
namespace geojson {
// Clang 3.8 fails to implicitly convert matching types, so we'll have to do it explicitly.
template <typename To, typename From>
To convertExplicit(From&& src) {
static_assert(std::is_same<typename std::decay_t<From>::container_type,
typename To::container_type>::value,
"container types do not match");
static_assert(std::is_rvalue_reference<From&&>::value,
"argument must be rvalue reference");
return *reinterpret_cast<std::add_pointer_t<To>>(&src);
}
/**
* Geometry -> List<Point>
*/
template <class T>
static jni::Local<jni::Object<java::util::List>> asPointsList(jni::JNIEnv& env, const T& pointsList) {
auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size());
for (jni::jsize i = 0; i < pointsList.size(); i++) {
jarray.Set(env, i, Point::New(env, pointsList.at(i)));
}
return java::util::Arrays::asList(env, jarray);
}
/**
* Geometry -> List<List<Point>>
*/
template <class SHAPE>
static jni::Local<jni::Object<java::util::List>> asPointsListsList(JNIEnv& env, const SHAPE& value) {
auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size());
for (size_t i = 0; i < value.size(); i++) {
jarray.Set(env, i, asPointsList(env, value[i]));
}
return java::util::Arrays::asList(env, jarray);
}
} // namespace geojson
} // namespace android
} // namespace mbgl

View File

@@ -1,29 +0,0 @@
#include "lat_lng.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<LatLng>> LatLng::New(jni::JNIEnv& env, const mbgl::LatLng& latLng) {
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
static auto constructor = javaClass.GetConstructor<double, double>(env);
return javaClass.New(env, constructor, latLng.latitude(), latLng.longitude());
}
mbgl::Point<double> LatLng::getGeometry(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
static auto& javaClass = jni::Class<LatLng>::Singleton(env);
static auto latitudeField = javaClass.GetField<jni::jdouble>(env, "latitude");
static auto longitudeField = javaClass.GetField<jni::jdouble>(env, "longitude");
return mbgl::Point<double>(latLng.Get(env, longitudeField), latLng.Get(env, latitudeField));
}
mbgl::LatLng LatLng::getLatLng(jni::JNIEnv& env, const jni::Object<LatLng>& latLng) {
auto point = LatLng::getGeometry(env, latLng);
return mbgl::LatLng(point.y, point.x);
}
void LatLng::registerNative(jni::JNIEnv& env) {
jni::Class<LatLng>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,29 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geometry.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class LatLng : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLng"; };
static jni::Local<jni::Object<LatLng>> New(jni::JNIEnv&, const mbgl::LatLng&);
static mbgl::Point<double> getGeometry(jni::JNIEnv&, const jni::Object<LatLng>&);
static mbgl::LatLng getLatLng(jni::JNIEnv&, const jni::Object<LatLng>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,30 +0,0 @@
#include "lat_lng_bounds.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<LatLngBounds>> LatLngBounds::New(jni::JNIEnv& env, mbgl::LatLngBounds bounds) {
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
static auto constructor = javaClass.GetConstructor<double, double, double, double>(env);
return javaClass.New(env, constructor, bounds.north(), bounds.east(), bounds.south(), bounds.west());
}
mbgl::LatLngBounds LatLngBounds::getLatLngBounds(jni::JNIEnv& env, const jni::Object<LatLngBounds>& bounds) {
static auto& javaClass = jni::Class<LatLngBounds>::Singleton(env);
static auto swLatField = javaClass.GetField<jni::jdouble>(env, "latitudeSouth");
static auto swLonField = javaClass.GetField<jni::jdouble>(env, "longitudeWest");
static auto neLatField = javaClass.GetField<jni::jdouble>(env, "latitudeNorth");
static auto neLonField = javaClass.GetField<jni::jdouble>(env, "longitudeEast");
mbgl::LatLng sw = { bounds.Get(env, swLatField), bounds.Get(env, swLonField) };
mbgl::LatLng ne = { bounds.Get(env, neLatField), bounds.Get(env, neLonField) };
return mbgl::LatLngBounds::hull(sw, ne);
}
void LatLngBounds::registerNative(jni::JNIEnv& env) {
jni::Class<LatLngBounds>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,26 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geometry.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class LatLngBounds : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngBounds"; };
static jni::Local<jni::Object<LatLngBounds>> New(jni::JNIEnv&, mbgl::LatLngBounds);
static mbgl::LatLngBounds getLatLngBounds(jni::JNIEnv&, const jni::Object<LatLngBounds>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,37 +0,0 @@
#include "lat_lng_quad.hpp"
#include "lat_lng.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<LatLngQuad>> LatLngQuad::New(jni::JNIEnv& env, std::array<mbgl::LatLng, 4> coordinates) {
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
static auto quadConstructor = javaClass.GetConstructor<jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>, jni::Object<LatLng>>(env);
return javaClass.New(env, quadConstructor,
LatLng::New(env, coordinates[0]),
LatLng::New(env, coordinates[1]),
LatLng::New(env, coordinates[2]),
LatLng::New(env, coordinates[3]));
}
std::array<mbgl::LatLng, 4> LatLngQuad::getLatLngArray(jni::JNIEnv& env, const jni::Object<LatLngQuad>& quad) {
static auto& javaClass = jni::Class<LatLngQuad>::Singleton(env);
static auto topLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "topLeft");
static auto topRightField = javaClass.GetField <jni::Object<LatLng>>(env, "topRight");
static auto bottomRightField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomRight");
static auto bottomLeftField = javaClass.GetField <jni::Object<LatLng>>(env, "bottomLeft");
return std::array < mbgl::LatLng, 4 > {{
LatLng::getLatLng(env, quad.Get(env, topLeftField)),
LatLng::getLatLng(env, quad.Get(env, topRightField)),
LatLng::getLatLng(env, quad.Get(env, bottomRightField)),
LatLng::getLatLng(env, quad.Get(env, bottomLeftField))
}};
}
void LatLngQuad::registerNative(jni::JNIEnv& env) {
jni::Class<LatLngQuad>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,27 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/geometry.hpp>
#include <jni/jni.hpp>
#include <array>
namespace mbgl {
namespace android {
class LatLngQuad : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/LatLngQuad"; };
static jni::Local<jni::Object<LatLngQuad>> New(jni::JNIEnv&, std::array<mbgl::LatLng, 4>);
static std::array<mbgl::LatLng, 4> getLatLngArray(jni::JNIEnv&, const jni::Object<LatLngQuad>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,17 +0,0 @@
#include "projected_meters.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<ProjectedMeters>> ProjectedMeters::New(jni::JNIEnv& env, double northing, double easting) {
static auto& javaClass = jni::Class<ProjectedMeters>::Singleton(env);
static auto constructor = javaClass.GetConstructor<double, double>(env);
return javaClass.New(env, constructor, northing, easting);
}
void ProjectedMeters::registerNative(jni::JNIEnv& env) {
jni::Class<ProjectedMeters>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,21 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/geometry.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class ProjectedMeters : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/geometry/ProjectedMeters"; };
static jni::Local<jni::Object<ProjectedMeters>> New(jni::JNIEnv&, double, double);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,156 +0,0 @@
#include <mbgl/platform/gl_functions.hpp>
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
namespace mbgl {
namespace platform {
void (* const glActiveTexture)(GLenum) = ::glActiveTexture;
void (* const glAttachShader)(GLuint, GLuint) = ::glAttachShader;
void (* const glBindAttribLocation)(GLuint, GLuint, const GLchar *) = ::glBindAttribLocation;
void (* const glBindBuffer)(GLenum, GLuint) = ::glBindBuffer;
void (* const glBindFramebuffer)(GLenum, GLuint) = ::glBindFramebuffer;
void (* const glBindRenderbuffer)(GLenum, GLuint) = ::glBindRenderbuffer;
void (* const glBindTexture)(GLenum, GLuint) = ::glBindTexture;
void (* const glBlendColor)(GLfloat, GLfloat, GLfloat, GLfloat) = ::glBlendColor;
void (* const glBlendEquation)(GLenum) = ::glBlendEquation;
void (* const glBlendEquationSeparate)(GLenum, GLenum) = ::glBlendEquationSeparate;
void (* const glBlendFunc)(GLenum, GLenum) = ::glBlendFunc;
void (* const glBlendFuncSeparate)(GLenum, GLenum, GLenum, GLenum) = ::glBlendFuncSeparate;
void (* const glBufferData)(GLenum, GLsizeiptr, const void *, GLenum) = ::glBufferData;
void (* const glBufferSubData)(GLenum, GLintptr, GLsizeiptr, const void *) = ::glBufferSubData;
GLenum (* const glCheckFramebufferStatus)(GLenum) = ::glCheckFramebufferStatus;
void (* const glClear)(GLbitfield) = ::glClear;
void (* const glClearColor)(GLfloat, GLfloat, GLfloat, GLfloat) = ::glClearColor;
void (* const glClearDepthf)(GLfloat) = ::glClearDepthf;
void (* const glClearStencil)(GLint) = ::glClearStencil;
void (* const glColorMask)(GLboolean, GLboolean, GLboolean, GLboolean) = ::glColorMask;
void (* const glCompileShader)(GLuint) = ::glCompileShader;
void (* const glCompressedTexImage2D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *) = ::glCompressedTexImage2D;
void (* const glCompressedTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *) = ::glCompressedTexSubImage2D;
void (* const glCopyTexImage2D)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint) = ::glCopyTexImage2D;
void (* const glCopyTexSubImage2D)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei) = ::glCopyTexSubImage2D;
GLuint (* const glCreateProgram)() = ::glCreateProgram;
GLuint (* const glCreateShader)(GLenum) = ::glCreateShader;
void (* const glCullFace)(GLenum) = ::glCullFace;
void (* const glDeleteBuffers)(GLsizei, const GLuint *) = ::glDeleteBuffers;
void (* const glDeleteFramebuffers)(GLsizei, const GLuint *) = ::glDeleteFramebuffers;
void (* const glDeleteProgram)(GLuint) = ::glDeleteProgram;
void (* const glDeleteRenderbuffers)(GLsizei, const GLuint *) = ::glDeleteRenderbuffers;
void (* const glDeleteShader)(GLuint) = ::glDeleteShader;
void (* const glDeleteTextures)(GLsizei, const GLuint *) = ::glDeleteTextures;
void (* const glDepthFunc)(GLenum) = ::glDepthFunc;
void (* const glDepthMask)(GLboolean) = ::glDepthMask;
void (* const glDepthRangef)(GLfloat, GLfloat) = ::glDepthRangef;
void (* const glDetachShader)(GLuint, GLuint) = ::glDetachShader;
void (* const glDisable)(GLenum) = ::glDisable;
void (* const glDisableVertexAttribArray)(GLuint) = ::glDisableVertexAttribArray;
void (* const glDrawArrays)(GLenum, GLint, GLsizei) = ::glDrawArrays;
void (* const glDrawElements)(GLenum, GLsizei, GLenum, const void *) = ::glDrawElements;
void (* const glEnable)(GLenum) = ::glEnable;
void (* const glEnableVertexAttribArray)(GLuint) = ::glEnableVertexAttribArray;
void (* const glFinish)() = ::glFinish;
void (* const glFlush)() = ::glFlush;
void (* const glFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint) = ::glFramebufferRenderbuffer;
void (* const glFramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint, GLint) = ::glFramebufferTexture2D;
void (* const glFrontFace)(GLenum) = ::glFrontFace;
void (* const glGenBuffers)(GLsizei, GLuint *) = ::glGenBuffers;
void (* const glGenerateMipmap)(GLenum) = ::glGenerateMipmap;
void (* const glGenFramebuffers)(GLsizei, GLuint *) = ::glGenFramebuffers;
void (* const glGenRenderbuffers)(GLsizei, GLuint *) = ::glGenRenderbuffers;
void (* const glGenTextures)(GLsizei, GLuint *) = ::glGenTextures;
void (* const glGetActiveAttrib)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *) = ::glGetActiveAttrib;
void (* const glGetActiveUniform)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *) = ::glGetActiveUniform;
void (* const glGetAttachedShaders)(GLuint, GLsizei, GLsizei *, GLuint *) = ::glGetAttachedShaders;
GLint (* const glGetAttribLocation)(GLuint, const GLchar *) = ::glGetAttribLocation;
void (* const glGetBooleanv)(GLenum, GLboolean *) = ::glGetBooleanv;
void (* const glGetBufferParameteriv)(GLenum, GLenum, GLint *) = ::glGetBufferParameteriv;
GLenum (* const glGetError)() = ::glGetError;
void (* const glGetFloatv)(GLenum, GLfloat *) = ::glGetFloatv;
void (* const glGetFramebufferAttachmentParameteriv)(GLenum, GLenum, GLenum, GLint *) = ::glGetFramebufferAttachmentParameteriv;
void (* const glGetIntegerv)(GLenum, GLint *) = ::glGetIntegerv;
void (* const glGetProgramInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *) = ::glGetProgramInfoLog;
void (* const glGetProgramiv)(GLuint, GLenum, GLint *) = ::glGetProgramiv;
void (* const glGetRenderbufferParameteriv)(GLenum, GLenum, GLint *) = ::glGetRenderbufferParameteriv;
void (* const glGetShaderInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *) = ::glGetShaderInfoLog;
void (* const glGetShaderiv)(GLuint, GLenum, GLint *) = ::glGetShaderiv;
void (* const glGetShaderSource)(GLuint, GLsizei, GLsizei *, GLchar *) = ::glGetShaderSource;
const GLubyte *(*glGetString)(GLenum) = ::glGetString;
void (* const glGetTexParameterfv)(GLenum, GLenum, GLfloat *) = ::glGetTexParameterfv;
void (* const glGetTexParameteriv)(GLenum, GLenum, GLint *) = ::glGetTexParameteriv;
void (* const glGetUniformfv)(GLuint, GLint, GLfloat *) = ::glGetUniformfv;
void (* const glGetUniformiv)(GLuint, GLint, GLint *) = ::glGetUniformiv;
GLint (* const glGetUniformLocation)(GLuint, const GLchar *) = ::glGetUniformLocation;
void (* const glGetVertexAttribfv)(GLuint, GLenum, GLfloat *) = ::glGetVertexAttribfv;
void (* const glGetVertexAttribiv)(GLuint, GLenum, GLint *) = ::glGetVertexAttribiv;
void (* const glGetVertexAttribPointerv)(GLuint, GLenum, void **) = ::glGetVertexAttribPointerv;
void (* const glHint)(GLenum, GLenum) = ::glHint;
GLboolean (* const glIsBuffer)(GLuint) = ::glIsBuffer;
GLboolean (* const glIsEnabled)(GLenum) = ::glIsEnabled;
GLboolean (* const glIsFramebuffer)(GLuint) = ::glIsFramebuffer;
GLboolean (* const glIsProgram)(GLuint) = ::glIsProgram;
GLboolean (* const glIsRenderbuffer)(GLuint) = ::glIsRenderbuffer;
GLboolean (* const glIsShader)(GLuint) = ::glIsShader;
GLboolean (* const glIsTexture)(GLuint) = ::glIsTexture;
void (* const glLineWidth)(GLfloat) = ::glLineWidth;
void (* const glLinkProgram)(GLuint) = ::glLinkProgram;
void (* const glPixelStorei)(GLenum, GLint) = ::glPixelStorei;
void (* const glPolygonOffset)(GLfloat, GLfloat) = ::glPolygonOffset;
void (* const glReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, void *) = ::glReadPixels;
void (* const glRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei) = ::glRenderbufferStorage;
void (* const glSampleCoverage)(GLfloat, GLboolean) = ::glSampleCoverage;
void (* const glScissor)(GLint, GLint, GLsizei, GLsizei) = ::glScissor;
// Some implementations use `const GLchar* const*` and others `const GLchar**`.
void (* const glShaderSource)(GLuint, GLsizei, const GLchar * const*, const GLint *) = [](GLuint shader, GLsizei count, const GLchar * const * string, const GLint *length) {
::glShaderSource(shader, count, const_cast<const GLchar **>(string), length);
};
void (* const glStencilFunc)(GLenum, GLint, GLuint) = ::glStencilFunc;
void (* const glStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint) = ::glStencilFuncSeparate;
void (* const glStencilMask)(GLuint) = ::glStencilMask;
void (* const glStencilMaskSeparate)(GLenum, GLuint) = ::glStencilMaskSeparate;
void (* const glStencilOp)(GLenum, GLenum, GLenum) = ::glStencilOp;
void (* const glStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum) = ::glStencilOpSeparate;
void (* const glTexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *) = ::glTexImage2D;
void (* const glTexParameterf)(GLenum, GLenum, GLfloat) = ::glTexParameterf;
void (* const glTexParameterfv)(GLenum, GLenum, const GLfloat *) = ::glTexParameterfv;
void (* const glTexParameteri)(GLenum, GLenum, GLint) = ::glTexParameteri;
void (* const glTexParameteriv)(GLenum, GLenum, const GLint *) = ::glTexParameteriv;
void (* const glTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *) = ::glTexSubImage2D;
void (* const glUniform1f)(GLint, GLfloat) = ::glUniform1f;
void (* const glUniform1fv)(GLint, GLsizei, const GLfloat *) = ::glUniform1fv;
void (* const glUniform1i)(GLint, GLint) = ::glUniform1i;
void (* const glUniform1iv)(GLint, GLsizei, const GLint *) = ::glUniform1iv;
void (* const glUniform2f)(GLint, GLfloat, GLfloat) = ::glUniform2f;
void (* const glUniform2fv)(GLint, GLsizei, const GLfloat *) = ::glUniform2fv;
void (* const glUniform2i)(GLint, GLint, GLint) = ::glUniform2i;
void (* const glUniform2iv)(GLint, GLsizei, const GLint *) = ::glUniform2iv;
void (* const glUniform3f)(GLint, GLfloat, GLfloat, GLfloat) = ::glUniform3f;
void (* const glUniform3fv)(GLint, GLsizei, const GLfloat *) = ::glUniform3fv;
void (* const glUniform3i)(GLint, GLint, GLint, GLint) = ::glUniform3i;
void (* const glUniform3iv)(GLint, GLsizei, const GLint *) = ::glUniform3iv;
void (* const glUniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat) = ::glUniform4f;
void (* const glUniform4fv)(GLint, GLsizei, const GLfloat *) = ::glUniform4fv;
void (* const glUniform4i)(GLint, GLint, GLint, GLint, GLint) = ::glUniform4i;
void (* const glUniform4iv)(GLint, GLsizei, const GLint *) = ::glUniform4iv;
void (* const glUniformMatrix2fv)(GLint, GLsizei, GLboolean, const GLfloat *) = ::glUniformMatrix2fv;
void (* const glUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat *) = ::glUniformMatrix3fv;
void (* const glUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat *) = ::glUniformMatrix4fv;
void (* const glUseProgram)(GLuint) = ::glUseProgram;
void (* const glValidateProgram)(GLuint) = ::glValidateProgram;
void (* const glVertexAttrib1f)(GLuint, GLfloat) = ::glVertexAttrib1f;
void (* const glVertexAttrib1fv)(GLuint, const GLfloat *) = ::glVertexAttrib1fv;
void (* const glVertexAttrib2f)(GLuint, GLfloat, GLfloat) = ::glVertexAttrib2f;
void (* const glVertexAttrib2fv)(GLuint, const GLfloat *) = ::glVertexAttrib2fv;
void (* const glVertexAttrib3f)(GLuint, GLfloat, GLfloat, GLfloat) = ::glVertexAttrib3f;
void (* const glVertexAttrib3fv)(GLuint, const GLfloat *) = ::glVertexAttrib3fv;
void (* const glVertexAttrib4f)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat) = ::glVertexAttrib4f;
void (* const glVertexAttrib4fv)(GLuint, const GLfloat *) = ::glVertexAttrib4fv;
void (* const glVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *) = ::glVertexAttribPointer;
void (* const glViewport)(GLint, GLint, GLsizei, GLsizei) = ::glViewport;
} // namespace platform
} // namespace mbgl

View File

@@ -1,25 +0,0 @@
#include <mbgl/util/geo.hpp>
#include "pointf.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<PointF>> PointF::New(jni::JNIEnv& env, float x, float y) {
static auto& javaClass = jni::Class<PointF>::Singleton(env);
static auto constructor = javaClass.GetConstructor<float, float>(env);
return javaClass.New(env, constructor, x, y);
}
mbgl::ScreenCoordinate PointF::getScreenCoordinate(jni::JNIEnv& env, const jni::Object<PointF>& point) {
static auto& javaClass = jni::Class<PointF>::Singleton(env);
static auto xField = javaClass.GetField<jni::jfloat>(env, "x");
static auto yField = javaClass.GetField<jni::jfloat>(env, "y");
return mbgl::ScreenCoordinate{point.Get(env, xField), point.Get(env, yField)};
}
void PointF::registerNative(jni::JNIEnv& env) {
jni::Class<PointF>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,24 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class PointF : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "android/graphics/PointF"; };
static jni::Local<jni::Object<PointF>> New(jni::JNIEnv&, float, float);
static mbgl::ScreenCoordinate getScreenCoordinate(jni::JNIEnv&, const jni::Object<PointF>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,35 +0,0 @@
#include "rectf.hpp"
namespace mbgl {
namespace android {
float RectF::getLeft(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
static auto& javaClass = jni::Class<RectF>::Singleton(env);
static auto field = javaClass.GetField<float>(env, "left");
return rectf.Get(env, field);
}
float RectF::getTop(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
static auto& javaClass = jni::Class<RectF>::Singleton(env);
static auto field = javaClass.GetField<float>(env, "top");
return rectf.Get(env, field);
}
float RectF::getRight(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
static auto& javaClass = jni::Class<RectF>::Singleton(env);
static auto field = javaClass.GetField<float>(env, "right");
return rectf.Get(env, field);
}
float RectF::getBottom(jni::JNIEnv& env, const jni::Object<RectF>& rectf) {
static auto& javaClass = jni::Class<RectF>::Singleton(env);
static auto field = javaClass.GetField<float>(env, "bottom");
return rectf.Get(env, field);
}
void RectF::registerNative(jni::JNIEnv& env) {
jni::Class<RectF>::Singleton(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,28 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class RectF : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "android/graphics/RectF"; };
static float getLeft(jni::JNIEnv&, const jni::Object<RectF>&);
static float getTop(jni::JNIEnv&, const jni::Object<RectF>&);
static float getRight(jni::JNIEnv&, const jni::Object<RectF>&);
static float getBottom(jni::JNIEnv&, const jni::Object<RectF>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,50 +0,0 @@
#include "json_array.hpp"
#include "json_element.hpp"
namespace mbgl {
namespace android {
namespace gson {
jni::Local<jni::Object<JsonArray>> JsonArray::New(jni::JNIEnv& env, const std::vector<mbgl::Value>& values){
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
static auto constructor = javaClass.GetConstructor(env);
static auto addMethod = javaClass.GetMethod<void (jni::Object<JsonElement>)>(env, "add");
auto jsonArray = javaClass.New(env, constructor);
for (const auto &v : values) {
jsonArray.Call(env, addMethod, JsonElement::New(env, v));
}
return jsonArray;
}
std::vector<mbgl::Value> JsonArray::convert(jni::JNIEnv& env, const jni::Object<JsonArray>& jsonArray) {
std::vector<mbgl::Value> values;
if (jsonArray) {
static auto& javaClass = jni::Class<JsonArray>::Singleton(env);
static auto getMethod = javaClass.GetMethod<jni::Object<JsonElement> (jni::jint)>(env, "get");
static auto sizeMethod = javaClass.GetMethod<jni::jint ()>(env, "size");
int size = jsonArray.Call(env, sizeMethod);
values.reserve(uint(size));
for (int i = 0; i < size; i++) {
auto entry = jsonArray.Call(env, getMethod, i);
if (entry) {
values.push_back(JsonElement::convert(env, entry));
}
}
}
return values;
}
void JsonArray::registerNative(jni::JNIEnv& env) {
jni::Class<JsonArray>::Singleton(env);
}
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,24 +0,0 @@
#pragma once
#include "json_element.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace gson {
class JsonArray {
public:
using SuperTag = JsonElement;
static constexpr auto Name() { return "com/google/gson/JsonArray"; };
static jni::Local<jni::Object<JsonArray>> New(jni::JNIEnv&, const std::vector<mbgl::Value>&);
static std::vector<mbgl::Value> convert(JNIEnv&, const jni::Object<JsonArray>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,88 +0,0 @@
#include "json_element.hpp"
#include "json_array.hpp"
#include "json_object.hpp"
#include "json_primitive.hpp"
namespace mbgl {
namespace android {
namespace gson {
jni::Local<jni::Object<JsonElement>> JsonElement::New(jni::JNIEnv& env, const mbgl::Value& value) {
static auto& primitive = jni::Class<JsonPrimitive>::Singleton(env);
static auto stringConstructor = primitive.GetConstructor<jni::String>(env);
static auto numberConstructor = primitive.GetConstructor<jni::Number>(env);
static auto booleanConstructor = primitive.GetConstructor<jni::Boolean>(env);
return value.match(
[&] (const mbgl::NullValue&) {
return jni::Local<jni::Object<JsonElement>>();
},
[&] (const std::string& value) {
return primitive.New(env, stringConstructor, jni::Make<jni::String>(env, value));
},
[&] (const double value) {
return primitive.New(env, numberConstructor, jni::Box(env, value));
},
[&] (const int64_t value) {
return primitive.New(env, numberConstructor, jni::Box(env, value));
},
[&] (const uint64_t value) {
return primitive.New(env, numberConstructor, jni::Box(env, int64_t(value))); // TODO: should use BigInteger
},
[&] (const bool value) {
return primitive.New(env, booleanConstructor, jni::Box(env, value ? jni::jni_true : jni::jni_false));
},
[&] (const std::vector<mbgl::Value>& values) {
return JsonArray::New(env, values);
},
[&] (const mbgl::PropertyMap& values) {
return JsonObject::New(env, values);
}
);
}
mbgl::Value JsonElement::convert(jni::JNIEnv &env, const jni::Object<JsonElement>& jsonElement) {
if (!jsonElement) {
return mbgl::NullValue();
}
static auto& elementClass = jni::Class<JsonElement>::Singleton(env);
static auto isJsonObject = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonObject");
static auto isJsonArray = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonArray");
static auto isJsonPrimitive = elementClass.GetMethod<jni::jboolean ()>(env, "isJsonPrimitive");
static auto& primitiveClass = jni::Class<JsonPrimitive>::Singleton(env);
static auto isBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "isBoolean");
static auto isString = primitiveClass.GetMethod<jni::jboolean ()>(env, "isString");
static auto isNumber = primitiveClass.GetMethod<jni::jboolean ()>(env, "isNumber");
static auto getAsBoolean = primitiveClass.GetMethod<jni::jboolean ()>(env, "getAsBoolean");
static auto getAsString = primitiveClass.GetMethod<jni::String ()>(env, "getAsString");
static auto getAsDouble = primitiveClass.GetMethod<jni::jdouble ()>(env, "getAsDouble");
if (jsonElement.Call(env, isJsonPrimitive)) {
auto primitive = jni::Cast(env, primitiveClass, jsonElement);
if (primitive.Call(env, isBoolean)) {
return bool(primitive.Call(env, getAsBoolean));
} else if (primitive.Call(env, isNumber)) {
return primitive.Call(env, getAsDouble);
} else if (primitive.Call(env, isString)) {
return jni::Make<std::string>(env, primitive.Call(env, getAsString));
} else {
return mbgl::NullValue();
}
} else if (jsonElement.Call(env, isJsonObject)) {
return JsonObject::convert(env, jni::Cast(env, jni::Class<JsonObject>::Singleton(env), jsonElement));
} else if (jsonElement.Call(env, isJsonArray)) {
return JsonArray::convert(env, jni::Cast(env, jni::Class<JsonArray>::Singleton(env), jsonElement));
} else {
return mbgl::NullValue();
}
}
void JsonElement::registerNative(jni::JNIEnv &env) {
jni::Class<JsonElement>::Singleton(env);
}
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,24 +0,0 @@
#pragma once
#include <mbgl/util/feature.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace gson {
class JsonElement {
public:
using SuperTag = jni::ObjectTag;
static constexpr auto Name() { return "com/google/gson/JsonElement"; };
static jni::Local<jni::Object<JsonElement>> New(jni::JNIEnv&, const mbgl::Value&);
static mbgl::Value convert(JNIEnv&, const jni::Object<JsonElement>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,65 +0,0 @@
#include "json_object.hpp"
#include "json_element.hpp"
#include "../java/util.hpp"
namespace mbgl {
namespace android {
namespace gson {
jni::Local<jni::Object<JsonObject>> JsonObject::New(jni::JNIEnv& env, const mbgl::PropertyMap& values) {
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
static auto constructor = javaClass.GetConstructor(env);
static auto addMethod = javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add");
auto jsonObject = javaClass.New(env, constructor);
for (auto &item : values) {
jsonObject.Call(env, addMethod,
jni::Make<jni::String>(env, item.first),
JsonElement::New(env, item.second));
}
return jsonObject;
}
template <typename F> // void (jni::String, jni::Object<gson::JsonElement>)
static void iterateEntrySet(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject, F callback) {
// Get Set<Map.Entry<String, JsonElement>>
static auto& javaClass = jni::Class<JsonObject>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<java::util::Set> ()>(env, "entrySet");
auto entryArray = java::util::Set::toArray<java::util::Map::Entry>(env, jsonObject.Call(env, method));
size_t size = entryArray.Length(env);
for (size_t i = 0; i < size; i++) {
auto entry = entryArray.Get(env, i);
if (entry) {
callback(
java::util::Map::Entry::getKey<jni::StringTag>(env, entry),
java::util::Map::Entry::getValue<gson::JsonElement>(env, entry));
}
}
}
mbgl::PropertyMap JsonObject::convert(jni::JNIEnv& env, const jni::Object<JsonObject>& jsonObject) {
mbgl::PropertyMap map;
if (jsonObject) {
iterateEntrySet(env, jsonObject, [&map, &env](const jni::String& jId, const jni::Object<gson::JsonElement>& jsonElement) {
map[jni::Make<std::string>(env, jId)] = JsonElement::convert(env, jsonElement);
});
}
return map;
}
void JsonObject::registerNative(jni::JNIEnv &env) {
jni::Class<JsonObject>::Singleton(env);
}
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,24 +0,0 @@
#pragma once
#include "json_element.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace gson {
class JsonObject {
public:
using SuperTag = JsonElement;
static constexpr auto Name() { return "com/google/gson/JsonObject"; };
static jni::Local<jni::Object<JsonObject>> New(jni::JNIEnv&, const mbgl::PropertyMap&);
static mbgl::PropertyMap convert(JNIEnv&, const jni::Object<JsonObject>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,13 +0,0 @@
#include "json_primitive.hpp"
namespace mbgl {
namespace android {
namespace gson {
void JsonPrimitive::registerNative(jni::JNIEnv &env) {
jni::Class<JsonPrimitive>::Singleton(env);
}
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,21 +0,0 @@
#pragma once
#include "json_element.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace gson {
class JsonPrimitive {
public:
using SuperTag = JsonElement;
static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; };
static void registerNative(jni::JNIEnv&);
};
} // namespace gson
} // namespace android
} // namespace mbgl

View File

@@ -1,194 +0,0 @@
#include <mbgl/storage/http_file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/http_header.hpp>
#include <jni/jni.hpp>
#include "attach_env.hpp"
namespace mbgl {
class HTTPFileSource::Impl {
public:
android::UniqueEnv env { android::AttachEnv() };
};
class HTTPRequest : public AsyncRequest {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/http/NativeHttpRequest"; };
HTTPRequest(jni::JNIEnv&, const Resource&, FileSource::Callback);
~HTTPRequest();
void onFailure(jni::JNIEnv&, int type, const jni::String& message);
void onResponse(jni::JNIEnv&, int code,
const jni::String& etag, const jni::String& modified,
const jni::String& cacheControl, const jni::String& expires,
const jni::String& retryAfter, const jni::String& xRateLimitReset,
const jni::Array<jni::jbyte>& body);
jni::Global<jni::Object<HTTPRequest>> javaRequest;
private:
Resource resource;
FileSource::Callback callback;
Response response;
util::AsyncTask async { [this] {
// Calling `callback` may result in deleting `this`. Copy data to temporaries first.
auto callback_ = callback;
auto response_ = response;
callback_(response_);
} };
static const int connectionError = 0;
static const int temporaryError = 1;
static const int permanentError = 2;
};
namespace android {
void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
jni::RegisterNativePeer<HTTPRequest>(env, javaClass, "nativePtr",
METHOD(&HTTPRequest::onFailure, "nativeOnFailure"),
METHOD(&HTTPRequest::onResponse, "nativeOnResponse"));
}
} // namespace android
HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource::Callback callback_)
: resource(resource_),
callback(callback_) {
std::string etagStr;
std::string modifiedStr;
if (resource.priorEtag) {
etagStr = *resource.priorEtag;
} else if (resource.priorModified) {
modifiedStr = util::rfc1123(*resource.priorModified);
}
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 10);
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(env);
static auto constructor =
javaClass.GetConstructor<jni::jlong, jni::String, jni::String, jni::String, jni::jboolean>(env);
javaRequest = jni::NewGlobal(env,
javaClass.New(env, constructor,
reinterpret_cast<jlong>(this),
jni::Make<jni::String>(env, resource.url),
jni::Make<jni::String>(env, etagStr),
jni::Make<jni::String>(env, modifiedStr),
(jboolean) (resource_.usage == Resource::Usage::Offline)
)
);
}
HTTPRequest::~HTTPRequest() {
android::UniqueEnv env = android::AttachEnv();
static auto& javaClass = jni::Class<HTTPRequest>::Singleton(*env);
static auto cancel = javaClass.GetMethod<void ()>(*env, "cancel");
javaRequest.Call(*env, cancel);
}
void HTTPRequest::onResponse(jni::JNIEnv& env, int code,
const jni::String& etag, const jni::String& modified,
const jni::String& cacheControl, const jni::String& expires,
const jni::String& jRetryAfter, const jni::String& jXRateLimitReset,
const jni::Array<jni::jbyte>& body) {
using Error = Response::Error;
if (etag) {
response.etag = jni::Make<std::string>(env, etag);
}
if (modified) {
response.modified = util::parseTimestamp(jni::Make<std::string>(env, modified).c_str());
}
if (cacheControl) {
const auto cc = http::CacheControl::parse(jni::Make<std::string>(env, cacheControl).c_str());
response.expires = cc.toTimePoint();
response.mustRevalidate = cc.mustRevalidate;
}
if (expires) {
response.expires = util::parseTimestamp(jni::Make<std::string>(env, expires).c_str());
}
if (code == 200) {
if (body) {
auto data = std::make_shared<std::string>(body.Length(env), char());
jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
response.data = data;
} else {
response.data = std::make_shared<std::string>();
}
} else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) {
response.noContent = true;
} else if (code == 304) {
response.notModified = true;
} else if (code == 404) {
response.error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
} else if (code == 429) {
optional<std::string> retryAfter;
optional<std::string> xRateLimitReset;
if (jRetryAfter) {
retryAfter = jni::Make<std::string>(env, jRetryAfter);
}
if (jXRateLimitReset) {
xRateLimitReset = jni::Make<std::string>(env, jXRateLimitReset);
}
response.error = std::make_unique<Error>(Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset));
} else if (code >= 500 && code < 600) {
response.error = std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } + util::toString(code));
} else {
response.error = std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } + util::toString(code));
}
async.send();
}
void HTTPRequest::onFailure(jni::JNIEnv& env, int type, const jni::String& message) {
std::string messageStr = jni::Make<std::string>(env, message);
using Error = Response::Error;
switch (type) {
case connectionError:
response.error = std::make_unique<Error>(Error::Reason::Connection, messageStr);
break;
case temporaryError:
response.error = std::make_unique<Error>(Error::Reason::Server, messageStr);
break;
default:
response.error = std::make_unique<Error>(Error::Reason::Other, messageStr);
}
async.send();
}
HTTPFileSource::HTTPFileSource()
: impl(std::make_unique<Impl>()) {
}
HTTPFileSource::~HTTPFileSource() = default;
std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, Callback callback) {
return std::make_unique<HTTPRequest>(*impl->env, resource, callback);
}
} // namespace mbgl

View File

@@ -1,194 +0,0 @@
#include <mbgl/i18n/collator.hpp>
#include <mbgl/text/language_tag.hpp>
#include <jni/jni.hpp>
#include "../attach_env.hpp"
#include "collator_jni.hpp"
namespace mbgl {
namespace android {
void Collator::registerNative(jni::JNIEnv& env) {
jni::Class<Collator>::Singleton(env);
}
jni::Local<jni::Object<Collator>> Collator::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
static auto& javaClass = jni::Class<Collator>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<Collator> (jni::Object<Locale>)>(env, "getInstance");
return javaClass.Call(env, method, locale);
}
void Collator::setStrength(jni::JNIEnv& env, const jni::Object<Collator>& collator, jni::jint strength) {
static auto& javaClass = jni::Class<Collator>::Singleton(env);
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setStrength");
collator.Call(env, method, strength);
}
jni::jint Collator::compare(jni::JNIEnv& env, const jni::Object<Collator>& collator, const jni::String& lhs, const jni::String& rhs) {
static auto& javaClass = jni::Class<Collator>::Singleton(env);
static auto method = javaClass.GetMethod<jni::jint (jni::String, jni::String)>(env, "compare");
return collator.Call(env, method, lhs, rhs);
}
void StringUtils::registerNative(jni::JNIEnv& env) {
jni::Class<StringUtils>::Singleton(env);
}
jni::Local<jni::String> StringUtils::unaccent(jni::JNIEnv& env, const jni::String& value) {
static auto& javaClass = jni::Class<StringUtils>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::String (jni::String)>(env, "unaccent");
return javaClass.Call(env, method, value);
}
void Locale::registerNative(jni::JNIEnv& env) {
jni::Class<Locale>::Singleton(env);
}
/*
We would prefer to use for/toLanguageTag, but they're only available in API level 21+
jni::Object<Locale> Locale::forLanguageTag(jni::JNIEnv& env, jni::String languageTag) {
using Signature = jni::Object<Locale>(jni::String);
auto method = javaClass.GetStaticMethod<Signature>(env, "forLanguageTag");
return javaClass.Call(env, method, languageTag);
}
jni::String Locale::toLanguageTag(jni::JNIEnv& env, jni::Object<Locale> locale) {
using Signature = jni::String();
auto static method = javaClass.GetMethod<Signature>(env, "toLanguageTag");
return locale.Call(env, method);
}
*/
jni::Local<jni::String> Locale::getLanguage(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
static auto& javaClass = jni::Class<Locale>::Singleton(env);
static auto method = javaClass.GetMethod<jni::String ()>(env, "getLanguage");
return locale.Call(env, method);
}
jni::Local<jni::String> Locale::getCountry(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
static auto& javaClass = jni::Class<Locale>::Singleton(env);
static auto method = javaClass.GetMethod<jni::String ()>(env, "getCountry");
return locale.Call(env, method);
}
jni::Local<jni::Object<Locale>> Locale::getDefault(jni::JNIEnv& env) {
static auto& javaClass = jni::Class<Locale>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<Locale> ()>(env, "getDefault");
return javaClass.Call(env, method);
}
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language) {
static auto& javaClass = jni::Class<Locale>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jni::String>(env);
return javaClass.New(env, constructor, language);
}
jni::Local<jni::Object<Locale>> Locale::New(jni::JNIEnv& env, const jni::String& language, const jni::String& region) {
static auto& javaClass = jni::Class<Locale>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jni::String, jni::String>(env);
return javaClass.New(env, constructor, language, region);
}
} // namespace android
namespace platform {
class Collator::Impl {
public:
Impl(bool caseSensitive_, bool diacriticSensitive_, optional<std::string> locale_)
: caseSensitive(caseSensitive_)
, diacriticSensitive(diacriticSensitive_)
, env(android::AttachEnv())
{
LanguageTag languageTag = locale_ ? LanguageTag::fromBCP47(*locale_) : LanguageTag();
if (!languageTag.language) {
locale = jni::NewGlobal(*env,
android::Locale::getDefault(*env));
} else if (!languageTag.region) {
locale = jni::NewGlobal(*env,
android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
} else {
locale = jni::NewGlobal(*env,
android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language),
jni::Make<jni::String>(*env, *languageTag.region)));
}
collator = jni::NewGlobal(*env, android::Collator::getInstance(*env, locale));
if (!diacriticSensitive && !caseSensitive) {
android::Collator::setStrength(*env, collator, 0 /*PRIMARY*/);
} else if (diacriticSensitive && !caseSensitive) {
android::Collator::setStrength(*env, collator, 1 /*SECONDARY*/);
} else if (caseSensitive) {
// If we're case-sensitive and diacritic-sensitive, we use a case-sensitive collator
// and a fallback implementation of diacritic-insensitivity.
android::Collator::setStrength(*env, collator, 2 /*TERTIARY*/);
}
}
bool operator==(const Impl& other) const {
return caseSensitive == other.caseSensitive &&
diacriticSensitive == other.diacriticSensitive &&
resolvedLocale() == other.resolvedLocale();
}
int compare(const std::string& lhs, const std::string& rhs) const {
bool useUnaccent = !diacriticSensitive && caseSensitive;
// java.text.Collator doesn't support a diacritic-insensitive/case-sensitive collation
// order, so we have to compromise here. We use Android's case-sensitive Collator
// against strings that have been "unaccented" using non-locale-aware nunicode logic.
// Because of the difference in locale-awareness, this means turning on case-sensitivity
// can _potentially_ change compare results for strings that don't actually have any case
// differences.
jni::Local<jni::String> jlhs = useUnaccent
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, lhs))
: jni::Make<jni::String>(*env, lhs);
jni::Local<jni::String> jrhs = useUnaccent
? android::StringUtils::unaccent(*env, jni::Make<jni::String>(*env, rhs))
: jni::Make<jni::String>(*env, rhs);
jni::jint result = android::Collator::compare(*env, collator, jlhs, jrhs);
return result;
}
std::string resolvedLocale() const {
std::string language = jni::Make<std::string>(*env, android::Locale::getLanguage(*env, locale));
std::string region = jni::Make<std::string>(*env, android::Locale::getCountry(*env, locale));
optional<std::string> resultLanguage;
if (!language.empty()) resultLanguage = language;
optional<std::string> resultRegion;
if (!region.empty()) resultRegion = region;
return LanguageTag(resultLanguage, {}, resultRegion).toBCP47();
}
private:
bool caseSensitive;
bool diacriticSensitive;
android::UniqueEnv env;
jni::Global<jni::Object<android::Collator>> collator;
jni::Global<jni::Object<android::Locale>> locale;
};
Collator::Collator(bool caseSensitive, bool diacriticSensitive, optional<std::string> locale_)
: impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, std::move(locale_)))
{}
bool Collator::operator==(const Collator& other) const {
return *impl == *(other.impl);
}
int Collator::compare(const std::string& lhs, const std::string& rhs) const {
return impl->compare(lhs, rhs);
}
std::string Collator::resolvedLocale() const {
return impl->resolvedLocale();
}
} // namespace platform
} // namespace mbgl

View File

@@ -1,62 +0,0 @@
#pragma once
#include <jni/jni.hpp>
/*
android::Collator and android::Locale are
the JNI wrappers of
java/text/Collator and java/util/Locale
mbgl::Collator is the portable interface
Both implementations are in collator.cpp
*/
namespace mbgl {
namespace android {
class Locale {
public:
static constexpr auto Name() { return "java/util/Locale"; };
/* Requires API level 21+ in order to support script/variant
static jni::Object<Locale> forLanguageTag(jni::JNIEnv&, jni::String);
static jni::String toLanguageTag(jni::JNIEnv&, jni::Object<Locale>);
*/
static jni::Local<jni::Object<Locale>> getDefault(jni::JNIEnv&);
static jni::Local<jni::String> getLanguage(jni::JNIEnv&, const jni::Object<Locale>&);
static jni::Local<jni::String> getCountry(jni::JNIEnv&, const jni::Object<Locale>&);
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&);
static jni::Local<jni::Object<Locale>> New(jni::JNIEnv&, const jni::String&, const jni::String&);
static void registerNative(jni::JNIEnv&);
};
class Collator {
public:
static constexpr auto Name() { return "java/text/Collator"; };
static jni::Local<jni::Object<Collator>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
static void setStrength(jni::JNIEnv&, const jni::Object<Collator>&, jni::jint);
static jni::jint compare(jni::JNIEnv&, const jni::Object<Collator>&, const jni::String&, const jni::String&);
static void registerNative(jni::JNIEnv&);
};
class StringUtils {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/utils/StringUtils"; };
static jni::Local<jni::String> unaccent(jni::JNIEnv&, const jni::String&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,80 +0,0 @@
#include <mbgl/i18n/number_format.hpp>
#include <mbgl/text/language_tag.hpp>
#include <jni/jni.hpp>
#include "../attach_env.hpp"
#include "number_format_jni.hpp"
namespace mbgl {
namespace android {
void NumberFormat::registerNative(jni::JNIEnv& env) {
jni::Class<NumberFormat>::Singleton(env);
}
jni::Local<jni::Object<NumberFormat>> NumberFormat::getInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat> (jni::Object<Locale>)>(env, "getInstance");
return javaClass.Call(env, method, locale);
}
jni::Local<jni::Object<NumberFormat>> NumberFormat::getCurrencyInstance(jni::JNIEnv& env, const jni::Object<Locale>& locale) {
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
static auto method = javaClass.GetStaticMethod<jni::Object<NumberFormat> (jni::Object<Locale>)>(env, "getCurrencyInstance");
return javaClass.Call(env, method, locale);
}
jni::Local<jni::String> NumberFormat::format(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jdouble number) {
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
static auto method = javaClass.GetMethod<jni::String (jni::jdouble)>(env, "format");
return nf.Call(env, method, number);
}
void NumberFormat::setMinimumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setMinimumFractionDigits");
return nf.Call(env, method, value);
}
void NumberFormat::setMaximumFractionDigits(jni::JNIEnv& env, const jni::Object<NumberFormat>& nf, jni::jint value) {
static auto& javaClass = jni::Class<NumberFormat>::Singleton(env);
static auto method = javaClass.GetMethod<void (jni::jint)>(env, "setMaximumFractionDigits");
return nf.Call(env, method, value);
}
} // namespace android
namespace platform {
std::string formatNumber(double number, const std::string& localeId, const std::string& currency,
uint8_t minFractionDigits, uint8_t maxFractionDigits) {
auto env{ android::AttachEnv() };
jni::Global<jni::Object<android::Locale>> locale;
LanguageTag languageTag = !localeId.empty() ? LanguageTag::fromBCP47(localeId) : LanguageTag();
if (!languageTag.language) {
locale = jni::NewGlobal(*env, android::Locale::getDefault(*env));
} else if (!languageTag.region) {
locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language)));
} else {
locale = jni::NewGlobal(*env, android::Locale::New(*env, jni::Make<jni::String>(*env, *languageTag.language),
jni::Make<jni::String>(*env, *languageTag.region)));
}
jni::Global<jni::Object<android::NumberFormat>> formatter;
if (currency.empty()) {
formatter = jni::NewGlobal(*env, android::NumberFormat::getInstance(*env, locale));
android::NumberFormat::setMinimumFractionDigits(*env, formatter, static_cast<jni::jint>(minFractionDigits));
android::NumberFormat::setMaximumFractionDigits(*env, formatter, static_cast<jni::jint>(maxFractionDigits));
} else {
formatter = jni::NewGlobal(*env, android::NumberFormat::getCurrencyInstance(*env, locale));
}
auto result = android::NumberFormat::format(*env, formatter, static_cast<jni::jdouble>(number));
return jni::Make<std::string>(*env, result);
}
} // namespace platform
} // namespace mbgl

View File

@@ -1,29 +0,0 @@
#pragma once
#include <jni/jni.hpp>
#include "collator_jni.hpp"
/*
android::NumberFormat is the JNI wrapper
of java/text/NumberFormat.
*/
namespace mbgl {
namespace android {
class NumberFormat {
public:
static constexpr auto Name() { return "java/text/NumberFormat"; };
static jni::Local<jni::Object<NumberFormat>> getInstance(jni::JNIEnv&, const jni::Object<Locale>&);
static jni::Local<jni::Object<NumberFormat>> getCurrencyInstance(jni::JNIEnv&, const jni::Object<Locale>&);
static jni::Local<jni::String> format(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jdouble);
static void setMinimumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
static void setMaximumFractionDigits(jni::JNIEnv&, const jni::Object<NumberFormat>&, jni::jint);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,21 +0,0 @@
#include <mbgl/util/image.hpp>
#include <mbgl/util/string.hpp>
#include <string>
#include "attach_env.hpp"
#include "bitmap_factory.hpp"
namespace mbgl {
PremultipliedImage decodeImage(const std::string& string) {
auto env{ android::AttachEnv() };
auto array = jni::Array<jni::jbyte>::New(*env, string.size());
jni::SetArrayRegion(*env, *array, 0, string.size(),
reinterpret_cast<const signed char*>(string.data()));
return android::Bitmap::GetImage(*env, android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size()));
}
} // namespace mbgl

View File

@@ -1,19 +0,0 @@
#include "util.hpp"
namespace mbgl {
namespace android {
namespace java {
namespace util {
void registerNative(jni::JNIEnv& env) {
jni::Class<Arrays>::Singleton(env);
jni::Class<List>::Singleton(env);
jni::Class<Set>::Singleton(env);
jni::Class<Map>::Singleton(env);
jni::Class<Map::Entry>::Singleton(env);
}
} // namespace util
} // namespace java
} // namespace android
} // namespace mbgl

View File

@@ -1,81 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace java {
namespace util {
class List : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "java/util/List"; };
template<class T>
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<List>& list) {
static auto& javaClass = jni::Class<List>::Singleton(env);
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray");
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
};
};
class Arrays : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "java/util/Arrays"; };
template <class T>
static jni::Local<jni::Object<List>> asList(jni::JNIEnv& env, const jni::Array<jni::Object<T>>& array) {
static auto& javaClass = jni::Class<Arrays>::Singleton(env);
static auto asList = javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList");
auto typeErasedArray = jni::Local<jni::Array<jni::Object<>>>(env, jni::NewLocal(env, array).release());
return javaClass.Call(env, asList, typeErasedArray);
}
};
class Set : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "java/util/Set"; };
template<class T>
static jni::Local<jni::Array<jni::Object<T>>> toArray(jni::JNIEnv& env, const jni::Object<Set>& list) {
static auto& javaClass = jni::Class<Set>::Singleton(env);
static auto toArray = javaClass.GetMethod<jni::Array<jni::Object<>> ()>(env, "toArray");
return jni::Local<jni::Array<jni::Object<T>>>(env, list.Call(env, toArray).release());
};
};
class Map : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "java/util/Map"; };
class Entry : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "java/util/Map$Entry"; };
template <class T>
static jni::Local<jni::Object<T>> getKey(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getKey");
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
}
template <class T>
static jni::Local<jni::Object<T>> getValue(jni::JNIEnv& env, const jni::Object<Entry>& entry) {
static auto& javaClass = jni::Class<Map::Entry>::Singleton(env);
static auto method = javaClass.GetMethod<jni::Object<> ()>(env, "getValue");
return jni::Cast(env, jni::Class<T>::Singleton(env), entry.Call(env, method));
}
};
};
void registerNative(jni::JNIEnv&);
} // namespace util
} // namespace java
} // namespace android
} // namespace mbgl

View File

@@ -1,49 +0,0 @@
#include "java_types.hpp"
namespace mbgl {
namespace android {
namespace java {
jni::jclass* ObjectArray::jclass;
jni::jclass* String::jclass;
jni::jclass* Boolean::jclass;
jni::jmethodID* Boolean::booleanValueMethodId;
jni::jclass* Number::jclass;
jni::jmethodID* Number::floatValueMethodId;
jni::jmethodID* Number::doubleValueMethodId;
jni::jmethodID* Number::longValueMethodId;
jni::jclass* Map::jclass;
jni::jmethodID* Map::getMethodId;
jni::jmethodID* Map::keySetMethodId;
jni::jclass* Set::jclass;
jni::jmethodID* Set::toArrayMethodId;
void registerNatives(JNIEnv& env) {
ObjectArray::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "[Ljava/lang/Object;")).release();
String::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release();
Boolean::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release();
Boolean::booleanValueMethodId = &jni::GetMethodID(env, *Boolean::jclass, "booleanValue", "()Z");
Number::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Number")).release();
Number::floatValueMethodId = &jni::GetMethodID(env, *Number::jclass, "floatValue", "()F");
Number::doubleValueMethodId = &jni::GetMethodID(env, *Number::jclass, "doubleValue", "()D");
Number::longValueMethodId = &jni::GetMethodID(env, *Number::jclass, "longValue", "()J");
Map::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Map")).release();
Map::getMethodId = &jni::GetMethodID(env, *Map::jclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
Map::keySetMethodId = &jni::GetMethodID(env, *Map::jclass, "keySet", "()Ljava/util/Set;");
Set::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Set")).release();
Set::toArrayMethodId = &jni::GetMethodID(env, *Set::jclass, "toArray", "()[Ljava/lang/Object;");
}
}
}
}

View File

@@ -1,43 +0,0 @@
#pragma once
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace java {
struct ObjectArray {
static jni::jclass* jclass;
};
struct String {
static jni::jclass* jclass;
};
struct Boolean {
static jni::jclass* jclass;
static jni::jmethodID* booleanValueMethodId;
};
struct Number {
static jni::jclass* jclass;
static jni::jmethodID* floatValueMethodId;
static jni::jmethodID* doubleValueMethodId;
static jni::jmethodID* longValueMethodId;
};
struct Map {
static jni::jclass* jclass;
static jni::jmethodID* getMethodId;
static jni::jmethodID* keySetMethodId;
};
struct Set {
static jni::jclass* jclass;
static jni::jmethodID* toArrayMethodId;
};
void registerNatives(JNIEnv&);
}
}
}

View File

@@ -1,54 +0,0 @@
#include "jni.hpp"
#include <mbgl/util/logging.hpp>
namespace mbgl {
namespace android {
JavaVM* theJVM;
//TODO: remove
bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName) {
assert(vm != nullptr);
assert(env != nullptr);
JavaVMAttachArgs args = {JNI_VERSION_1_2, threadName.c_str(), NULL};
jint ret;
*env = nullptr;
bool detach = false;
ret = vm->GetEnv(reinterpret_cast<void **>(env), JNI_VERSION_1_6);
if (ret != JNI_OK) {
if (ret != JNI_EDETACHED) {
mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret);
throw std::runtime_error("GetEnv() failed");
} else {
ret = vm->AttachCurrentThread(env, &args);
if (ret != JNI_OK) {
mbgl::Log::Error(mbgl::Event::JNI, "AttachCurrentThread() failed with %i", ret);
throw std::runtime_error("AttachCurrentThread() failed");
}
detach = true;
}
}
return detach;
}
//TODO: remove
void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach) {
if (detach) {
assert(vm != nullptr);
assert(env != nullptr);
jint ret;
if ((ret = vm->DetachCurrentThread()) != JNI_OK) {
mbgl::Log::Error(mbgl::Event::JNI, "DetachCurrentThread() failed with %i", ret);
throw std::runtime_error("DetachCurrentThread() failed");
}
}
*env = nullptr;
}
} // namespace android
} // namespace mbgl

View File

@@ -1,24 +0,0 @@
#pragma once
#include <mbgl/util/util.hpp>
#include <string>
#include <jni/jni.hpp>
typedef struct _jmethodID* jmethodID;
typedef struct _JavaVM JavaVM;
typedef struct _JNIEnv JNIEnv;
namespace mbgl {
namespace android {
extern JavaVM* theJVM;
extern std::string cachePath;
extern std::string dataPath;
bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName);
void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach);
} // namespace android
} // namespace mbgl

View File

@@ -1,168 +0,0 @@
#include "jni_native.hpp"
#include "annotation/marker.hpp"
#include "annotation/polygon.hpp"
#include "annotation/polyline.hpp"
#include "bitmap.hpp"
#include "bitmap_factory.hpp"
#include "connectivity_listener.hpp"
#include "conversion/collection.hpp"
#include "conversion/conversion.hpp"
#include "file_source.hpp"
#include "geojson/feature.hpp"
#include "geojson/feature_collection.hpp"
#include "geojson/geometry.hpp"
#include "geojson/geometry_collection.hpp"
#include "geojson/line_string.hpp"
#include "geojson/multi_line_string.hpp"
#include "geojson/multi_point.hpp"
#include "geojson/multi_polygon.hpp"
#include "geojson/point.hpp"
#include "geojson/polygon.hpp"
#include "geometry/lat_lng.hpp"
#include "geometry/lat_lng_bounds.hpp"
#include "geometry/lat_lng_quad.hpp"
#include "geometry/projected_meters.hpp"
#include "graphics/pointf.hpp"
#include "graphics/rectf.hpp"
#include "gson/json_array.hpp"
#include "gson/json_element.hpp"
#include "gson/json_object.hpp"
#include "gson/json_primitive.hpp"
#include "java_types.hpp"
#include "map_renderer.hpp"
#include "map_renderer_runnable.hpp"
#include "mapbox.hpp"
#include "native_map_view.hpp"
#ifndef MBGL_MODULE_OFFLINE_DISABLE
#include "offline/offline_manager.hpp"
#include "offline/offline_region.hpp"
#include "offline/offline_region_definition.hpp"
#include "offline/offline_region_error.hpp"
#include "offline/offline_region_status.hpp"
#endif
#include "style/transition_options.hpp"
#include "style/layers/layer_manager.hpp"
#include "style/sources/source.hpp"
#include "style/light.hpp"
#include "style/formatted.hpp"
#include "style/formatted_section.hpp"
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
#include "snapshotter/map_snapshotter.hpp"
#include "snapshotter/map_snapshot.hpp"
#endif
#include "i18n/collator_jni.hpp"
#include "i18n/number_format_jni.hpp"
#include "logger.hpp"
#include "text/local_glyph_rasterizer_jni.hpp"
namespace mbgl {
namespace android {
void RegisterNativeHTTPRequest(JNIEnv&);
void registerNatives(JavaVM *vm) {
theJVM = vm;
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
// For the DefaultFileSource
static mbgl::util::RunLoop mainRunLoop;
FileSource::registerNative(env);
// Basic types
java::registerNatives(env);
java::util::registerNative(env);
PointF::registerNative(env);
RectF::registerNative(env);
// GeoJSON
geojson::Feature::registerNative(env);
geojson::FeatureCollection::registerNative(env);
geojson::Geometry::registerNative(env);
geojson::GeometryCollection::registerNative(env);
geojson::LineString::registerNative(env);
geojson::MultiLineString::registerNative(env);
geojson::MultiPoint::registerNative(env);
geojson::MultiPolygon::registerNative(env);
geojson::Point::registerNative(env);
geojson::Polygon::registerNative(env);
// Geometry
LatLng::registerNative(env);
LatLngBounds::registerNative(env);
LatLngQuad::registerNative(env);
ProjectedMeters::registerNative(env);
// GSon
gson::JsonArray::registerNative(env);
gson::JsonElement::registerNative(env);
gson::JsonObject::registerNative(env);
gson::JsonPrimitive::registerNative(env);
//Annotation
Marker::registerNative(env);
Polygon::registerNative(env);
Polyline::registerNative(env);
// Map
MapRenderer::registerNative(env);
MapRendererRunnable::registerNative(env);
NativeMapView::registerNative(env);
// Http
RegisterNativeHTTPRequest(env);
// Bitmap
Bitmap::registerNative(env);
BitmapFactory::registerNative(env);
// Style
TransitionOptions::registerNative(env);
LayerManagerAndroid::get()->registerNative(env);
Source::registerNative(env);
Light::registerNative(env);
Position::registerNative(env);
Formatted::registerNative(env);
FormattedSection::registerNative(env);
// Map
CameraPosition::registerNative(env);
Image::registerNative(env);
// Connectivity
ConnectivityListener::registerNative(env);
// Offline
#ifndef MBGL_MODULE_OFFLINE_DISABLE
OfflineManager::registerNative(env);
OfflineRegion::registerNative(env);
OfflineRegionDefinition::registerNative(env);
OfflineTilePyramidRegionDefinition::registerNative(env);
OfflineGeometryRegionDefinition::registerNative(env);
OfflineRegionError::registerNative(env);
OfflineRegionStatus::registerNative(env);
#endif
// Snapshotter
#ifndef MBGL_MODULE_SNAPSHOT_DISABLE
MapSnapshotter::registerNative(env);
MapSnapshot::registerNative(env);
#endif
// text
LocalGlyphRasterizer::registerNative(env);
Locale::registerNative(env);
Collator::registerNative(env);
StringUtils::registerNative(env);
NumberFormat::registerNative(env);
// Logger
Logger::registerNative(env);
// AssetManager
Mapbox::registerNative(env);
}
} // namespace android
} // namespace mbgl

View File

@@ -1,13 +0,0 @@
#pragma once
#include <mbgl/util/util.hpp>
#include "jni.hpp"
namespace mbgl {
namespace android {
MBGL_EXPORT void registerNatives(JavaVM* vm);
} // namespace android
} // namespace mbgl

View File

@@ -1,34 +0,0 @@
#include "logger.hpp"
#include "java_types.hpp"
namespace mbgl {
namespace android {
void Logger::registerNative(jni::JNIEnv& env) {
jni::Class<Logger>::Singleton(env);
}
void Logger::log(jni::JNIEnv& env, EventSeverity severity, const std::string &msg) {
static auto& _class = jni::Class<Logger>::Singleton(env);
auto tag = jni::Make<jni::String>(env, "Mbgl");
auto message = jni::Make<jni::String>(env, msg);
using Signature = void(jni::String, jni::String);
if (severity == EventSeverity::Debug) {
auto static debug = _class.GetStaticMethod<Signature>(env, "d");
_class.Call(env, debug, tag, message);
} else if (severity == EventSeverity::Info) {
auto static info = _class.GetStaticMethod<Signature>(env, "i");
_class.Call(env, info, tag, message);
} else if(severity == EventSeverity::Warning) {
auto static warning = _class.GetStaticMethod<Signature>(env, "w");
_class.Call(env, warning, tag, message);
} else {
auto static error = _class.GetStaticMethod<Signature>(env, "e");
_class.Call(env, error, tag, message);
}
}
} // namespace android
} // namespace mbgl

View File

@@ -1,21 +0,0 @@
#pragma once
#include <mbgl/util/event.hpp>
#include <jni/jni.hpp>
#include "bitmap.hpp"
namespace mbgl {
namespace android {
class Logger {
public:
static constexpr auto Name() {
return "com/mapbox/mapboxsdk/log/Logger";
};
static void registerNative(jni::JNIEnv&);
static void log(jni::JNIEnv&, EventSeverity severity, const std::string &msg);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,13 +0,0 @@
#include <mbgl/util/logging.hpp>
#include "logger.hpp"
#include "attach_env.hpp"
namespace mbgl {
void Log::platformRecord(EventSeverity severity, const std::string &msg) {
auto env{ android::AttachEnv() };
android::Logger::log(*env, severity, msg);
}
}

View File

@@ -1,9 +0,0 @@
#include "jni.hpp"
#include "jni_native.hpp"
#include <jni/jni.hpp>
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *) {
assert(vm != nullptr);
mbgl::android::registerNatives(vm);
return JNI_VERSION_1_6;
}

View File

@@ -1,69 +0,0 @@
#include "camera_position.hpp"
#include "../geometry/lat_lng.hpp"
namespace mbgl {
namespace android {
jni::Local<jni::Object<CameraPosition>> CameraPosition::New(jni::JNIEnv &env, mbgl::CameraOptions options, float pixelRatio) {
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jni::Object<LatLng>, double, double, double, jni::Array<jni::jdouble>>(env);
// wrap LatLng values coming from core
auto center = options.center.value();
center.wrap();
// convert bearing, measured in radians counterclockwise from true north.
// Wrapped to [−π rad, π rad). Android binding from 0 to 360 degrees
double bearing_degrees = options.bearing.value_or(0);
while (bearing_degrees > 360) {
bearing_degrees -= 360;
}
while (bearing_degrees < 0) {
bearing_degrees += 360;
}
// convert tilt, core ranges from [0 rad, 1,0472 rad], android ranges from 0 to 60
double tilt_degrees = options.pitch.value_or(0);
std::vector<jdouble> paddingVect;
auto insets = options.padding.value_or(EdgeInsets {0, 0, 0, 0});
auto padding = jni::Array<jni::jdouble>::New(env, 4);
paddingVect.push_back(insets.left() * pixelRatio);
paddingVect.push_back(insets.top() * pixelRatio);
paddingVect.push_back(insets.right() * pixelRatio);
paddingVect.push_back(insets.bottom() * pixelRatio);
padding.SetRegion<std::vector<jni::jdouble>>(env, 0, paddingVect);
return javaClass.New(env, constructor, LatLng::New(env, center), options.zoom.value_or(0), tilt_degrees, bearing_degrees, padding);
}
mbgl::CameraOptions CameraPosition::getCameraOptions(jni::JNIEnv& env, const jni::Object<CameraPosition>& position, float pixelRatio) {
static auto& javaClass = jni::Class<CameraPosition>::Singleton(env);
static auto bearing = javaClass.GetField<jni::jdouble>(env, "bearing");
static auto target = javaClass.GetField<jni::Object<LatLng>>(env, "target");
static auto tilt = javaClass.GetField<jni::jdouble>(env, "tilt");
static auto zoom = javaClass.GetField<jni::jdouble>(env, "zoom");
static auto paddingField = javaClass.GetField<jni::Array<jni::jdouble>>(env, "padding");
auto padding = position.Get(env, paddingField);
auto center = LatLng::getLatLng(env, position.Get(env, target));
return mbgl::CameraOptions{center,
padding && padding.Length(env) == 4 ? EdgeInsets{padding.Get(env, 1) * pixelRatio,
padding.Get(env, 0) * pixelRatio,
padding.Get(env, 3) * pixelRatio,
padding.Get(env, 2) * pixelRatio}
: (EdgeInsets){},
{},
position.Get(env, zoom),
position.Get(env, bearing),
position.Get(env, tilt)};
}
void CameraPosition::registerNative(jni::JNIEnv &env) {
jni::Class<CameraPosition>::Singleton(env);
}
} // namespace android
} // namespace mb

View File

@@ -1,23 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/map/camera.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class CameraPosition : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/camera/CameraPosition"; };
static jni::Local<jni::Object<CameraPosition>> New(jni::JNIEnv&, mbgl::CameraOptions, float pixelRatio);
static mbgl::CameraOptions getCameraOptions(jni::JNIEnv&, const jni::Object<CameraPosition>&, float pixelRatio);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,41 +0,0 @@
#include <mbgl/style/image.hpp>
#include <mbgl/util/exception.hpp>
#include "image.hpp"
namespace mbgl {
namespace android {
mbgl::style::Image Image::getImage(jni::JNIEnv& env, const jni::Object<Image>& image) {
static auto& javaClass = jni::Class<Image>::Singleton(env);
static auto widthField = javaClass.GetField<jni::jint>(env, "width");
static auto heightField = javaClass.GetField<jni::jint>(env, "height");
static auto pixelRatioField = javaClass.GetField<jni::jfloat>(env, "pixelRatio");
static auto bufferField = javaClass.GetField<jni::Array<jbyte>>(env, "buffer");
static auto nameField = javaClass.GetField<jni::String>(env, "name");
static auto sdfField = javaClass.GetField<jni::jboolean>(env, "sdf");
auto height = image.Get(env, heightField);
auto width = image.Get(env, widthField);
auto pixelRatio = image.Get(env, pixelRatioField);
auto pixels = image.Get(env, bufferField);
auto name = jni::Make<std::string>(env, image.Get(env, nameField));
auto sdf = (bool) image.Get(env, sdfField);
jni::NullCheck(env, pixels.get());
std::size_t size = pixels.Length(env);
mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
if (premultipliedImage.bytes() != uint32_t(size)) {
throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
}
jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio, sdf};
}
void Image::registerNative(jni::JNIEnv &env) {
jni::Class<Image>::Singleton(env);
}
} // namespace android
} // namespace mb

View File

@@ -1,21 +0,0 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <jni/jni.hpp>
#include <mbgl/style/image.hpp>
namespace mbgl {
namespace android {
class Image : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/Image"; };
static mbgl::style::Image getImage(jni::JNIEnv&, const jni::Object<Image>&);
static void registerNative(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -1,236 +0,0 @@
#include "map_renderer.hpp"
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/util/run_loop.hpp>
#include <string>
#include "attach_env.hpp"
#include "android_renderer_backend.hpp"
#include "map_renderer_runnable.hpp"
namespace mbgl {
namespace android {
MapRenderer::MapRenderer(jni::JNIEnv& _env,
const jni::Object<MapRenderer>& obj,
jni::jfloat pixelRatio_,
const jni::String& localIdeographFontFamily_)
: javaPeer(_env, obj)
, pixelRatio(pixelRatio_)
, localIdeographFontFamily(localIdeographFontFamily_ ? jni::Make<std::string>(_env, localIdeographFontFamily_) : optional<std::string>{})
, mailbox(std::make_shared<Mailbox>(*this)) {
}
MapRenderer::~MapRenderer() = default;
void MapRenderer::reset() {
destroyed = true;
if (renderer) {
// Make sure to destroy the renderer on the GL Thread
auto self = ActorRef<MapRenderer>(*this, mailbox);
self.ask(&MapRenderer::resetRenderer).wait();
}
// Lock to make sure there is no concurrent initialisation on the gl thread
std::lock_guard<std::mutex> lock(initialisationMutex);
rendererObserver.reset();
}
ActorRef<Renderer> MapRenderer::actor() const {
return *rendererRef;
}
void MapRenderer::schedule(std::function<void()> scheduled) {
// Create a runnable
android::UniqueEnv _env = android::AttachEnv();
auto runnable = std::make_unique<MapRendererRunnable>(*_env, std::move(scheduled));
// Obtain ownership of the peer (gets transferred to the MapRenderer on the JVM for later GC)
auto peer = runnable->peer();
// Queue the event on the Java Peer
static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env);
static auto queueEvent = javaClass.GetMethod<void(
jni::Object<MapRendererRunnable>)>(*_env, "queueEvent");
auto weakReference = javaPeer.get(*_env);
if (weakReference) {
weakReference.Call(*_env, queueEvent, peer);
}
// Release the c++ peer as it will be destroyed on GC of the Java Peer
runnable.release();
}
void MapRenderer::requestRender() {
android::UniqueEnv _env = android::AttachEnv();
static auto& javaClass = jni::Class<MapRenderer>::Singleton(*_env);
static auto onInvalidate = javaClass.GetMethod<void()>(*_env, "requestRender");
auto weakReference = javaPeer.get(*_env);
if (weakReference) {
weakReference.Call(*_env, onInvalidate);
}
}
void MapRenderer::update(std::shared_ptr<UpdateParameters> params) {
// Lock on the parameters
std::lock_guard<std::mutex> lock(updateMutex);
updateParameters = std::move(params);
}
void MapRenderer::setObserver(std::shared_ptr<RendererObserver> _rendererObserver) {
// Lock as the initialization can come from the main thread or the GL thread first
std::lock_guard<std::mutex> lock(initialisationMutex);
rendererObserver = std::move(_rendererObserver);
// Set the new observer on the Renderer implementation
if (renderer) {
renderer->setObserver(rendererObserver.get());
}
}
void MapRenderer::requestSnapshot(SnapshotCallback callback) {
auto self = ActorRef<MapRenderer>(*this, mailbox);
self.invoke(
&MapRenderer::scheduleSnapshot,
std::make_unique<SnapshotCallback>([&, callback=std::move(callback), runloop=util::RunLoop::Get()](PremultipliedImage image) {
runloop->invoke([callback=std::move(callback), image=std::move(image), renderer=std::move(this)]() mutable {
if (renderer && !renderer->destroyed) {
callback(std::move(image));
}
});
snapshotCallback.reset();
})
);
}
// Called on OpenGL thread //
void MapRenderer::resetRenderer() {
renderer.reset();
}
void MapRenderer::scheduleSnapshot(std::unique_ptr<SnapshotCallback> callback) {
snapshotCallback = std::move(callback);
requestRender();
}
void MapRenderer::render(JNIEnv&) {
assert (renderer);
std::shared_ptr<UpdateParameters> params;
{
// Lock on the parameters
std::unique_lock<std::mutex> lock(updateMutex);
if (!updateParameters) return;
// Hold on to the update parameters during render
params = updateParameters;
}
// Activate the backend
gfx::BackendScope backendGuard { *backend };
// Ensure that the "current" scheduler on the render thread is
// this scheduler.
Scheduler::SetCurrent(this);
if (framebufferSizeChanged) {
backend->updateViewPort();
framebufferSizeChanged = false;
}
renderer->render(*params);
// Deliver the snapshot if requested
if (snapshotCallback) {
snapshotCallback->operator()(backend->readFramebuffer());
snapshotCallback.reset();
}
}
void MapRenderer::onSurfaceCreated(JNIEnv&) {
// Lock as the initialization can come from the main thread or the GL thread first
std::lock_guard<std::mutex> lock(initialisationMutex);
// The GL context is already active if get a new surface.
gfx::BackendScope backendGuard { *backend, gfx::BackendScope::ScopeType::Implicit };
// The android system will have already destroyed the underlying
// GL resources if this is not the first initialization and an
// attempt to clean them up will fail
if (backend) backend->markContextLost();
if (renderer) renderer->markContextLost();
// Reset in opposite order
renderer.reset();
backend.reset();
// Create the new backend and renderer
backend = std::make_unique<AndroidRendererBackend>();
renderer = std::make_unique<Renderer>(*backend, pixelRatio, localIdeographFontFamily);
rendererRef = std::make_unique<ActorRef<Renderer>>(*renderer, mailbox);
// Set the observer on the new Renderer implementation
if (rendererObserver) {
renderer->setObserver(rendererObserver.get());
}
}
void MapRenderer::onSurfaceChanged(JNIEnv& env, jint width, jint height) {
if (!renderer) {
// In case the surface has been destroyed (due to app back-grounding)
onSurfaceCreated(env);
}
backend->resizeFramebuffer(width, height);
framebufferSizeChanged = true;
requestRender();
}
void MapRenderer::onRendererReset(JNIEnv&) {
// Make sure to destroy the renderer on the GL Thread
auto self = ActorRef<MapRenderer>(*this, mailbox);
self.ask(&MapRenderer::resetRenderer).wait();
}
// needs to be called on GL thread
void MapRenderer::onSurfaceDestroyed(JNIEnv&) {
resetRenderer();
}
// Static methods //
void MapRenderer::registerNative(jni::JNIEnv& env) {
// Lookup the class
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
// Register the peer
jni::RegisterNativePeer<MapRenderer>(env, javaClass, "nativePtr",
jni::MakePeer<MapRenderer, const jni::Object<MapRenderer>&, jni::jfloat, const jni::String&>,
"nativeInitialize", "finalize",
METHOD(&MapRenderer::render, "nativeRender"),
METHOD(&MapRenderer::onRendererReset, "nativeReset"),
METHOD(&MapRenderer::onSurfaceCreated,
"nativeOnSurfaceCreated"),
METHOD(&MapRenderer::onSurfaceChanged,
"nativeOnSurfaceChanged"),
METHOD(&MapRenderer::onSurfaceDestroyed,
"nativeOnSurfaceDestroyed"));
}
MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, const jni::Object<MapRenderer>& jObject) {
static auto& javaClass = jni::Class<MapRenderer>::Singleton(env);
static auto field = javaClass.GetField<jlong>(env, "nativePtr");
MapRenderer* mapRenderer = reinterpret_cast<MapRenderer*>(jObject.Get(env, field));
assert(mapRenderer != nullptr);
return *mapRenderer;
}
} // namespace android
} // namespace mbgl

View File

@@ -1,128 +0,0 @@
#pragma once
#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/optional.hpp>
#include <memory>
#include <mutex>
#include <utility>
#include <jni/jni.hpp>
namespace mbgl {
template <class>
class ActorRef;
class Mailbox;
class Renderer;
class RendererBackend;
class RendererObserver;
class ThreadPool;
class UpdateParameters;
namespace android {
class AndroidRendererBackend;
/**
* The MapRenderer is a peer class that encapsulates the actions
* performed on the GL Thread.
*
* The public methods are safe to call from the main thread, others are not.
*/
class MapRenderer : public Scheduler {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/renderer/MapRenderer"; };
static void registerNative(jni::JNIEnv&);
static MapRenderer& getNativePeer(JNIEnv&, const jni::Object<MapRenderer>&);
MapRenderer(jni::JNIEnv& _env,
const jni::Object<MapRenderer>&,
jni::jfloat pixelRatio,
const jni::String& localIdeographFontFamily);
~MapRenderer() override;
// Resets the renderer to clean up on the calling thread
void reset();
// Takes the RendererObserver by shared_ptr so we
// don't have to make the header public. Use
// this instead of Renderer#setObserver directly
void setObserver(std::shared_ptr<RendererObserver>);
// Sets the new update parameters to use on subsequent
// renders. Be sure to trigger a render with
// requestRender().
void update(std::shared_ptr<UpdateParameters>);
// Gives a handle to the Renderer to enable actions on
// any thread.
ActorRef<Renderer> actor() const;
// From Scheduler. Schedules by using callbacks to the
// JVM to process the mailbox on the right thread.
void schedule(std::function<void()> scheduled) override;
void requestRender();
// Snapshot - requires a RunLoop on the calling thread
using SnapshotCallback = std::function<void (PremultipliedImage)>;
void requestSnapshot(SnapshotCallback);
protected:
// Called from the GL Thread //
void scheduleSnapshot(std::unique_ptr<SnapshotCallback>);
private:
// Called from the GL Thread //
// Resets the renderer
void resetRenderer();
// Renders a frame.
void render(JNIEnv&);
void onSurfaceCreated(JNIEnv&);
void onSurfaceChanged(JNIEnv&, jint width, jint height);
void onSurfaceDestroyed(JNIEnv&);
private:
// Called on either Main or GL thread //
void onRendererReset(JNIEnv&);
private:
jni::WeakReference<jni::Object<MapRenderer>, jni::EnvAttachingDeleter> javaPeer;
float pixelRatio;
optional<std::string> localIdeographFontFamily;
std::shared_ptr<ThreadPool> threadPool;
std::shared_ptr<Mailbox> mailbox;
std::mutex initialisationMutex;
std::shared_ptr<RendererObserver> rendererObserver;
std::unique_ptr<AndroidRendererBackend> backend;
std::unique_ptr<Renderer> renderer;
std::unique_ptr<ActorRef<Renderer>> rendererRef;
std::shared_ptr<UpdateParameters> updateParameters;
std::mutex updateMutex;
bool framebufferSizeChanged = false;
std::atomic<bool> destroyed {false};
std::unique_ptr<SnapshotCallback> snapshotCallback;
};
} // namespace android
} // namespace mbgl

View File

@@ -1,49 +0,0 @@
#include "map_renderer_runnable.hpp"
#include <mbgl/util/logging.hpp>
namespace mbgl {
namespace android {
MapRendererRunnable::MapRendererRunnable(jni::JNIEnv& env, std::function<void()> function_)
: function(std::move(function_)) {
// Create the Java peer and hold on to a global reference
// Not using a weak reference here as this might oerflow
// the weak reference table on some devices
jni::UniqueLocalFrame frame = jni::PushLocalFrame(env, 5);
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
static auto constructor = javaClass.GetConstructor<jlong>(env);
auto instance = javaClass.New(env, constructor, reinterpret_cast<jlong>(this));
javaPeer = jni::NewGlobal(env, instance);
}
MapRendererRunnable::~MapRendererRunnable() = default;
void MapRendererRunnable::run(jni::JNIEnv&) {
if (function) function();
}
jni::Global<jni::Object<MapRendererRunnable>> MapRendererRunnable::peer() {
return std::move(javaPeer);
}
// Static methods //
void MapRendererRunnable::registerNative(jni::JNIEnv& env) {
// Lookup the class
static auto& javaClass = jni::Class<MapRendererRunnable>::Singleton(env);
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
jni::RegisterNativePeer<MapRendererRunnable>(
env,
javaClass,
"nativePtr",
std::make_unique<MapRendererRunnable, JNIEnv&>,
"nativeInitialize",
"finalize",
METHOD(&MapRendererRunnable::run, "run"));
}
} // namespace android
} // namespace mbgl

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