diff --git a/.clang-format b/.clang-format
new file mode 100644
index 000000000..ff0f39e73
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,18 @@
+Standard: Cpp11
+IndentWidth: 4
+AccessModifierOffset: -4
+UseTab: Never
+BinPackParameters: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+AlwaysBreakTemplateDeclarations: true
+NamespaceIndentation: None
+PointerBindsToType: true
+SpacesInParentheses: false
+BreakBeforeBraces: Attach
+ColumnLimit: 100
+Cpp11BracedListStyle: false
+SpacesBeforeTrailingComments: 1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..3e46c0a0a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,35 @@
+.DS_Store
+*.xcodeproj
+*.o
+*.actual.png
+*.diff.png
+*.pyc
+/android/debug
+/android/sdk
+/android/**/.classpath
+/android/**/.project
+/android/**/.settings/
+/mason_packages
+/config/*.gypi
+/build
+/macosx/build
+/linux/build
+/ios/build
+/ios/app/build
+/test/build
+/gyp/build
+/gyp/java
+/test/node_modules
+/test/fixtures/*/*_actual.*
+/test/fixtures/api/1.png
+/test/fixtures/api/2.png
+/test/fixtures/database/*.db
+/include/mbgl/shader/shaders.hpp
+/src/shader/shaders_gl.cpp
+/src/shader/shaders_gles2.cpp
+/bin/style.bin.js
+*~
+
+/ios/benchmark/assets/tiles/mapbox.mapbox-streets-v6/
+/ios/benchmark/assets/tiles/mapbox.mapbox-terrain-v2/
+/ios/benchmark/assets/glyphs/DIN Offc Pro*/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..d84cfecbc
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,23 @@
+[submodule "test/suite"]
+ path = test/suite
+ url = https://github.com/mapbox/mapbox-gl-test-suite.git
+
+[submodule ".mason"]
+ path = .mason
+ url = https://github.com/mapbox/mason.git
+
+[submodule "styles"]
+ path = styles
+ url = https://github.com/mapbox/mapbox-gl-styles.git
+
+[submodule "test/ios/KIF"]
+ path = test/ios/KIF
+ url = https://github.com/kif-framework/KIF.git
+
+[submodule "platform/ios/vendor/SMCalloutView"]
+ path = platform/ios/vendor/SMCalloutView
+ url = https://github.com/nfarina/calloutview.git
+
+[submodule "src/mbgl/util/geojsonvt"]
+ path = src/mbgl/util/geojsonvt
+ url = https://github.com/mapbox/geojson-vt-cpp
diff --git a/.mason b/.mason
new file mode 160000
index 000000000..d8597d944
--- /dev/null
+++ b/.mason
@@ -0,0 +1 @@
+Subproject commit d8597d944533dbb5e28d08dfdba22a82c93171b7
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..9c65614df
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,100 @@
+language: android
+
+sudo: false
+
+matrix:
+ exclude:
+ - os: linux
+ include:
+ - os: linux
+ env: FLAVOR=linux CXX=g++-4.9 BUILDTYPE=Release
+ addons:
+ apt:
+ sources: [ 'ubuntu-toolchain-r-test' ]
+ packages: [ 'gdb', 'g++-4.9', 'gcc-4.9', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ]
+ - os: linux
+ env: FLAVOR=linux CXX=clang++-3.5 BUILDTYPE=Debug
+ addons:
+ apt:
+ sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
+ packages: [ 'gdb', 'clang-3.5', 'libstdc++-4.9-dev', 'libstdc++6', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ]
+ - os: linux
+ env: FLAVOR=linux CXX=clang++-3.5 BUILDTYPE=Release
+ addons:
+ apt:
+ sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5' ]
+ packages: [ 'gdb', 'clang-3.5', 'libstdc++-4.9-dev', 'libstdc++6', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ]
+ - os: osx
+ osx_image: xcode6.4
+ env: FLAVOR=osx BUILDTYPE=Debug
+ - os: osx
+ osx_image: xcode6.4
+ env: FLAVOR=ios BUILDTYPE=Release
+ - os: linux
+ env: FLAVOR=android ANDROID_ABI=arm-v7 BUILDTYPE=Release
+ android:
+ components: [ 'build-tools-23', 'android-23', 'extra-android-m2repository' ]
+ addons:
+ apt:
+ packages: [ 'lib32stdc++6' ]
+ - os: linux
+ env: FLAVOR=android ANDROID_ABI=arm-v7 BUILDTYPE=Debug
+ android:
+ components: [ 'build-tools-23', 'android-23', 'extra-android-m2repository' ]
+ addons:
+ apt:
+ packages: [ 'lib32stdc++6' ]
+ - os: linux
+ env: FLAVOR=android ANDROID_ABI=arm-v8 BUILDTYPE=Release
+ android:
+ components: [ 'build-tools-23', 'android-23', 'extra-android-m2repository' ]
+ addons:
+ apt:
+ packages: [ 'lib32stdc++6' ]
+ - os: linux
+ env: FLAVOR=android ANDROID_ABI=x86 BUILDTYPE=Release
+ android:
+ components: [ 'build-tools-23', 'android-23', 'extra-android-m2repository' ]
+ addons:
+ apt:
+ packages: [ 'lib32stdc++6' ]
+
+env:
+ global:
+ - TERM: dumb
+ # AWS
+ - secure: "MZHblLZXG/jWf2w0ZFlxCLDwx2qtGgRDODQyg1BR7JIuMz6AtWv8XR/sUczWLbiABCL0a/NzJF1g4v2pI7X69IntcjOdIABBgTh7++6+1TJ0Kp8viEltb55nQG3lHy/R6fOaI7Pj9tuCX0PCRtGA5C/fGnodLGEjy3RVOJ09ln0="
+ - secure: "KaSQbhgjtV7ZCkesHmvrNsbQVjk5SPfGKB1VkWenRGYhLF45HpSRNwSxMQddZ566Pg7qIFgF1iWl/B0QW3B6AWL5WmzQ5AOJgwS876pNIc/UT7ubMPtgAtjpvw1bQvQP3B8MrB+3OE5c6tD+a3LhR9krV//dOsfErR5Yy+3Mbkc="
+ # Access Token
+ - secure: "RiBIBfVhhaMjU5ksuwJO3shdvG9FpinBjdSv4co9jg9171SR8edNriedHjVKSIeBhSGNmZmX+twS3dJS/By6tl/LKh9sTynA+ZAYYljkE7jn881B/gMrlYvdAA6og5KvkhV1/0iJWlhuZrMTkhpDR200iLgg3EWBhWjltzmDW/I="
+ # Testmunk
+ - secure: "CHBiUM60TolDbQnn+4IRA/tvOKwKs3g9EDvv8YHSJMg3FuHmjKQkprBasvxf3hnTXg4WLZEubmeDcyJ6RRzPP5mMSr/hksYl0pSjj/6TUecE5fHPVVeN7txVqkpOBf9i45Y+iBUQMjBb1NnDK3pHXxpnAs1Q/pe7vReErj4GF1U="
+ # iOS code signing
+ - secure: "I6Iu75X1E+js5tzijtKi1EGtIuBcA4/25nDYe0svV4HAtujY71ZJZ4eB6355CKhFXpLXrF3i7eKVX3v+zWS0QROPEWacgsqsvNg+Ba9cnznW/faUSOYekCfhzWd/6reYDM7KzKAQwSUHLk9JIWK/kkmi4r+vVJK7h+tjPllK5YA="
+ - IOS_APP_NAME="Mapbox GL"
+ - 'IOS_DEVELOPER_NAME="iPhone Distribution: Mapbox, Inc."'
+ - IOS_PROFILE_NAME="ios-in-house"
+ - secure: "nQqSM8rd7OHtV4MqmNqVnkrVHqxKqQsaWRYk4/nPdhbeVWtTtkk0df711LrF1TUtbEPEewHxYUvTZ/UXmwJNeoKdzTHavI8hnatRkgjyxGERPn1il1Otelht9I+LQQHf+plrpRjVWBrNIW0Zox1B3cqn6d3NglpbXrEQ2EjYGNA="
+ - KIF_SCREENSHOTS="${TRAVIS_BUILD_DIR}/screenshots"
+
+before_install:
+- source ./scripts/travis_helper.sh
+
+install:
+- ./scripts/${FLAVOR}/install.sh
+
+script:
+- ./scripts/${FLAVOR}/run.sh
+
+after_failure:
+- "[ -f ./scripts/${FLAVOR}/after_failure.sh ] && ./scripts/${FLAVOR}/after_failure.sh"
+
+after_script:
+- "[ -f ./scripts/${FLAVOR}/after_script.sh ] && ./scripts/${FLAVOR}/after_script.sh"
+
+notifications:
+ slack:
+ secure: HHQYr7sF8M1SzoWSqgKVYtwAgGdLLCyTMsQjFhEEQNYO92ZwURE5s03qWTGH5k8+4Yqn26yrXt3NztLC4JIOpcGervN2mSZyq4dZgFTcWEd61igw0qwSenlwvFfbE1ASK/KYCzfyn9MIfHN+ovwLoRxXZkPwinKDvl3DXjBaFNg=
+
+git:
+ submodules: false
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
new file mode 100644
index 000000000..be5e3a5c1
--- /dev/null
+++ b/.ycm_extra_conf.py
@@ -0,0 +1,162 @@
+# Version of .ycm_extra_conf.py sample file adapted
+# for the Mapbox GL Native project.
+#
+# This file is NOT licensed under the GPLv3, which is the license for the rest
+# of YouCompleteMe.
+#
+# Here's the license text for this file:
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# For more information, please refer to
+
+import os
+import subprocess
+import sys
+import ycm_core
+
+
+def DirectoryOfThisScript():
+ return os.path.dirname(os.path.abspath(__file__))
+
+
+default_flags = [
+ '-std=c++14',
+ '-I%s' % (os.path.join(DirectoryOfThisScript(), 'src')),
+ '-I%s' % (os.path.join(DirectoryOfThisScript(), 'include')),
+]
+
+
+def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
+ if not working_directory:
+ return list(flags)
+
+ new_flags = []
+ make_next_absolute = False
+ path_flags = ['-isystem', '-I', '-iquote', '--sysroot=']
+
+ for flag in flags:
+ new_flag = flag
+
+ if make_next_absolute:
+ make_next_absolute = False
+ if not flag.startswith('/'):
+ new_flag = os.path.join(working_directory, flag)
+
+ for path_flag in path_flags:
+ if flag == path_flag:
+ make_next_absolute = True
+ break
+
+ if flag.startswith(path_flag):
+ path = flag[len(path_flag):]
+ new_flag = path_flag + os.path.join(working_directory, path)
+ break
+
+ if new_flag:
+ new_flags.append(new_flag)
+
+ return new_flags
+
+
+def FlagsForFileDefault():
+ return {
+ 'flags': default_flags,
+ 'do_cache': False,
+ }
+
+
+def FlagsForFileLinux(filename):
+ working_directory = os.path.join('build', 'linux')
+
+ if not os.path.exists(os.path.join(DirectoryOfThisScript(), working_directory)):
+ return FlagsForFileDefault()
+
+ relative_source_path = filename.replace(DirectoryOfThisScript() + '/', '')
+ relative_obj_path = os.path.splitext(relative_source_path)[0] + '.o'
+
+ make_cmd = 'make -pn |grep %s: |grep GYP_CXXFLAGS |cut -d\' \' -f4-' % relative_obj_path
+
+ p = subprocess.Popen([make_cmd], shell=True, stdout=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+
+ if p.returncode:
+ return FlagsForFileDefault()
+
+ flags = stdout.split(' ')
+ flags_relative = MakeRelativePathsInFlagsAbsolute(flags, os.path.join(DirectoryOfThisScript(), working_directory))
+ flags_final = [flag for flag in flags_relative if flag.startswith("-")]
+
+ return {
+ 'flags': flags_final,
+ 'do_cache': True,
+ }
+
+
+def FlagsForFileDarwin(filename):
+ working_directory = os.path.join('build', 'osx')
+
+ if not os.path.exists(os.path.join(DirectoryOfThisScript(), working_directory)):
+ return FlagsForFileDefault()
+
+ relative_source_path = filename.replace(DirectoryOfThisScript() + '/', '')
+ relative_obj_path = os.path.splitext(relative_source_path)[0] + '.o'
+
+ make_cmd = 'make -pn |grep "%s :=" |grep "NDEBUG" |tail -n 1 | cut -d\' \' -f4-' % relative_obj_path
+
+ p = subprocess.Popen([make_cmd], shell=True, stdout=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+
+ if p.returncode:
+ return FlagsForFileDefault()
+
+ flags = stdout.split(' ')
+ flags_relative = MakeRelativePathsInFlagsAbsolute(flags, os.path.join(DirectoryOfThisScript(), working_directory))
+ flags_final = [flag for flag in flags_relative if flag.startswith("-")]
+
+ # Append OSX sysroot SDK path
+ xcrun_cmd = 'xcrun --show-sdk-path'
+
+ p = subprocess.Popen([xcrun_cmd], shell=True, stdout=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+
+ if p.returncode:
+ return FlagsForFileDefault()
+
+ flags_final.append('-isysroot ' + stdout)
+
+ return {
+ 'flags': flags_final,
+ 'do_cache': True,
+ }
+
+
+def FlagsForFile(filename, **kwargs):
+ if sys.platform.startswith('linux'):
+ return FlagsForFileLinux(filename)
+
+ if sys.platform.startswith('darwin'):
+ return FlagsForFileDarwin(filename)
+
+ return FlagsForFileDefault()
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..45b1959a4
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,72 @@
+# Changelog
+
+## 0.5.1
+
+### iOS
+
+- Added support for CocoaPods 0.38.0. ([#1876](https://github.com/mapbox/mapbox-gl-native/pull/1876))
+
+## 0.5.0
+
+### Core
+
+- Support for runtime marker imagery. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941))
+- Added `Map::fitBounds()` for region-based viewport setting. ([#1092](https://github.com/mapbox/mapbox-gl-native/issues/1092))
+- Added a raster satellite bundled style and improved raster rendering. ([#963](https://github.com/mapbox/mapbox-gl-native/issues/963))
+- Improved round line joins for semi-transparent lines. ([#1839](https://github.com/mapbox/mapbox-gl-native/pull/1839))
+- Improved map render lifecycle notifications. ([#1026](https://github.com/mapbox/mapbox-gl-native/issues/1026))
+- Fixed a bug that caused annotations not to show at zoom level zero. ([#1279](https://github.com/mapbox/mapbox-gl-native/issues/1279))
+- Fixed a bug with the ordering of shape layers. ([#1866](https://github.com/mapbox/mapbox-gl-native/pull/1866))
+- Other bug fixes and performance improvements.
+
+### iOS
+
+- **Breaking:** Headers now make use of lightweight generics, eliminating many unnecessary casts when working with annotations in Swift 2.0 in Xcode 7. ([#1711](https://github.com/mapbox/mapbox-gl-native/pull/1711))
+- **Breaking:** `-mapView:symbolNameForAnnotation:` has been removed from the `MGLMapViewDelegate` protocol. Implement `-mapView:imageForAnnotation:` instead, which accepts images at runtime. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941))
+- **Breaking:** `MGLMapView.direction` is now expressed in terms of degrees clockwise from true north, as indicated in the documentation, rather than counterclockwise. ([#1789](https://github.com/mapbox/mapbox-gl-native/pull/1789))
+- A Satellite style showing Mapbox Satellite imagery is now bundled with Mapbox GL. ([#1845](https://github.com/mapbox/mapbox-gl-native/pull/1845))
+- Improved `UIView` tracking to the map. ([#1813](https://github.com/mapbox/mapbox-gl-native/pull/1813))
+- Delegate method `-[MGLMapViewDelegate mapView:didFailToLocateUserWithError:]` now works. ([#1608](https://github.com/mapbox/mapbox-gl-native/pull/1608))
+- It is now possible to fit the map’s viewport to a coordinate bounding box via `-[MGLMapView setVisibleCoordinateBounds:animated:]` or to a specific set of coordinates via `-[MGLMapView setVisibleCoordinates:count:edgePadding:animated:]`. ([#1783](https://github.com/mapbox/mapbox-gl-native/pull/1783), [#1795](https://github.com/mapbox/mapbox-gl-native/pull/1795))
+- The logo and ℹ️ no longer disappear or get distorted after embedding MGLMapView in a different view, and you can now access these subviews directly via properties on MGLMapView. ([#1779](https://github.com/mapbox/mapbox-gl-native/pull/1779), [#1815](https://github.com/mapbox/mapbox-gl-native/pull/1815))
+- Raster tiles now look sharper midway between two zoom levels. ([#1843](https://github.com/mapbox/mapbox-gl-native/pull/1843))
+- Resetting the map rotation to north no longer also resets the user location tracking mode. ([#1809](https://github.com/mapbox/mapbox-gl-native/pull/1809))
+- `-[MGLMapView convertPoint:toCoordinateFromView:]` now returns accurate coordinates on iPhone 6. ([#1827](https://github.com/mapbox/mapbox-gl-native/pull/1827))
+- Fixed an issue in which `-[MGLMapView direction]` would sometimes return 360 instead of 0. ([#1829](https://github.com/mapbox/mapbox-gl-native/pull/1829))
+- Build against iOS 8.4. ([#1868](https://github.com/mapbox/mapbox-gl-native/pull/1868))
+
+## 0.4.0
+
+### Core
+
+- Support for polyline and polygon shape annotations. ([#1655](https://github.com/mapbox/mapbox-gl-native/issues/1655))
+- Improved placement and density of labels. ([#1666](https://github.com/mapbox/mapbox-gl-native/issues/1666), [blog](https://www.mapbox.com/blog/better-label-placement-mapbox-mobile/))
+- Improved z-ordering appearance of point markers. ([#988](https://github.com/mapbox/mapbox-gl-native/issues/988))
+- Fixed an issue in which certain features, such as roundabouts, were not rendered completely. ([#1725](https://github.com/mapbox/mapbox-gl-native/issues/1725))
+- Many bug fixes and performance and stability improvements.
+- Improved tests.
+
+### iOS
+
+- **Breaking:** `MGLMapView` no longer manages Mapbox access tokens directly; an access token cannot be passed in when initializing the map view. Instead, set `MGLMapboxAccessToken` to your access token in your app’s `Info.plist` file, or call `+[MGLAccountManager setAccessToken:]` before initializing the map view. If you were setting the access token inside an Interface Builder inspectable, also remove it from the User Defined Runtime Attributes section of the Identity inspector. ([#1553](https://github.com/mapbox/mapbox-gl-native/issues/1553))
+- **Breaking:** `MGLAccountManager`'s `-setMapboxMetricsEnabledSettingShownInApp:` has been removed. If you implement a Mapbox Metrics switch inside your app, instead of inside a Settings bundle, set `MGLMapboxMetricsEnabledSettingShownInApp` to `YES` in the `Info.plist` file. ([#1553](https://github.com/mapbox/mapbox-gl-native/issues/1553))
+- **Breaking:** `MGLMapView`'s `-mapID` has been renamed to `-styleID`. ([#1561](https://github.com/mapbox/mapbox-gl-native/issues/1561))
+- Headers have been audited for nullability, improving type safety in both Objective-C and Swift 1.2 when compiling with Xcode 6.3 or above. ([#1578](https://github.com/mapbox/mapbox-gl-native/issues/1578))
+- Fixed an issue in which the map would sometimes spin 180° while rotating the map with two fingers. ([#1453](https://github.com/mapbox/mapbox-gl-native/issues/1453))
+- Added a shortcut to the Mapbox Metrics switch in `MGLMapView`'s action sheet that is attached to the ℹ️ button. ([#1611](https://github.com/mapbox/mapbox-gl-native/issues/1611))
+- `MGLMapView` now supports Interface Builder designables. When you add an `MGLMapView` to a storyboard, it displays instructions for getting set up directly on the storyboard canvas. ([#1573](https://github.com/mapbox/mapbox-gl-native/issues/1573))
+- The default title for the user location annotation is now “You Are Here”. You can customize the title by setting `mapView.userAnnotation.title`. ([#1559](https://github.com/mapbox/mapbox-gl-native/issues/1559))
+- Internal use of the Reachability library has been cleaned up so that your app can include its own copy of Reachability. ([#1718](https://github.com/mapbox/mapbox-gl-native/issues/1718))
+- Now distribute a binary stripped of debugging symbols by default with an optional, secondary symbols build. ([#1650](https://github.com/mapbox/mapbox-gl-native/issues/1650))
+
+## 0.3.1
+
+- Temporarily removed `IBDesignable` support on iOS.
+
+## 0.3.0
+
+- Initial iOS beta release.
+
+Known issues:
+
+- None.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..3348bf902
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,11 @@
+# Contributing
+
+If you have a usage question for a product built on Mapbox GL (such as Mapbox Mobile toolkits like our SDKs), please visit https://www.mapbox.com/help/.
+
+If you want to contribute code:
+
+1. Please familiarize yourself with the [install process](INSTALL.md).
+
+1. Ensure that the [existing issues](https://github.com/mapbox/mapbox-gl-native/issues?utf8=✓&q=) don't already cover your question or contribution.
+
+1. Pull requests gladly accepted.
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 000000000..ac5bb8667
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,347 @@
+# Install
+
+This document describes the process for setting up Mapbox GL for development _on the framework itself_.
+
+# Depends
+
+ - Modern C++ compiler that supports `-std=c++14` (clang++ 3.5 or later or g++-4.9 or later)
+ - [Boost headers](http://boost.org/)
+ - [`zlib`](http://www.zlib.net/)
+ - [`libpng`](http://www.libpng.org/pub/png/libpng.html)
+ - [`libuv 0.10+`](https://github.com/joyent/libuv)
+ - [`glfw 3.1+`](http://www.glfw.org/)
+ - [`libcurl`](http://curl.haxx.se/libcurl/) (depends on OpenSSL; Linux only)
+ - Apple Command Line Tools (for build on OS X; available at [Apple Developer](https://developer.apple.com/downloads))
+ - `pkg-config` (for build only)
+ - [Homebrew](http://brew.sh) (for building on OS X)
+ - [xcpretty](https://github.com/supermarin/xcpretty) (for building on OS X)
+ - [Cask](http://caskroom.io/) (for building Android on OS X)
+ - Python 2.x (for build only)
+
+# Build instructions
+
+We try to link to as many system-provided libraries as possible. When these are unavailable or too outdated, we run a thin build-script layer called [Mason](https://github.com/mapbox/mason) to automate builds, and load precompiled binary packages when possible.
+
+Be sure to pull down all submodules first:
+
+ git submodule init
+ git submodule update
+
+## OS X
+
+This process gives you either a native OS X windowed app or a Linux desktop app with a map view for development purposes, built on an OS X host system.
+
+### Build
+
+ImageMagick is required for tests. It's recommended to install it with [Homebrew](http://brew.sh/) via `brew install imagemagick`.
+
+To create projects, you can run:
+
+- `make xproj`: Creates an Xcode project with OS X-specific handlers for HTTP downloads and settings storage. It uses [GLFW](http://www.glfw.org) for window handling.
+- `make lproj`: Creates an Xcode project with platform-independent handlers for downloads and settings storage. This is what is also being built on Linux.
+- `make osx run-osx`: Builds and runs the OS X application on the command line with `xcodebuild`.
+- `make linux run-linux`: Builds and runs the Linux application with `make`.
+
+Note that you can't have more than one project in Xcode open at a time since the static library project is shared across the OS X, Linux and iOS project.
+
+### Test
+
+- `make test-*` Builds and runs all tests. You can specify individual tests by replacing * with their name.
+
+### Usage
+
+- Press `S` to cycle through bundled styles
+- Press `X` to reset the transform
+- Press `N` to reset north
+- Press `Tab` to toggle debug information
+- Press `C` to toggle symbol collision debug boxes
+- Press `Esc` to quit
+- Press `1` through `6` to add increasing numbers of point annotations for testing
+
+### Target
+
+OS X 10.9+
+
+
+## iOS (Test App)
+
+This process gives you a native iOS app for simulator or device which compiles the source to GL within it for fastest turnaround time during development. Normal, production use of the library is via a precompiled binary linked into the app target.
+
+Developing for iOS implies an OS X host system.
+
+### Build
+
+If you want to build from source and/or contribute to development of the project, run `make iproj`, which will create and open an Xcode project which can build the entire library from source as well as an Objective-C test app. If you don't have an Apple Developer account, change the destination from "My Mac" to a simulator such as "iPhone 6" before you run and build the app.
+
+### Test
+
+You can run `make itest` to run the included integration tests. Requires `gem install xcpretty`. If you want to run the tests in Xcode instead, first `make ipackage` to create a local static library version, then open `test/ios/ios-tests.xcodeproj`, and lastly `Command + U` on the `Mapbox GL Tests` application target.
+
+### Usage
+
+- Pan to move
+- Pinch to zoom
+- Use two fingers to rotate
+- Double-tap to zoom in one level
+- Two-finger single-tap to zoom out one level
+- Double-tap, long-pressing the second, then pan up and down to "quick zoom" (iPhone only, meant for one-handed use)
+- Use the debug menu to add test annotations, reset position, and toggle debug info.
+
+## iOS (Your App)
+
+**If you want a production version of this project, use [Mapbox Mobile](http://mapbox.com/mobile).**
+
+This section is for people contributing to Mapbox GL directly in the context of their own app.
+
+### Build
+
+1. Install [appledoc](http://appledoc.gentlebytes.com/appledoc/) 2.2v963 for API docs generation (only this exact version works right now ([#2117](https://github.com/mapbox/mapbox-gl-native/issues/2117)).
+
+ ```
+ curl -L -o appledoc.zip https://github.com/tomaz/appledoc/releases/download/v2.2-963/appledoc.zip
+ unzip appledoc.zip
+ cp appledoc /usr/local/bin
+ cp -Rf Templates/ ~/.appledoc
+ ```
+
+1. Run `make ipackage`. The packaging script will produce the statically-linked `libMapbox.a`, `Mapbox.bundle` for resources, a `Headers` folder, and a `Docs` folder with HTML API documentation.
+
+### Test
+
+In the context of your own app, you can now either:
+
+#### CocoaPods
+
+Currently, until [#1437](https://github.com/mapbox/mapbox-gl-native/issues/1437) is completed, to install a _development version_ of Mapbox GL using CocoaPods you will need to build it from source manually per above.
+
+1. Zip up the build product.
+
+ cd build/ios/pkg/static
+ ZIP=mapbox-ios-sdk.zip
+ rm -f ../${ZIP}
+ zip -r ../${ZIP} *
+
+1. Modify a custom `Mapbox-iOS-SDK.podspec` to download this zip file.
+
+ {...}
+
+ m.source = {
+ :http => "http://{...}/mapbox-ios-sdk.zip",
+ :flatten => true
+ }
+
+ {...}
+
+1. Update your app's `Podfile` to point to the `Mapbox-iOS-SDK.podspec`.
+
+ pod 'Mapbox-iOS-SDK', :podspec => 'http://{...}/Mapbox-iOS-SDK.podspec'
+
+1. Run `pod update` to grab the newly-built library.
+
+#### Binary
+
+1. Built from source manually per above.
+
+1. Copy the contents of `build/ios/pkg/static` into your project. It should happen automatically, but ensure that:
+
+ - `Headers` is in your *Header Search Paths* (`HEADER_SEARCH_PATHS`) build setting.
+ - `Mapbox.bundle` is in your target's *Copy Bundle Resources* build phase.
+ - `libMapbox.a` is in your target's *Link Binary With Libraries* build phase.
+
+1. Add the following Cocoa framework dependencies to your target's *Link Binary With Libraries* build phase:
+
+ - `CoreTelephony.framework`
+ - `GLKit.framework`
+ - `ImageIO.framework`
+ - `MobileCoreServices.framework`
+ - `QuartzCore.framework`
+ - `SystemConfiguration.framework`
+ - `libc++.dylib`
+ - `libsqlite3.dylib`
+ - `libz.dylib`
+
+1. Add `-ObjC` to your target's "Other Linker Flags" build setting (`OTHER_LDFLAGS`).
+
+### Target
+
+Devices: iPhone 4S and above (5, 5c, 5s, 6, 6 Plus), iPad 2 and above (3, 4, Mini, Air, Mini 2, Air 2), iPod touch 5th gen and above
+
+iOS: 7.0+
+
+
+## Linux
+
+We are using Ubuntu for development. While the software should work on other distributions as well, we are not providing explicit build instructions here.
+
+This process gives you a Linux desktop app built on a Linux host system.
+
+### Build
+
+Install GCC 4.9+ if you are running Ubuntu 14.04 or older. Alternatively, you can also use [Clang 3.5+](http://llvm.org/apt/).
+
+ sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
+ sudo apt-get update
+ sudo apt-get install gcc-4.9 g++-4.9
+ export CXX=g++-4.9
+
+Ensure you have git and other build essentials:
+
+ sudo apt-get install curl git build-essential zlib1g-dev automake \
+ libtool xutils-dev make cmake pkg-config python-pip \
+ libcurl4-openssl-dev libpng-dev libsqlite3-dev \
+ libllvm3.4
+
+Install glfw3 dependencies:
+
+ sudo apt-get install libxi-dev libglu1-mesa-dev x11proto-randr-dev \
+ x11proto-xext-dev libxrandr-dev \
+ x11proto-xf86vidmode-dev libxxf86vm-dev \
+ libxcursor-dev libxinerama-dev
+
+Then, you can then proceed to build the library:
+
+ git submodule update --init
+ make linux
+
+Set an access token as described below, and then run:
+
+ make run-linux
+
+### Test
+
+- `make test-*` Builds and runs all tests. You can specify individual tests by replacing * with their name.
+
+### Usage
+
+- Press `S` to cycle through bundled styles
+- Press `X` to reset the transform
+- Press `N` to reset north
+- Press `Tab` to toggle debug information
+- Press `C` to toggle symbol collision debug boxes
+- Press `Esc` to quit
+- Press `1` through `6` to add increasing numbers of point annotations for testing
+
+### Target
+
+Ubuntu
+
+
+## Android
+
+### Build (Linux Host)
+
+Install a few build dependencies:
+
+ apt-get install -y make git build-essential automake \
+ libtool make cmake pkg-config lib32stdc++6 lib32z1
+
+Install Oracle JDK 7 (requires license agreement) from http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
+
+ export JAVA_HOME="/dir/to/jdk1.7.0_71"
+
+Install the [Android NDK Revision 10e](https://developer.android.com/tools/sdk/ndk/index.html).
+
+ export ANDROID_NDK_PATH="/dir/to/android-ndk-r10e"
+
+Install the Android SDK. We recommend doing this by way of [Android Studio](https://developer.android.com/sdk/installing/studio.html).
+
+ export ANDROID_HOME="/dir/to/android-sdk-linux"
+
+Run:
+
+ make android
+
+You can then open `android/java` in Android Studio via "Import Non-Android Studio Project".
+
+### Build (OS X Host)
+
+Install Oracle JDK 7+:
+
+ brew cask install java
+
+Install the [Android NDK Revision 10e](https://developer.android.com/tools/sdk/ndk/index.html) for 64-bit OS X:
+
+ brew install android-ndk
+
+This will also install the dependency `android-sdk`.
+
+Install [Android Studio](https://developer.android.com/sdk/installing/studio.html):
+
+ brew cask install android-studio
+ android
+
+By default, the SDK will be installed to `/usr/local/opt/android-sdk`. If you open Android Studio at this point, you may get an error message telling you that it can't find a JVM, it's because you installed a custom Java VM from Oracle. Follow [these instructions](http://tools.android.com/recent/androidstudio1rc3_releasecandidate3released) to start Android Studio. You'll wind up setting these environment variables in your .bash_profile or similar:
+
+ echo "export ANDROID_HOME=`brew --prefix android-sdk`" >> .bash_profile
+ echo "export ANDROID_NDK_PATH=`brew --cellar android-ndk`/r10e" >> .bash_profile
+ # Replace with something like /Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk
+ echo "export JAVA_HOME=" >> .bash_profile
+ echo "export STUDIO_JDK=$JAVA_HOME" >> .bash_profile
+
+Run:
+
+ make android
+ open -a Android\ Studio
+
+You can then open `android/java` in Android Studio via "Import Non-Android Studio Project".
+
+### Setting up Android emulator
+
+If you want to run the test app in the emulator, we recommend the x86 build because it will run a lot faster.
+
+First ensure you have an `MAPBOX_ACCESS_TOKEN` environment variable set, as described below. Then, create an x86 build:
+
+ ANDROID_ABI=x86 make android
+
+In Android Studio, create an x86 AVD (Android Virtual Device):
+
+- Open AVD Manager via the Tools menu -> Android -> AVD Manager
+- Click "Create Virtual Device" at the bottom on AVD Manager window
+- Select one of the device profiles, for example the Nexus 4
+- Click "Next"
+- Select a Lollipop or Kitkat release with ABI of x86. If the line is greyed out click Download to download the OS files.
+- Click "Next"
+- Under "Emulated Performance" check "Host GPU" and uncheck "Store a snapshot for faster startup"
+- Click "Finish"
+- Close the AVD Manager
+
+Now when you run or debug the Android project you will see a window "Choose Device". Select your new AVD from drop down under "Launch emulator". If you select "Use same device for future launches" Android Studio will remember the selection and not ask again.
+
+### Running on a hardware device
+
+First read the [Google documentation](http://developer.android.com/tools/device.html) to set up your device and your OS to connect to the device.
+
+When you plug your device in and then run or debug the Android project you will see a window "Choose Device". Choose your device from the "Choose a running device" list.
+
+If your device does not show up, you have not set it up properly. Double check the [Google documentation](http://developer.android.com/tools/device.html).
+
+### Target
+
+Devices running Android 4.0+ (API level 14+).
+
+
+# Troubleshooting
+
+To trigger a complete rebuild, run `make clean` and then start over generating the Xcode projects or `Makefile` as described above.
+
+If you are having trouble getting the dependencies right, you can blow away the `mason_packages` directory, or run `make distclean`. This means the `Makefile` and configure script will automatically install the dependencies again on the next try.
+
+On OS X, you can also try clearing the Xcode cache with `make clear_xcode_cache`.
+
+# Mapbox API access tokens
+
+The demo applications use Mapbox vector tiles, which **require a Mapbox account and API access token**. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/account/apps/).
+
+For iOS and OS X use of the demo apps in Xcode, setup the access token by editing the scheme for the application target, then adding an environment variable with the name `MAPBOX_ACCESS_TOKEN`.
+
+
+
+
+
+For Linux, set the environment variable `MAPBOX_ACCESS_TOKEN` to your token.
+
+For Android, gradle will take the value of `MAPBOX_ACCESS_TOKEN` and save it to `android/java/MapboxGLAndroidSDKTestApp/src/main/res/raw/token.txt` where the app will read it from.
+
+# Style
+
+Default styles in the JSON-based [styling format](https://github.com/mapbox/mapbox-gl-style-spec) are included at `./styles` as a submodule. See the [styles project](https://github.com/mapbox/mapbox-gl-styles) to report problems or to contribute to these styles.
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 000000000..6de1da495
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,65 @@
+mapbox-gl-native copyright (c) 2014, Mapbox.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+Mapbox GL uses portions of the Mapbox iOS SDK, which was derived from the
+Route-Me open source project, including the Alpstein fork of it.
+
+The Route-Me license appears below.
+
+Copyright (c) 2008-2013, Route-Me Contributors
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+===========================================================================
+
+Mapbox GL uses portions of SVPulsingAnnotationView.
+
+Copyright (c) 2013, Sam Vermette
+
+Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..358b3c05c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,134 @@
+export BUILDTYPE ?= Release
+export BUILD_TEST ?= 1
+export BUILD_RENDER ?= 1
+
+# Determine build platform
+ifeq ($(shell uname -s), Darwin)
+export BUILD = osx
+export JOBS ?= $(shell sysctl -n hw.ncpu)
+export XCPRETTY := $(shell ./scripts/xcpretty.sh)
+else ifeq ($(shell uname -s), Linux)
+export BUILD = linux
+export JOBS ?= $(shell grep --count processor /proc/cpuinfo)
+else
+$(error Cannot determine build platform)
+endif
+export BUILD_VERSION = $(shell uname -m)
+
+RUN = +@$(MAKE) -f scripts/main.mk
+
+default: ; @printf "You must specify a valid target\n"
+
+#### OS X targets ##############################################################
+
+ifeq ($(BUILD),osx)
+.PHONY: osx xosx run-osx run-xosx
+osx: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Makefile/osxapp
+xosx: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/osxapp
+run-osx: osx ; @"build/osx-x86_64/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL"
+run-xosx: xosx ; @"gyp/build/$(BUILDTYPE)/Mapbox GL.app/Contents/MacOS/Mapbox GL"
+
+.PHONY: Xcode/osx Xcode/ios
+Xcode/ios: ; $(RUN) HOST=ios Xcode/__project__
+Xcode/osx: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/__project__
+
+.PHONY: xproj iproj
+xproj: Xcode/osx ; @open ./build/osx-x86_64/gyp/osx.xcodeproj
+iproj: Xcode/ios ; @open ./build/ios-all/gyp/ios.xcodeproj
+
+.PHONY: ios ibench isim
+ios ibench isim: export XCODEBUILD_ARGS += PROVISIONING_PROFILE="$$(PROVISIONING_PROFILE)"
+
+ios: export XCODEBUILD_ARGS += -sdk iphoneos ARCHS="arm64 armv7 armv7s"
+ios: ; $(RUN) HOST=ios Xcode/iosapp
+
+isim: export XCODEBUILD_ARGS += -sdk iphonesimulator ARCHS="x86_64 i386"
+isim: ; $(RUN) HOST=ios Xcode/iosapp
+
+ibench: export XCODEBUILD_ARGS += -sdk iphoneos ARCHS="arm64"
+ibench: ; $(RUN) HOST=ios Xcode/ios-bench
+
+.PHONY: ipackage ipackage-strip ipackage-sim itest
+ipackage: Xcode/ios ; @JOBS=$(JOBS) ./scripts/ios/package.sh
+ipackage-strip: Xcode/ios ; @JOBS=$(JOBS) ./scripts/ios/package.sh strip
+ipackage-sim: Xcode/ios ; @JOBS=$(JOBS) ./scripts/ios/package.sh sim
+itest: ipackage-sim ; ./scripts/ios/test.sh
+endif
+
+#### All platforms targets #####################################################
+
+.PHONY: linux run-linux run-valgrind-linux
+linux: ; $(RUN) Makefile/linuxapp
+run-linux: linux ; (cd build/linux-x86_64/$(BUILDTYPE) && ./mapbox-gl)
+run-valgrind-linux: linux
+ (cd build/linux-x86_64/$(BUILDTYPE) && valgrind --leak-check=full --suppressions=../../../scripts/valgrind.sup ./mapbox-gl)
+
+.PHONY: android android-lib
+# Builds a particular android architecture.
+android-lib-%: ; $(RUN) HOST=android HOST_VERSION=$* Makefile/androidapp
+
+# Builds the default Android library
+android-lib: ; $(RUN) HOST=android Makefile/androidapp
+
+# Builds the selected/default Android library
+android: android-lib
+ cd android/java && ./gradlew --parallel --max-workers=$(JOBS) assemble$(BUILDTYPE)
+
+# Builds all android architectures.
+android-all: android-lib-arm-v5 android-lib-arm-v7 android-lib-arm-v8
+android-all: android-lib-x86 android-lib-x86-64
+android-all: android-lib-mips android-lib-mips-64
+ cd android/java && ./gradlew --parallel-threads=$(JOBS) assemble$(BUILDTYPE)
+
+.PHONY: test
+test: ; $(RUN) Makefile/test
+test-%: ; $(RUN) test-$*
+ifeq ($(BUILD),osx)
+xtest: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/test
+endif
+
+.PHONY: render xrender
+render: ; $(RUN) Makefile/mbgl-render
+ifeq ($(BUILD),osx)
+xrender: ; $(RUN) HOST=osx HOST_VERSION=x86_64 Xcode/mbgl-render
+endif
+
+
+##### Maintenace operations ####################################################
+
+.PHONY: clear_xcode_cache
+clear_xcode_cache:
+ifeq ($(BUILD), osx)
+ @CUSTOM_DD=`defaults read com.apple.dt.Xcode IDECustomDerivedDataLocation 2>/dev/null`; \
+ if [ $$CUSTOM_DD ]; then \
+ echo clearing files in $$CUSTOM_DD older than one day; \
+ find $$CUSTOM_DD/mapboxgl-app-* -mtime +1 | xargs rm -rf; \
+ fi; \
+ if [ -d ~/Library/Developer/Xcode/DerivedData/ ] && [ ! $$CUSTOM_DD ]; then \
+ echo 'clearing files in ~/Library/Developer/Xcode/DerivedData/mapboxgl-app-* older than one day'; \
+ find ~/Library/Developer/Xcode/DerivedData/mapboxgl-app-* -mtime +1 | xargs rm -rf; \
+ fi
+endif
+
+.PHONY: clear_sqlite_cache
+clear_sqlite_cache:
+ifeq ($(BUILD), osx)
+ rm -f ~/Library/Application\ Support/Mapbox\ GL/cache.db
+else
+ rm -f /tmp/mbgl-cache.db
+endif
+
+clean: clear_sqlite_cache clear_xcode_cache
+ -find ./deps/gyp -name "*.pyc" -exec rm {} \;
+ -rm -rf ./build/
+ -rm -rf ./macosx/build
+ -rm -rf ./linux/build
+ -rm -rf ./ios/build
+ -rm -rf ./test/build
+ -rm -rf ./config/*.gypi
+ -rm -rf ./android/java/build ./android/java/MapboxGLAndroidSDKTestApp/build ./android/java/MapboxGLAndroidSDKTestApp/build
+ -rm -rf ./android/java/MapboxGLAndroidSDK/src/main/jniLibs ./android/java/MapboxGLAndroidSDK/src/main/assets
+ -rm -f ./android/test/features.zip
+
+distclean: clean
+ -rm -rf ./mason_packages
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..57928618a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# Mapbox GL (Native)
+
+[](https://travis-ci.org/mapbox/mapbox-gl-native/builds)
+
+An OpenGL ES-based renderer for [Mapbox Vector Tiles](https://www.mapbox.com/blog/vector-tiles), consisting of a C++ library for OS X and Linux and SDK bindings for iOS and Android.
+
+**This repository is for development on Mapbox GL itself.**
+
+If you want to use products _based on_ Mapbox GL, check out:
+
+- [Mapbox Mobile](http://mapbox.com/mobile) — iOS and Android native development libraries for vector maps in apps
+- [`node-mapbox-gl-native`](https://github.com/mapbox/node-mapbox-gl-native) — Node.js library for vector map rendering
+- [`react-native-mapbox-gl`](https://github.com/mapbox/react-native-mapbox-gl`) — React Native library for vector maps in apps
+- [`qmapboxgl`](https://github.com/tmpsantos/qmapboxgl) — Qt library for vector map rendering
+
+--
+
+See [`INSTALL.md`](./INSTALL.md) for development setup and install instructions, including dependencies.
diff --git a/android/LICENSE_GESTURES.md b/android/LICENSE_GESTURES.md
new file mode 100644
index 000000000..d2d488c6e
--- /dev/null
+++ b/android/LICENSE_GESTURES.md
@@ -0,0 +1,13 @@
+Android Gesture Detectors Framework Licence
+===================================
+
+Copyright (c) 2012, Almer Thie
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/android/LICENSE_LOST.txt b/android/LICENSE_LOST.txt
new file mode 100644
index 000000000..a0fba4cbc
--- /dev/null
+++ b/android/LICENSE_LOST.txt
@@ -0,0 +1,13 @@
+Copyright (c) 2014 Mapzen
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp
new file mode 100644
index 000000000..d1040d68e
--- /dev/null
+++ b/android/cpp/jni.cpp
@@ -0,0 +1,1863 @@
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
+namespace mbgl {
+namespace android {
+
+JavaVM* theJVM;
+
+std::string cachePath;
+std::string dataPath;
+std::string apkPath;
+std::string androidRelease;
+
+jmethodID onInvalidateId = nullptr;
+jmethodID onMapChangedId = nullptr;
+jmethodID onFpsChangedId = nullptr;
+
+jclass latLngClass = nullptr;
+jmethodID latLngConstructorId = nullptr;
+jfieldID latLngLatitudeId = nullptr;
+jfieldID latLngLongitudeId = nullptr;
+
+jclass latLngZoomClass = nullptr;
+jmethodID latLngZoomConstructorId = nullptr;
+jfieldID latLngZoomLatitudeId = nullptr;
+jfieldID latLngZoomLongitudeId = nullptr;
+jfieldID latLngZoomZoomId = nullptr;
+
+jclass markerClass = nullptr;
+jmethodID markerConstructorId = nullptr;
+jfieldID markerPositionId = nullptr;
+jfieldID markerSpriteId = nullptr;
+
+jclass polylineClass = nullptr;
+jmethodID polylineConstructorId = nullptr;
+jfieldID polylineAlphaId = nullptr;
+jfieldID polylineVisibleId = nullptr;
+jfieldID polylineColorId = nullptr;
+jfieldID polylineWidthId = nullptr;
+jfieldID polylinePointsId = nullptr;
+
+jclass polygonClass = nullptr;
+jmethodID polygonConstructorId = nullptr;
+jfieldID polygonAlphaId = nullptr;
+jfieldID polygonVisibleId = nullptr;
+jfieldID polygonFillColorId = nullptr;
+jfieldID polygonStrokeColorId = nullptr;
+jfieldID polygonStrokeWidthId = nullptr;
+jfieldID polygonPointsId = nullptr;
+jfieldID polygonHolesId = nullptr;
+
+jclass runtimeExceptionClass = nullptr;
+jclass nullPointerExceptionClass = nullptr;
+
+jmethodID listToArrayId = nullptr;
+
+jclass arrayListClass = nullptr;
+jmethodID arrayListConstructorId = nullptr;
+jmethodID arrayListAddId = nullptr;
+
+jclass projectedMetersClass = nullptr;
+jmethodID projectedMetersConstructorId = nullptr;
+jfieldID projectedMetersNorthingId = nullptr;
+jfieldID projectedMetersEastingId = nullptr;
+
+jclass pointFClass = nullptr;
+jmethodID pointFConstructorId = nullptr;
+jfieldID pointFXId = nullptr;
+jfieldID pointFYId = nullptr;
+
+jclass httpContextClass = nullptr;
+jmethodID httpContextGetInstanceId = nullptr;
+jmethodID httpContextCreateRequestId = nullptr;
+
+jclass httpRequestClass = nullptr;
+jmethodID httpRequestStartId = nullptr;
+jmethodID httpRequestCancelId = nullptr;
+
+bool throw_jni_error(JNIEnv *env, const char *msg) {
+ if (env->ThrowNew(runtimeExceptionClass, msg) < 0) {
+ env->ExceptionDescribe();
+ return false;
+ }
+
+ return true;
+}
+
+bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName) {
+ JavaVMAttachArgs args = {JNI_VERSION_1_2, threadName.c_str(), NULL};
+
+ jint ret;
+ *env = nullptr;
+ bool detach = false;
+ ret = vm->GetEnv(reinterpret_cast(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 new 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 new std::runtime_error("AttachCurrentThread() failed");
+ }
+ detach = true;
+ }
+ }
+
+ return detach;
+}
+
+void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach) {
+ if (detach) {
+ jint ret;
+ if ((ret = vm->DetachCurrentThread()) != JNI_OK) {
+ mbgl::Log::Error(mbgl::Event::JNI, "DetachCurrentThread() failed with %i", ret);
+ throw new std::runtime_error("DetachCurrentThread() failed");
+ }
+ }
+ *env = nullptr;
+}
+
+std::string std_string_from_jstring(JNIEnv *env, jstring jstr) {
+ std::string str;
+
+ if (jstr == nullptr) {
+ if (env->ThrowNew(nullPointerExceptionClass, "String cannot be null.") < 0) {
+ env->ExceptionDescribe();
+ return str;
+ }
+
+ return str;
+ }
+
+ jsize len = env->GetStringLength(jstr);
+ if (len < 0) {
+ env->ExceptionDescribe();
+ return str;
+ }
+
+ const jchar *chars = env->GetStringChars(jstr, nullptr);
+ if (chars == nullptr) {
+ env->ExceptionDescribe();
+ return str;
+ }
+
+ std::u16string ustr(reinterpret_cast(chars), len);
+ env->ReleaseStringChars(jstr, chars);
+ chars = nullptr;
+ str = std::wstring_convert, char16_t>().to_bytes(ustr);
+ return str;
+}
+
+jstring std_string_to_jstring(JNIEnv *env, std::string str) {
+ std::u16string ustr =
+ std::wstring_convert, char16_t>().from_bytes(str);
+
+ jstring jstr = env->NewString(reinterpret_cast(ustr.c_str()), ustr.size());
+ if (jstr == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return jstr;
+}
+
+std::vector std_vector_string_from_jobject(JNIEnv *env, jobject jlist) {
+ std::vector vector;
+
+ if (jlist == nullptr) {
+ if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) {
+ env->ExceptionDescribe();
+ return vector;
+ }
+
+ return vector;
+ }
+
+ jobjectArray jarray =
+ reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId));
+ if (env->ExceptionCheck() || (jarray == nullptr)) {
+ env->ExceptionDescribe();
+ return vector;
+ }
+
+ jsize len = env->GetArrayLength(jarray);
+ if (len < 0) {
+ env->ExceptionDescribe();
+ return vector;
+ }
+
+ for (jsize i = 0; i < len; i++) {
+ jstring jstr = reinterpret_cast(env->GetObjectArrayElement(jarray, i));
+ if (jstr == nullptr) {
+ env->ExceptionDescribe();
+ return vector;
+ }
+
+ vector.push_back(std_string_from_jstring(env, jstr));
+ }
+
+ env->DeleteLocalRef(jarray);
+ jarray = nullptr;
+
+ return vector;
+}
+
+jobject std_vector_string_to_jobject(JNIEnv *env, std::vector vector) {
+ jobject jlist = env->NewObject(arrayListClass, arrayListConstructorId);
+ if (jlist == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ for (const auto& str : vector) {
+ env->CallBooleanMethod(jlist, arrayListAddId, std_string_to_jstring(env, str));
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+ }
+
+ return jlist;
+}
+
+jlongArray std_vector_uint_to_jobject(JNIEnv *env, std::vector vector) {
+ jlongArray jarray = env->NewLongArray(vector.size());
+ if (jarray == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ std::vector v;
+ for (const uint32_t& id : vector) {
+ v.push_back((jlong)id);
+ }
+
+ env->SetLongArrayRegion(jarray, 0, v.size(), &(v[0]));
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return jarray;
+}
+
+mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jobject jlist) {
+ mbgl::AnnotationSegment segment;
+
+ if (jlist == nullptr) {
+ if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+ return segment;
+ }
+
+ jobjectArray jarray =
+ reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId));
+ if (env->ExceptionCheck() || (jarray == nullptr)) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ jsize len = env->GetArrayLength(jarray);
+ if (len < 0) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ segment.reserve(len);
+
+ for (jsize i = 0; i < len; i++) {
+ jobject latLng = reinterpret_cast(env->GetObjectArrayElement(jarray, i));
+ if (latLng == nullptr) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return segment;
+ }
+
+ segment.push_back(mbgl::LatLng(latitude, longitude));
+ env->DeleteLocalRef(latLng);
+ }
+
+ env->DeleteLocalRef(jarray);
+ jarray = nullptr;
+
+ return segment;
+}
+
+std::pair annotation_std_pair_from_polygon_jobject(JNIEnv *env, jobject polygon) {
+ jfloat alpha = env->GetFloatField(polygon, polygonAlphaId);
+ //jboolean visible = env->GetBooleanField(polygon, polygonVisibleId);
+ jint fillColor = env->GetIntField(polygon, polygonFillColorId);
+ jint strokeColor = env->GetIntField(polygon, polygonStrokeColorId);
+
+ int rF = (fillColor >> 16) & 0xFF;
+ int gF = (fillColor >> 8) & 0xFF;
+ int bF = (fillColor) & 0xFF;
+ int aF = (fillColor >> 24) & 0xFF;
+
+ int rS = (strokeColor >> 16) & 0xFF;
+ int gS = (strokeColor >> 8) & 0xFF;
+ int bS = (strokeColor) & 0xFF;
+ int aS = (strokeColor >> 24) & 0xFF;
+
+ mbgl::StyleProperties shapeProperties;
+ mbgl::FillProperties fillProperties;
+ fillProperties.opacity = alpha;
+ fillProperties.stroke_color = {{ static_cast(rS) / 255.0f, static_cast(gS) / 255.0f, static_cast(bS) / 255.0f, static_cast(aS) / 255.0f }};
+ fillProperties.fill_color = {{ static_cast(rF) / 255.0f, static_cast(gF) / 255.0f, static_cast(bF) / 255.0f, static_cast(aF) / 255.0f }};
+ shapeProperties.set(fillProperties);
+
+ jobject points = env->GetObjectField(polygon, polygonPointsId);
+ mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
+ env->DeleteLocalRef(points);
+
+ return std::make_pair(segment, shapeProperties);
+}
+
+}
+}
+
+namespace {
+
+using namespace mbgl::android;
+
+jlong JNICALL nativeCreate(JNIEnv *env, jobject obj, jstring cachePath_, jstring dataPath_, jstring apkPath_, jfloat pixelRatio, jint availableProcessors, jlong totalMemory) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeCreate");
+ cachePath = std_string_from_jstring(env, cachePath_);
+ dataPath = std_string_from_jstring(env, dataPath_);
+ apkPath = std_string_from_jstring(env, apkPath_);
+ NativeMapView *nativeMapView = new NativeMapView(env, obj, pixelRatio, availableProcessors, totalMemory);
+ jlong mapViewPtr = reinterpret_cast(nativeMapView);
+ return mapViewPtr;
+}
+
+void JNICALL nativeDestroy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeDestroy");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ delete nativeMapView;
+ nativeMapView = nullptr;
+}
+
+void JNICALL nativeInitializeDisplay(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeInitializeDisplay");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ try
+ {
+ nativeMapView->initializeDisplay();
+ } catch(const std::exception& e) {
+ throw_jni_error(env, "Unable to initialize GL display.");
+ }
+}
+
+void JNICALL nativeTerminateDisplay(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminateDisplay");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->terminateDisplay();
+}
+
+void JNICALL nativeInitializeContext(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeInitializeContext");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ try {
+ nativeMapView->initializeContext();
+ } catch(const std::exception& e) {
+ throw_jni_error(env, "Unable to initialize GL context.");
+ }
+}
+
+void JNICALL nativeTerminateContext(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminateContext");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->terminateContext();
+}
+
+void JNICALL nativeCreateSurface(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject surface) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeCreateSurface");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ try {
+ nativeMapView->createSurface(ANativeWindow_fromSurface(env, surface));
+ } catch(const std::exception& e) {
+ throw_jni_error(env, "Unable to create GL surface.");
+ }
+}
+
+void JNICALL nativeDestroySurface(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeDestroySurface");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->destroySurface();
+}
+
+void JNICALL nativePause(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativePause");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->pause();
+}
+
+void JNICALL nativeResume(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeResume");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->resume();
+}
+
+void JNICALL nativeUpdate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdate");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().update(mbgl::Update::Repaint);
+}
+
+void JNICALL nativeOnInvalidate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeOnInvalidate");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->onInvalidate();
+}
+
+void JNICALL nativeViewResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint width, jint height) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeViewResize");
+ assert(nativeMapViewPtr != 0);
+ assert(width >= 0);
+ assert(height >= 0);
+ assert(width <= UINT16_MAX);
+ assert(height <= UINT16_MAX);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->resizeView(width, height);
+}
+
+void JNICALL nativeFramebufferResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint fbWidth, jint fbHeight) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeFramebufferResize");
+ assert(nativeMapViewPtr != 0);
+ assert(fbWidth >= 0);
+ assert(fbHeight >= 0);
+ assert(fbWidth <= UINT16_MAX);
+ assert(fbHeight <= UINT16_MAX);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->resizeFramebuffer(fbWidth, fbHeight);
+}
+
+void JNICALL nativeRemoveClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveClass");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().removeClass(std_string_from_jstring(env, clazz));
+}
+
+jboolean JNICALL nativeHasClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeHasClass");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().hasClass(std_string_from_jstring(env, clazz));
+}
+
+void JNICALL nativeAddClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddClass");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().addClass(std_string_from_jstring(env, clazz));
+}
+
+void JNICALL nativeSetClasses(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject classes) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetClasses");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setClasses(std_vector_string_from_jobject(env, classes));
+}
+
+jobject JNICALL nativeGetClasses(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetClasses");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return std_vector_string_to_jobject(env, nativeMapView->getMap().getClasses());
+}
+
+void JNICALL nativeSetDefaultTransitionDuration(JNIEnv *env, jobject obj, jlong nativeMapViewPtr,
+ jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetDefaultTransitionDuration");
+ assert(nativeMapViewPtr != 0);
+ assert(duration >= 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setDefaultTransitionDuration(std::chrono::milliseconds(duration));
+}
+
+jlong JNICALL nativeGetDefaultTransitionDuration(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetDefaultTransitionDuration");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return std::chrono::duration_cast(nativeMapView->getMap().getDefaultTransitionDuration()).count();
+}
+
+void JNICALL nativeSetStyleURL(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring url) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleURL");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setStyleURL(std_string_from_jstring(env, url));
+}
+
+void JNICALL nativeSetStyleJSON(JNIEnv *env, jobject obj, jlong nativeMapViewPtr,
+ jstring newStyleJson, jstring base) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleJSON");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setStyleJSON(std_string_from_jstring(env, newStyleJson),
+ std_string_from_jstring(env, base));
+}
+
+jstring JNICALL nativeGetStyleJSON(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetStyleJSON");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return std_string_to_jstring(env, nativeMapView->getMap().getStyleJSON());
+}
+
+void JNICALL nativeSetAccessToken(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring accessToken) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetAccessToken");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getFileSource().setAccessToken(std_string_from_jstring(env, accessToken));
+}
+
+jstring JNICALL nativeGetAccessToken(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetAccessToken");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return std_string_to_jstring(env, nativeMapView->getFileSource().getAccessToken());
+}
+
+void JNICALL nativeCancelTransitions(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeCancelTransitions");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().cancelTransitions();
+}
+
+void JNICALL nativeSetGestureInProgress(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean inProgress) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetGestureInProgress");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setGestureInProgress(inProgress);
+}
+
+void JNICALL nativeMoveBy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble dx, jdouble dy,
+ jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeMoveBy");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().moveBy(dx, dy, std::chrono::milliseconds(duration));
+}
+
+void JNICALL nativeSetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng,
+ jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLatLng");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ nativeMapView->getMap().setLatLng(mbgl::LatLng(latitude, longitude), std::chrono::milliseconds(duration));
+}
+
+jobject JNICALL nativeGetLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLng");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ mbgl::LatLng latLng = nativeMapView->getMap().getLatLng();
+
+ jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude);
+ if (ret == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return ret;
+}
+
+void JNICALL nativeResetPosition(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetPosition");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().resetPosition();
+}
+
+void JNICALL nativeScaleBy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble ds, jdouble cx,
+ jdouble cy, jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeScaleBy");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().scaleBy(ds, cx, cy, std::chrono::milliseconds(duration));
+}
+
+void JNICALL nativeSetScale(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble scale,
+ jdouble cx, jdouble cy, jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetScale");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setScale(scale, cx, cy, std::chrono::milliseconds(duration));
+}
+
+jdouble JNICALL nativeGetScale(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetScale");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getScale();
+}
+
+void JNICALL nativeSetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble zoom, jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetZoom");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setZoom(zoom, std::chrono::milliseconds(duration));
+}
+
+jdouble JNICALL nativeGetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetZoom");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getZoom();
+}
+
+void JNICALL nativeSetLatLngZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr,
+ jobject latLngZoom, jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetLatLngZoom");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jdouble latitude = env->GetDoubleField(latLngZoom, latLngZoomLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ jdouble longitude = env->GetDoubleField(latLngZoom, latLngZoomLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ jdouble zoom = env->GetDoubleField(latLngZoom, latLngZoomZoomId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ nativeMapView->getMap().setLatLngZoom(mbgl::LatLng(latitude, longitude), zoom, std::chrono::milliseconds(duration));
+}
+
+jobject JNICALL nativeGetLatLngZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLatLngZoom");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ mbgl::LatLng latLng = nativeMapView->getMap().getLatLng();
+ jdouble zoom = nativeMapView->getMap().getZoom();
+
+ jobject ret = env->NewObject(latLngZoomClass, latLngZoomConstructorId, latLng.longitude, latLng.latitude, zoom);
+ if (ret == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return ret;
+}
+
+void JNICALL nativeResetZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetZoom");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().resetZoom();
+}
+
+jdouble JNICALL nativeGetMinZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMinZoom");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getMinZoom();
+}
+
+jdouble JNICALL nativeGetMaxZoom(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMaxZoom");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getMaxZoom();
+}
+
+void JNICALL nativeRotateBy(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble sx,
+ jdouble sy, jdouble ex, jdouble ey, jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeRotateBy");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().rotateBy(sx, sy, ex, ey, std::chrono::milliseconds(duration));
+}
+
+void JNICALL nativeSetBearing(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble degrees,
+ jlong duration) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetBearing");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setBearing(degrees, std::chrono::milliseconds(duration));
+}
+
+void JNICALL nativeSetBearing(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble degrees,
+ jdouble cx, jdouble cy) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetBearing");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setBearing(degrees, cx, cy);
+}
+
+jdouble JNICALL nativeGetBearing(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetBearing");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getBearing();
+}
+
+void JNICALL nativeResetNorth(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeResetNorth");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().resetNorth();
+}
+
+jlong JNICALL nativeAddMarker(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject marker) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarker");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jobject position = env->GetObjectField(marker, markerPositionId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ jstring jsprite = reinterpret_cast(env->GetObjectField(marker, markerSpriteId));
+ std::string sprite = std_string_from_jstring(env, jsprite);
+
+ jdouble latitude = env->GetDoubleField(position, latLngLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ jdouble longitude = env->GetDoubleField(position, latLngLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
+ return nativeMapView->getMap().addPointAnnotation(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), sprite));
+}
+
+jlong JNICALL nativeAddPolyline(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polyline) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolyline");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jfloat alpha = env->GetFloatField(polyline, polylineAlphaId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ /*jboolean visible = env->GetBooleanField(polyline, polylineVisibleId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }*/
+
+ jint color = env->GetIntField(polyline, polylineColorId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ int r = (color >> 16) & 0xFF;
+ int g = (color >> 8) & 0xFF;
+ int b = (color) & 0xFF;
+ int a = (color >> 24) & 0xFF;
+
+ jfloat width = env->GetFloatField(polyline, polylineWidthId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ mbgl::StyleProperties shapeProperties;
+ mbgl::LineProperties lineProperties;
+ lineProperties.opacity = alpha;
+ lineProperties.color = {{ static_cast(r) / 255.0f, static_cast(g) / 255.0f, static_cast(b) / 255.0f, static_cast(a) / 255.0f }};
+ lineProperties.width = width;
+ shapeProperties.set(lineProperties);
+
+ jobject points = env->GetObjectField(polyline, polylinePointsId);
+ mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
+
+ std::vector shapes;
+ shapes.emplace_back(mbgl::AnnotationSegments { segment }, shapeProperties);
+
+ std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
+ uint32_t id = shapeAnnotationIDs.at(0);
+
+ return id;
+}
+
+jlong JNICALL nativeAddPolygon(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject polygon) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygon");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ std::vector shapes;
+ std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon);
+
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return -1;
+ }
+
+ shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second);
+
+ std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
+ uint32_t id = shapeAnnotationIDs.at(0);
+ return id;
+}
+
+jlongArray JNICALL nativeAddPolygons(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject jlist) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygons");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ std::vector shapes;
+
+ if (jlist == nullptr) {
+ if (env->ThrowNew(nullPointerExceptionClass, "List cannot be null.") < 0) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+ return nullptr;
+ }
+
+ jobjectArray jarray =
+ reinterpret_cast(env->CallObjectMethod(jlist, listToArrayId));
+ if (env->ExceptionCheck() || (jarray == nullptr)) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ jsize len = env->GetArrayLength(jarray);
+ if (len < 0) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ shapes.reserve(len);
+
+ for (jsize i = 0; i < len; i++) {
+ jobject polygon = reinterpret_cast(env->GetObjectArrayElement(jarray, i));
+
+ std::pair segment = annotation_std_pair_from_polygon_jobject(env, polygon);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second);
+
+ env->DeleteLocalRef(polygon);
+ }
+
+ env->DeleteLocalRef(jarray);
+
+ std::vector shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
+ return std_vector_uint_to_jobject(env, shapeAnnotationIDs);
+}
+
+void JNICALL nativeRemoveAnnotation(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlong annotationId) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotation");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().removeAnnotation(static_cast(annotationId));
+}
+
+void JNICALL nativeRemoveAnnotations(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jlongArray jarray) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotations");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ std::vector ids;
+
+ if (env->ExceptionCheck() || (jarray == nullptr)) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ jsize len = env->GetArrayLength(jarray);
+ if (len < 0) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ ids.reserve(len);
+ jlong* jids = env->GetLongArrayElements(jarray, nullptr);
+
+ for (jsize i = 0; i < len; i++) {
+ if(jids[i] == -1L)
+ continue;
+ ids.push_back(static_cast(jids[i]));
+ }
+
+ env->ReleaseLongArrayElements(jarray, jids, JNI_ABORT);
+
+ nativeMapView->getMap().removeAnnotations(ids);
+}
+
+void JNICALL nativeSetSprite(JNIEnv *env, jobject obj, jlong nativeMapViewPtr,
+ jstring symbol, jint width, jint height, jfloat scale, jbyteArray jpixels) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetSprite");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ const std::string symbolName = std_string_from_jstring(env, symbol);
+
+ jbyte* pixelData = env->GetByteArrayElements(jpixels, nullptr);
+ std::string pixels(reinterpret_cast(pixelData), width * height * 4);
+ env->ReleaseByteArrayElements(jpixels, pixelData, JNI_ABORT);
+
+ auto spriteImage = std::make_shared(
+ uint16_t(width),
+ uint16_t(height),
+ float(scale),
+ std::move(pixels));
+
+ nativeMapView->getMap().setSprite(symbolName, spriteImage);
+}
+
+void JNICALL nativeOnLowMemory(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeOnLowMemory");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().onLowMemory();
+}
+
+void JNICALL nativeSetDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean debug) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetDebug");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setDebug(debug);
+ nativeMapView->enableFps(debug);
+}
+
+void JNICALL nativeToggleDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeToggleDebug");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().toggleDebug();
+ nativeMapView->enableFps(nativeMapView->getMap().getDebug());
+}
+
+jboolean JNICALL nativeGetDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetDebug");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getDebug();
+}
+
+void JNICALL nativeSetCollisionDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean debug) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetCollisionDebug");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().setCollisionDebug(debug);
+}
+
+void JNICALL nativeToggleCollisionDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeToggleCollisionDebug");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ nativeMapView->getMap().toggleCollisionDebug();
+}
+
+jboolean JNICALL nativeGetCollisionDebug(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetCollisionDebug");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getCollisionDebug();
+}
+
+jboolean JNICALL nativeIsFullyLoaded(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeIsFullyLoaded");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().isFullyLoaded();
+}
+
+void JNICALL nativeSetReachability(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jboolean status) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetReachability");
+ assert(nativeMapViewPtr != 0);
+ if (status) {
+ mbgl::NetworkStatus::Reachable();
+ }
+}
+
+jdouble JNICALL nativeGetMetersPerPixelAtLatitude(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jdouble lat, jdouble zoom) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetMetersPerPixelAtLatitude");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+ return nativeMapView->getMap().getMetersPerPixelAtLatitude(lat, zoom);
+}
+
+jobject JNICALL nativeProjectedMetersForLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeProjectedMetersForLatLng");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ mbgl::ProjectedMeters projectedMeters = nativeMapView->getMap().projectedMetersForLatLng(mbgl::LatLng(latitude, longitude));
+
+ jobject ret = env->NewObject(projectedMetersClass, projectedMetersConstructorId, projectedMeters.northing, projectedMeters.easting);
+ if (ret == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return ret;
+}
+
+jobject JNICALL nativeLatLngForProjectedMeters(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject projectedMeters) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeLatLngForProjectedMeters");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jdouble northing = env->GetDoubleField(projectedMeters, projectedMetersNorthingId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ jdouble easting = env->GetDoubleField(projectedMeters, projectedMetersEastingId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ mbgl::LatLng latLng = nativeMapView->getMap().latLngForProjectedMeters(mbgl::ProjectedMeters(northing, easting));
+
+ jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude);
+ if (ret == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return ret;
+}
+
+jobject JNICALL nativePixelForLatLng(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject latLng) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativePixelForLatLng");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jdouble latitude = env->GetDoubleField(latLng, latLngLatitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ jdouble longitude = env->GetDoubleField(latLng, latLngLongitudeId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ mbgl::vec2 pixel = nativeMapView->getMap().pixelForLatLng(mbgl::LatLng(latitude, longitude));
+
+ jobject ret = env->NewObject(pointFClass, pointFConstructorId, static_cast(pixel.x), static_cast(pixel.y));
+ if (ret == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return ret;
+}
+
+jobject JNICALL nativeLatLngForPixel(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jobject pixel) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeLatLngForPixel");
+ assert(nativeMapViewPtr != 0);
+ NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr);
+
+ jfloat x = env->GetFloatField(pixel, pointFXId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ jfloat y = env->GetFloatField(pixel, pointFYId);
+ if (env->ExceptionCheck()) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::vec2(x, y));
+
+ jobject ret = env->NewObject(latLngClass, latLngConstructorId, latLng.latitude, latLng.longitude);
+ if (ret == nullptr) {
+ env->ExceptionDescribe();
+ return nullptr;
+ }
+
+ return ret;
+}
+
+}
+
+extern "C" {
+
+extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "JNI_OnLoad");
+
+ theJVM = vm;
+
+ JNIEnv *env = nullptr;
+ jint ret = vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6);
+ if (ret != JNI_OK) {
+ mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret);
+ return JNI_ERR;
+ }
+
+ latLngClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLng");
+ if (latLngClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngConstructorId = env->GetMethodID(latLngClass, "", "(DD)V");
+ if (latLngConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngLatitudeId = env->GetFieldID(latLngClass, "latitude", "D");
+ if (latLngLatitudeId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngLongitudeId = env->GetFieldID(latLngClass, "longitude", "D");
+ if (latLngLongitudeId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngZoomClass = env->FindClass("com/mapbox/mapboxgl/geometry/LatLngZoom");
+ if (latLngZoomClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngZoomConstructorId = env->GetMethodID(latLngZoomClass, "", "(DDD)V");
+ if (latLngZoomConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngZoomLatitudeId = env->GetFieldID(latLngZoomClass, "latitude", "D");
+ if (latLngZoomLatitudeId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngZoomLongitudeId = env->GetFieldID(latLngZoomClass, "longitude", "D");
+ if (latLngZoomLongitudeId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngZoomZoomId = env->GetFieldID(latLngZoomClass, "zoom", "D");
+ if (latLngZoomZoomId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ markerClass = env->FindClass("com/mapbox/mapboxgl/annotations/Marker");
+ if (markerClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ markerConstructorId = env->GetMethodID(markerClass, "", "()V");
+ if (markerConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ markerPositionId = env->GetFieldID(markerClass, "position", "Lcom/mapbox/mapboxgl/geometry/LatLng;");
+ if (markerPositionId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ markerSpriteId = env->GetFieldID(markerClass, "sprite", "Ljava/lang/String;");
+ if (markerSpriteId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineClass = env->FindClass("com/mapbox/mapboxgl/annotations/Polyline");
+ if (polylineClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineConstructorId = env->GetMethodID(polylineClass, "", "()V");
+ if (polylineConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineAlphaId = env->GetFieldID(polylineClass, "alpha", "F");
+ if (polylineAlphaId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineVisibleId = env->GetFieldID(polylineClass, "visible", "Z");
+ if (polylineVisibleId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineColorId = env->GetFieldID(polylineClass, "color", "I");
+ if (polylineColorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylineWidthId = env->GetFieldID(polylineClass, "width", "F");
+ if (polylineWidthId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polylinePointsId = env->GetFieldID(polylineClass, "points", "Ljava/util/List;");
+ if (polylineWidthId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonClass = env->FindClass("com/mapbox/mapboxgl/annotations/Polygon");
+ if (polygonClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonConstructorId = env->GetMethodID(polygonClass, "", "()V");
+ if (polygonConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonAlphaId = env->GetFieldID(polygonClass, "alpha", "F");
+ if (polygonAlphaId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonVisibleId = env->GetFieldID(polygonClass, "visible", "Z");
+ if (polygonVisibleId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonFillColorId = env->GetFieldID(polygonClass, "fillColor", "I");
+ if (polygonFillColorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonStrokeColorId = env->GetFieldID(polygonClass, "strokeColor", "I");
+ if (polygonStrokeColorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonStrokeWidthId = env->GetFieldID(polygonClass, "strokeWidth", "F");
+ if (polygonStrokeWidthId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonPointsId = env->GetFieldID(polygonClass, "points", "Ljava/util/List;");
+ if (polygonPointsId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ polygonHolesId = env->GetFieldID(polygonClass, "holes", "Ljava/util/List;");
+ if (polygonHolesId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ jclass nativeMapViewClass = env->FindClass("com/mapbox/mapboxgl/views/NativeMapView");
+ if (nativeMapViewClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ onInvalidateId = env->GetMethodID(nativeMapViewClass, "onInvalidate", "()V");
+ if (onInvalidateId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ onMapChangedId = env->GetMethodID(nativeMapViewClass, "onMapChanged", "()V");
+ if (onMapChangedId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ onFpsChangedId = env->GetMethodID(nativeMapViewClass, "onFpsChanged", "(D)V");
+ if (onFpsChangedId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ runtimeExceptionClass = env->FindClass("java/lang/RuntimeException");
+ if (runtimeExceptionClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ nullPointerExceptionClass = env->FindClass("java/lang/NullPointerException");
+ if (nullPointerExceptionClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ jclass listClass = env->FindClass("java/util/List");
+ if (listClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ listToArrayId = env->GetMethodID(listClass, "toArray", "()[Ljava/lang/Object;");
+ if (listToArrayId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ arrayListClass = env->FindClass("java/util/ArrayList");
+ if (arrayListClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ arrayListConstructorId = env->GetMethodID(arrayListClass, "", "()V");
+ if (arrayListConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ arrayListAddId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
+ if (arrayListAddId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ projectedMetersClass = env->FindClass("com/mapbox/mapboxgl/geometry/ProjectedMeters");
+ if (projectedMetersClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ projectedMetersConstructorId = env->GetMethodID(projectedMetersClass, "", "(DD)V");
+ if (projectedMetersConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ projectedMetersNorthingId = env->GetFieldID(projectedMetersClass, "northing", "D");
+ if (projectedMetersNorthingId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ projectedMetersEastingId = env->GetFieldID(projectedMetersClass, "easting", "D");
+ if (projectedMetersEastingId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ pointFClass = env->FindClass("android/graphics/PointF");
+ if (pointFClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ pointFConstructorId = env->GetMethodID(pointFClass, "", "(FF)V");
+ if (pointFConstructorId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ pointFXId = env->GetFieldID(pointFClass, "x", "F");
+ if (pointFXId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ pointFYId = env->GetFieldID(pointFClass, "y", "F");
+ if (pointFYId == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ httpContextClass = env->FindClass("com/mapbox/mapboxgl/http/HTTPContext");
+ if (httpContextClass == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ httpContextGetInstanceId = env->GetStaticMethodID(httpContextClass, "getInstance", "()Lcom/mapbox/mapboxgl/http/HTTPContext;");
+ if (httpContextGetInstanceId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ httpContextCreateRequestId = env->GetMethodID(httpContextClass, "createRequest", "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/mapbox/mapboxgl/http/HTTPContext$HTTPRequest;");
+ if (httpContextCreateRequestId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ httpRequestClass = env->FindClass("com/mapbox/mapboxgl/http/HTTPContext$HTTPRequest");
+ if (httpRequestClass == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ httpRequestStartId = env->GetMethodID(httpRequestClass, "start", "()V");
+ if (httpRequestStartId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ httpRequestCancelId = env->GetMethodID(httpRequestClass, "cancel", "()V");
+ if (httpRequestCancelId == nullptr) {
+ env->ExceptionDescribe();
+ }
+
+ const std::vector methods = {
+ {"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;FIJ)J",
+ reinterpret_cast(&nativeCreate)},
+ {"nativeDestroy", "(J)V", reinterpret_cast(&nativeDestroy)},
+ {"nativeInitializeDisplay", "(J)V", reinterpret_cast(&nativeInitializeDisplay)},
+ {"nativeTerminateDisplay", "(J)V", reinterpret_cast(&nativeTerminateDisplay)},
+ {"nativeInitializeContext", "(J)V", reinterpret_cast(&nativeInitializeContext)},
+ {"nativeTerminateContext", "(J)V", reinterpret_cast(&nativeTerminateContext)},
+ {"nativeCreateSurface", "(JLandroid/view/Surface;)V",
+ reinterpret_cast(&nativeCreateSurface)},
+ {"nativeDestroySurface", "(J)V", reinterpret_cast(&nativeDestroySurface)},
+ {"nativePause", "(J)V", reinterpret_cast(&nativePause)},
+ {"nativeResume", "(J)V", reinterpret_cast(&nativeResume)},
+ {"nativeUpdate", "(J)V", reinterpret_cast(&nativeUpdate)},
+ {"nativeOnInvalidate", "(J)V", reinterpret_cast(&nativeOnInvalidate)},
+ {"nativeViewResize", "(JII)V",
+ reinterpret_cast(static_cast(&nativeViewResize))},
+ {"nativeFramebufferResize", "(JII)V",
+ reinterpret_cast(static_cast(&nativeFramebufferResize))},
+ {"nativeAddClass", "(JLjava/lang/String;)V",
+ reinterpret_cast(&nativeAddClass)},
+ {"nativeRemoveClass", "(JLjava/lang/String;)V",
+ reinterpret_cast(&nativeRemoveClass)},
+ {"nativeHasClass", "(JLjava/lang/String;)Z",
+ reinterpret_cast(&nativeHasClass)},
+ {"nativeSetClasses", "(JLjava/util/List;)V",
+ reinterpret_cast(&nativeSetClasses)},
+ {"nativeGetClasses", "(J)Ljava/util/List;",
+ reinterpret_cast(&nativeGetClasses)},
+ {"nativeSetDefaultTransitionDuration", "(JJ)V",
+ reinterpret_cast(&nativeSetDefaultTransitionDuration)},
+ {"nativeGetDefaultTransitionDuration", "(J)J",
+ reinterpret_cast(&nativeGetDefaultTransitionDuration)},
+ {"nativeSetStyleUrl", "(JLjava/lang/String;)V",
+ reinterpret_cast(&nativeSetStyleURL)},
+ {"nativeSetStyleJson", "(JLjava/lang/String;Ljava/lang/String;)V",
+ reinterpret_cast(&nativeSetStyleJSON)},
+ {"nativeGetStyleJson", "(J)Ljava/lang/String;",
+ reinterpret_cast(&nativeGetStyleJSON)},
+ {"nativeSetAccessToken", "(JLjava/lang/String;)V",
+ reinterpret_cast(&nativeSetAccessToken)},
+ {"nativeGetAccessToken", "(J)Ljava/lang/String;",
+ reinterpret_cast(&nativeGetAccessToken)},
+ {"nativeCancelTransitions", "(J)V", reinterpret_cast(&nativeCancelTransitions)},
+ {"nativeSetGestureInProgress", "(JZ)V", reinterpret_cast(&nativeSetGestureInProgress)},
+ {"nativeMoveBy", "(JDDJ)V", reinterpret_cast(&nativeMoveBy)},
+ {"nativeSetLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;J)V",
+ reinterpret_cast(&nativeSetLatLng)},
+ {"nativeGetLatLng", "(J)Lcom/mapbox/mapboxgl/geometry/LatLng;",
+ reinterpret_cast(&nativeGetLatLng)},
+ {"nativeResetPosition", "(J)V", reinterpret_cast(&nativeResetPosition)},
+ {"nativeScaleBy", "(JDDDJ)V", reinterpret_cast(&nativeScaleBy)},
+ {"nativeSetScale", "(JDDDJ)V", reinterpret_cast(&nativeSetScale)},
+ {"nativeGetScale", "(J)D", reinterpret_cast(&nativeGetScale)},
+ {"nativeSetZoom", "(JDJ)V", reinterpret_cast(&nativeSetZoom)},
+ {"nativeGetZoom", "(J)D", reinterpret_cast(&nativeGetZoom)},
+ {"nativeSetLatLngZoom", "(JLcom/mapbox/mapboxgl/geometry/LatLngZoom;J)V",
+ reinterpret_cast(&nativeSetLatLngZoom)},
+ {"nativeGetLatLngZoom", "(J)Lcom/mapbox/mapboxgl/geometry/LatLngZoom;",
+ reinterpret_cast(&nativeGetLatLngZoom)},
+ {"nativeResetZoom", "(J)V", reinterpret_cast(&nativeResetZoom)},
+ {"nativeGetMinZoom", "(J)D", reinterpret_cast(&nativeGetMinZoom)},
+ {"nativeGetMaxZoom", "(J)D", reinterpret_cast(&nativeGetMaxZoom)},
+ {"nativeRotateBy", "(JDDDDJ)V", reinterpret_cast(&nativeRotateBy)},
+ {"nativeSetBearing", "(JDJ)V",
+ reinterpret_cast(
+ static_cast(
+ &nativeSetBearing))},
+ {"nativeSetBearing", "(JDDD)V",
+ reinterpret_cast(
+ static_cast(
+ &nativeSetBearing))},
+ {"nativeGetBearing", "(J)D", reinterpret_cast(&nativeGetBearing)},
+ {"nativeResetNorth", "(J)V", reinterpret_cast(&nativeResetNorth)},
+ {"nativeAddMarker", "(JLcom/mapbox/mapboxgl/annotations/Marker;)J",
+ reinterpret_cast(&nativeAddMarker)},
+ {"nativeAddPolyline", "(JLcom/mapbox/mapboxgl/annotations/Polyline;)J",
+ reinterpret_cast(&nativeAddPolyline)},
+ {"nativeAddPolygon", "(JLcom/mapbox/mapboxgl/annotations/Polygon;)J",
+ reinterpret_cast(&nativeAddPolygon)},
+ {"nativeAddPolygons", "(JLjava/util/List;)[J",
+ reinterpret_cast(&nativeAddPolygons)},
+ {"nativeRemoveAnnotation", "(JJ)V", reinterpret_cast(&nativeRemoveAnnotation)},
+ {"nativeRemoveAnnotations", "(J[J)V", reinterpret_cast(&nativeRemoveAnnotations)},
+ {"nativeSetSprite", "(JLjava/lang/String;IIF[B)V", reinterpret_cast(&nativeSetSprite)},
+ {"nativeOnLowMemory", "(J)V", reinterpret_cast(&nativeOnLowMemory)},
+ {"nativeSetDebug", "(JZ)V", reinterpret_cast(&nativeSetDebug)},
+ {"nativeToggleDebug", "(J)V", reinterpret_cast(&nativeToggleDebug)},
+ {"nativeGetDebug", "(J)Z", reinterpret_cast(&nativeGetDebug)},
+ {"nativeSetCollisionDebug", "(JZ)V", reinterpret_cast(&nativeSetCollisionDebug)},
+ {"nativeToggleCollisionDebug", "(J)V", reinterpret_cast(&nativeToggleCollisionDebug)},
+ {"nativeGetCollisionDebug", "(J)Z", reinterpret_cast(&nativeGetCollisionDebug)},
+ {"nativeIsFullyLoaded", "(J)Z", reinterpret_cast(&nativeIsFullyLoaded)},
+ {"nativeSetReachability", "(JZ)V", reinterpret_cast(&nativeSetReachability)},
+ //{"nativeGetWorldBoundsMeters", "(J)V", reinterpret_cast(&nativeGetWorldBoundsMeters)},
+ //{"nativeGetWorldBoundsLatLng", "(J)V", reinterpret_cast(&nativeGetWorldBoundsLatLng)},
+ {"nativeGetMetersPerPixelAtLatitude", "(JDD)D", reinterpret_cast(&nativeGetMetersPerPixelAtLatitude)},
+ {"nativeProjectedMetersForLatLng",
+ "(JLcom/mapbox/mapboxgl/geometry/LatLng;)Lcom/mapbox/mapboxgl/geometry/ProjectedMeters;",
+ reinterpret_cast(&nativeProjectedMetersForLatLng)},
+ {"nativeLatLngForProjectedMeters",
+ "(JLcom/mapbox/mapboxgl/geometry/ProjectedMeters;)Lcom/mapbox/mapboxgl/geometry/LatLng;",
+ reinterpret_cast(&nativeLatLngForProjectedMeters)},
+ {"nativePixelForLatLng", "(JLcom/mapbox/mapboxgl/geometry/LatLng;)Landroid/graphics/PointF;",
+ reinterpret_cast(&nativePixelForLatLng)},
+ {"nativeLatLngForPixel", "(JLandroid/graphics/PointF;)Lcom/mapbox/mapboxgl/geometry/LatLng;",
+ reinterpret_cast(&nativeLatLngForPixel)},
+ };
+
+ if (env->RegisterNatives(nativeMapViewClass, methods.data(), methods.size()) < 0) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngClass = reinterpret_cast(env->NewGlobalRef(latLngClass));
+ if (latLngClass == nullptr) {
+ env->ExceptionDescribe();
+ return JNI_ERR;
+ }
+
+ latLngZoomClass = reinterpret_cast(env->NewGlobalRef(latLngZoomClass));
+ if (latLngZoomClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ return JNI_ERR;
+ }
+
+ markerClass = reinterpret_cast(env->NewGlobalRef(markerClass));
+ if (markerClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ return JNI_ERR;
+ }
+
+ polylineClass = reinterpret_cast(env->NewGlobalRef(polylineClass));
+ if (polylineClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(markerClass);
+ return JNI_ERR;
+ }
+
+ polygonClass = reinterpret_cast(env->NewGlobalRef(polygonClass));
+ if (polygonClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(polylineClass);
+ return JNI_ERR;
+ }
+
+ runtimeExceptionClass = reinterpret_cast(env->NewGlobalRef(runtimeExceptionClass));
+ if (runtimeExceptionClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(polylineClass);
+ env->DeleteGlobalRef(polygonClass);
+ return JNI_ERR;
+ }
+
+ nullPointerExceptionClass =
+ reinterpret_cast(env->NewGlobalRef(nullPointerExceptionClass));
+ if (nullPointerExceptionClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(polylineClass);
+ env->DeleteGlobalRef(polygonClass);
+ env->DeleteGlobalRef(runtimeExceptionClass);
+ return JNI_ERR;
+ }
+
+ arrayListClass = reinterpret_cast(env->NewGlobalRef(arrayListClass));
+ if (arrayListClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(polylineClass);
+ env->DeleteGlobalRef(polygonClass);
+ env->DeleteGlobalRef(runtimeExceptionClass);
+ env->DeleteGlobalRef(nullPointerExceptionClass);
+ return JNI_ERR;
+ }
+
+ projectedMetersClass = reinterpret_cast(env->NewGlobalRef(projectedMetersClass));
+ if (projectedMetersClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(polylineClass);
+ env->DeleteGlobalRef(polygonClass);
+ env->DeleteGlobalRef(runtimeExceptionClass);
+ env->DeleteGlobalRef(nullPointerExceptionClass);
+ env->DeleteGlobalRef(arrayListClass);
+ return JNI_ERR;
+ }
+
+ pointFClass = reinterpret_cast(env->NewGlobalRef(pointFClass));
+ if (pointFClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(polylineClass);
+ env->DeleteGlobalRef(polygonClass);
+ env->DeleteGlobalRef(runtimeExceptionClass);
+ env->DeleteGlobalRef(nullPointerExceptionClass);
+ env->DeleteGlobalRef(arrayListClass);
+ env->DeleteGlobalRef(projectedMetersClass);
+ return JNI_ERR;
+ }
+
+ httpContextClass = reinterpret_cast(env->NewGlobalRef(httpContextClass));
+ if (httpContextClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(polylineClass);
+ env->DeleteGlobalRef(polygonClass);
+ env->DeleteGlobalRef(runtimeExceptionClass);
+ env->DeleteGlobalRef(nullPointerExceptionClass);
+ env->DeleteGlobalRef(arrayListClass);
+ env->DeleteGlobalRef(projectedMetersClass);
+ env->DeleteGlobalRef(pointFClass);
+ }
+
+ httpRequestClass = reinterpret_cast(env->NewGlobalRef(httpRequestClass));
+ if (httpRequestClass == nullptr) {
+ env->ExceptionDescribe();
+ env->DeleteGlobalRef(latLngClass);
+ env->DeleteGlobalRef(markerClass);
+ env->DeleteGlobalRef(latLngZoomClass);
+ env->DeleteGlobalRef(polylineClass);
+ env->DeleteGlobalRef(polygonClass);
+ env->DeleteGlobalRef(runtimeExceptionClass);
+ env->DeleteGlobalRef(nullPointerExceptionClass);
+ env->DeleteGlobalRef(arrayListClass);
+ env->DeleteGlobalRef(projectedMetersClass);
+ env->DeleteGlobalRef(pointFClass);
+ env->DeleteGlobalRef(httpContextClass);
+ }
+
+ char release[PROP_VALUE_MAX] = "";
+ __system_property_get("ro.build.version.release", release);
+ androidRelease = std::string(release);
+
+ return JNI_VERSION_1_6;
+}
+
+extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "JNI_OnUnload");
+
+ theJVM = vm;
+
+ JNIEnv *env = nullptr;
+ jint ret = vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6);
+ if (ret != JNI_OK) {
+ mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret);
+ throw new std::runtime_error("GetEnv() failed");
+ }
+
+ env->DeleteGlobalRef(latLngClass);
+ latLngClass = nullptr;
+ latLngConstructorId = nullptr;
+ latLngLongitudeId = nullptr;
+ latLngLatitudeId = nullptr;
+
+ env->DeleteGlobalRef(latLngZoomClass);
+ latLngZoomClass = nullptr;
+ latLngZoomConstructorId = nullptr;
+ latLngZoomLongitudeId = nullptr;
+ latLngZoomLatitudeId = nullptr;
+ latLngZoomZoomId = nullptr;
+
+ env->DeleteGlobalRef(markerClass);
+ markerClass = nullptr;
+ markerConstructorId = nullptr;
+ markerPositionId = nullptr;
+ markerSpriteId = nullptr;
+
+ env->DeleteGlobalRef(polylineClass);
+ polylineClass = nullptr;
+ polylineConstructorId = nullptr;
+ polylineAlphaId = nullptr;
+ polylineVisibleId = nullptr;
+ polylineColorId = nullptr;
+ polylineWidthId = nullptr;
+ polylinePointsId = nullptr;
+
+ env->DeleteGlobalRef(polygonClass);
+ polygonClass = nullptr;
+ polygonConstructorId = nullptr;
+ polygonAlphaId = nullptr;
+ polygonVisibleId = nullptr;
+ polygonFillColorId = nullptr;
+ polygonStrokeColorId = nullptr;
+ polygonStrokeWidthId = nullptr;
+ polygonPointsId = nullptr;
+ polygonHolesId = nullptr;
+
+ onInvalidateId = nullptr;
+ onMapChangedId = nullptr;
+ onFpsChangedId = nullptr;
+
+ env->DeleteGlobalRef(runtimeExceptionClass);
+ runtimeExceptionClass = nullptr;
+
+ env->DeleteGlobalRef(nullPointerExceptionClass);
+ nullPointerExceptionClass = nullptr;
+
+ listToArrayId = nullptr;
+
+ env->DeleteGlobalRef(arrayListClass);
+ arrayListClass = nullptr;
+ arrayListConstructorId = nullptr;
+ arrayListAddId = nullptr;
+
+ env->DeleteGlobalRef(projectedMetersClass);
+ projectedMetersClass = nullptr;
+ projectedMetersConstructorId = nullptr;
+ projectedMetersNorthingId = nullptr;
+ projectedMetersEastingId = nullptr;
+
+ env->DeleteGlobalRef(pointFClass);
+ pointFClass = nullptr;
+ pointFConstructorId = nullptr;
+ pointFXId = nullptr;
+ pointFYId = nullptr;
+
+ env->DeleteGlobalRef(httpContextClass);
+ httpContextGetInstanceId = nullptr;
+ httpContextCreateRequestId = nullptr;
+
+ env->DeleteGlobalRef(httpRequestClass);
+ httpRequestStartId = nullptr;
+ httpRequestCancelId = nullptr;
+
+ theJVM = nullptr;
+}
+}
diff --git a/android/cpp/native_map_view.cpp b/android/cpp/native_map_view.cpp
new file mode 100644
index 000000000..d7c40ba5a
--- /dev/null
+++ b/android/cpp/native_map_view.cpp
@@ -0,0 +1,728 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace mbgl {
+namespace android {
+
+void log_egl_string(EGLDisplay display, EGLint name, const char *label) {
+ const char *str = eglQueryString(display, name);
+ if (str == nullptr) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "eglQueryString(%d) returned error %d", name,
+ eglGetError());
+ throw new std::runtime_error("eglQueryString() failed");
+ } else {
+ char buf[513];
+ for (int len = std::strlen(str), pos = 0; len > 0; len -= 512, pos += 512) {
+ strncpy(buf, str + pos, 512);
+ buf[512] = 0;
+ mbgl::Log::Info(mbgl::Event::OpenGL, "EGL %s: %s", label, buf);
+ }
+ }
+}
+
+void log_gl_string(GLenum name, const char *label) {
+ const GLubyte *str = glGetString(name);
+ if (str == nullptr) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "glGetString(%d) returned error %d", name,
+ glGetError());
+ throw new std::runtime_error("glGetString() failed");
+ } else {
+ char buf[513];
+ for (int len = std::strlen(reinterpret_cast(str)), pos = 0; len > 0;
+ len -= 512, pos += 512) {
+ strncpy(buf, reinterpret_cast(str) + pos, 512);
+ buf[512] = 0;
+ mbgl::Log::Info(mbgl::Event::OpenGL, "GL %s: %s", label, buf);
+ }
+ }
+}
+
+NativeMapView::NativeMapView(JNIEnv *env, jobject obj_, float pixelRatio_, int availableProcessors_, size_t totalMemory_)
+ : mbgl::View(*this),
+ pixelRatio(pixelRatio_),
+ availableProcessors(availableProcessors_),
+ totalMemory(totalMemory_),
+ fileCache(mbgl::android::cachePath + "/mbgl-cache.db"),
+ fileSource(&fileCache),
+ map(*this, fileSource, MapMode::Continuous) {
+ mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::NativeMapView");
+
+ map.pause();
+
+ assert(env != nullptr);
+ assert(obj_ != nullptr);
+
+ if (env->GetJavaVM(&vm) < 0) {
+ env->ExceptionDescribe();
+ return;
+ }
+
+ obj = env->NewGlobalRef(obj_);
+ if (obj == nullptr) {
+ env->ExceptionDescribe();
+ return;
+ }
+}
+
+NativeMapView::~NativeMapView() {
+ mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::~NativeMapView");
+ terminateContext();
+ destroySurface();
+ terminateDisplay();
+
+ assert(vm != nullptr);
+ assert(obj != nullptr);
+
+ jint ret;
+ JNIEnv *env = nullptr;
+ ret = vm->GetEnv(reinterpret_cast