Merge branch 'master' of github.com:mapbox/mapbox-gl-native into nightlyBuilds

This commit is contained in:
Brad Leege
2015-02-10 17:15:10 -08:00
147 changed files with 5448 additions and 582 deletions

1
.gitignore vendored
View File

@@ -9,6 +9,7 @@
/build
/macosx/build
/linux/build
/ios/build
/test/build
/test/node_modules
/include/mbgl/shader/shaders.hpp

10
.gitmodules vendored
View File

@@ -1,7 +1,3 @@
[submodule "ios/mapbox-gl-cocoa"]
path = ios/mapbox-gl-cocoa
url = https://github.com/mapbox/mapbox-gl-cocoa.git
[submodule "test/suite"]
path = test/suite
url = https://github.com/mapbox/mapbox-gl-test-suite.git
@@ -14,6 +10,6 @@
path = styles
url = https://github.com/mapbox/mapbox-gl-styles.git
[submodule "app/ios"]
path = app/ios
url = https://github.com/mapbox/mapbox-gl-cocoa.git
[submodule "test/ios/KIF"]
path = test/ios/KIF
url = https://github.com/mapbox/KIF.git

View File

@@ -47,6 +47,13 @@ env:
- secure: "CHBiUM60TolDbQnn+4IRA/tvOKwKs3g9EDvv8YHSJMg3FuHmjKQkprBasvxf3hnTXg4WLZEubmeDcyJ6RRzPP5mMSr/hksYl0pSjj/6TUecE5fHPVVeN7txVqkpOBf9i45Y+iBUQMjBb1NnDK3pHXxpnAs1Q/pe7vReErj4GF1U="
- LD_LIBRARY_PATH: '/usr/local/lib'
- TERM: dumb
# begin 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="
# end iOS code signing
before_install:
- if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then sudo service mysql stop; fi
@@ -65,10 +72,19 @@ install:
before_script:
# Set the core file limit to unlimited so a core file is generated upon crash
- ulimit -c unlimited -S
# begin iOS code signing
- openssl aes-256-cbc -k "$IOS_ENCRYPTION_SECRET" -in scripts/ios_travis/ios-in-house.mobileprovision.enc -d -a -out scripts/ios_travis/ios-in-house.mobileprovision
- openssl aes-256-cbc -k "$IOS_ENCRYPTION_SECRET" -in scripts/ios_travis/ios-dist.cer.enc -d -a -out scripts/ios_travis/ios-dist.cer
- openssl aes-256-cbc -k "$IOS_ENCRYPTION_SECRET" -in scripts/ios_travis/ios-dist.p12.enc -d -a -out scripts/ios_travis/ios-dist.p12
- ./scripts/ios_travis/add-key.sh
# end iOS code signing
script:
- ./scripts/travis_script.sh
after_script:
- ./scripts/ios_travis/remove-key.sh
notifications:
hipchat:
rooms:

View File

@@ -23,7 +23,7 @@ config/%.gypi: configure
#### Library builds ############################################################
.PRECOIUS: Makefile/mbgl
.PRECIOUS: Makefile/mbgl
Makefile/mbgl: config/$(HOST).gypi
deps/run_gyp mbgl.gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f make
@@ -36,6 +36,9 @@ standalone: Makefile/mbgl
install: Makefile/mbgl
LINK=`pwd`/gyp/link.py $(MAKE) -C build/$(HOST) BUILDTYPE=$(BUILDTYPE) install
.PRECIOUS: Xcode/mbgl
Xcode/mbgl: config/$(HOST).gypi
deps/run_gyp mbgl.gyp $(CONFIG_$(HOST)) $(LIBS_$(HOST)) --generator-output=./build/$(HOST) -f xcode
##### Test builds ##############################################################
@@ -101,15 +104,18 @@ xproj: xosx-proj
#### iOS application builds ####################################################
.PRECIOUS: Xcode/ios
Xcode/ios: ios/mapbox-gl-cocoa/app/mapboxgl-app.gyp config/ios.gypi
deps/run_gyp ios/mapbox-gl-cocoa/app/mapboxgl-app.gyp $(CONFIG_ios) $(LIBS_ios) --generator-output=./build/ios -f xcode
Xcode/ios: ios/app/mapboxgl-app.gyp config/ios.gypi
deps/run_gyp ios/app/mapboxgl-app.gyp $(CONFIG_ios) $(LIBS_ios) --generator-output=./build/ios -f xcode
.PHONY: ios-proj ios run-ios
ios-proj: Xcode/ios
open ./build/ios/ios/mapbox-gl-cocoa/app/mapboxgl-app.xcodeproj
open ./build/ios/ios/app/mapboxgl-app.xcodeproj
ios: Xcode/ios
xcodebuild -sdk iphonesimulator ARCHS=x86_64 -project ./build/ios/ios/mapbox-gl-cocoa/app/mapboxgl-app.xcodeproj -configuration $(BUILDTYPE) -target iosapp -jobs `sysctl -n hw.ncpu`
xcodebuild -sdk iphoneos ARCHS="arm64 armv7 armv7s" PROVISIONING_PROFILE="2b532944-bf3d-4bf4-aa6c-a81676984ae8" -project ./build/ios/ios/app/mapboxgl-app.xcodeproj -configuration Release -target iosapp -jobs `sysctl -n hw.ncpu`
isim: Xcode/ios
xcodebuild -sdk iphonesimulator ARCHS="x86_64 i386" -project ./build/ios/ios/app/mapboxgl-app.xcodeproj -configuration Debug -target iosapp -jobs `sysctl -n hw.ncpu`
# Legacy name
iproj: ios-proj
@@ -197,8 +203,7 @@ clean: clear_sqlite_cache clear_xcode_cache
-rm -rf ./build/
-rm -rf ./macosx/build
-rm -rf ./linux/build
-rm -rf ./ios/mapbox-gl-cocoa/build
-rm -rf ./ios/mapbox-gl-cocoa/app/build
-rm -rf ./ios/build
-rm -rf ./test/build
-rm -rf ./config/*.gypi
-rm -rf ./android/java/build ./android/java/app/build ./android/java/lib/build

View File

@@ -28,7 +28,7 @@ Be sure to pull down all submodules first:
## OS X
On OS X, we are using `zlib`, `SQLite3`, `libcurl` and `libpng` provided by the operating system. In addition to that, you need to have the Boost headers installed and ImageMagick for running tests. To install all prerequisites, use [Homebrew](http://brew.sh/) and type `brew install pkg-config boost imagemagick`.
Prerequisites include the Boost headers (for routines provided therein) and ImageMagick (for tests). To install all prerequisites, use [Homebrew](http://brew.sh/) and type `brew install pkg-config boost imagemagick`.
To create projects, you can run:
@@ -40,22 +40,19 @@ To create projects, you can run:
Note that you can't have more than one project in Xcode open at a time since they the static library project is shared across the OS X, Linux and iOS project.
Target OS: 10.9+
Target OS X: 10.9+
## iOS
iOS makes use of a Cocoa-specific API called [`mapbox-gl-cocoa`](https://github.com/mapbox/mapbox-gl-cocoa). If you are just interested in running Mapbox GL on iOS and not developing with it, head to that project and you can use this library as a pre-built static library instead. A `UIView` interface to the map view and bundle resources are provided there.
If you merely want to install the library for iOS and try it out as an Objective-C consumer, run `./scripts/package_ios.sh`. It requires the Boost headers to be installed, so use [Homebrew](http://brew.sh/) to install them (`brew install boost`). The packaging script will produce the statically-linked `libMapboxGL.a`, `MapboxGL.bundle` for resources, and a `Headers` folder.
If you intend to develop here, `mapbox-gl-cocoa` is included as a submodule of the overall build setup.
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.
You can run `make iproj` to create and open an Xcode project with an iOS-specific view controller housing. This will automatically install required dependencies as well.
Target devices: iPhone 4S and above (5, 5c, 5s, 6, 6 Plus) and iPad 2 and above (3, 4, Mini, Air, Mini 2, Air 2).
Note that if you are doing OS X development as well, to toggle from OS X back to iOS, you will need to `make iproj` again.
Target iOS: 7.0 through 8.1
Target devices: iPhone 4S and above (5, 5c, 5s, 6, 6 Plus) and iPad 2 and above (3, 4, Mini , Air, Mini 2, Air 2).
Target OS: 7.0+
## Linux
@@ -103,7 +100,11 @@ Set an access token as described below, and then run:
make run-linux
## Android (on Linux)
## Android
Target devices: All Android devices on Android 4.0 or newer (API level >= 14)
### On Linux
Install a few build dependencies:
@@ -128,7 +129,7 @@ Run:
You can then open `android/java` in Android Studio via "Import Non-Android Studio Project".
## Android (on OS X)
### On OS X
Install Oracle JDK 7 (requires license agreement) from http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html

View File

@@ -16,7 +16,3 @@ make android BUILDTYPE=$BUILDTYPE JOBS=$JOBS
aws s3 cp ./android/java/app/build/outputs/apk/app-debug.apk s3://mapbox-gl-testing/android/${NAME}/app-debug.apk
aws s3 cp ./android/java/app/build/outputs/apk/app-release-unsigned.apk s3://mapbox-gl-testing/android/${NAME}/app-release-unsigned.apk
if [[ $TESTMUNK == "yes" ]]; then
./android/scripts/upload-testmunk.sh ./android/java/app/build/outputs/apk/app-debug.apk
fi

View File

@@ -1,25 +0,0 @@
#!/usr/bin/env bash
set -e
set -o pipefail
EMAIL="leith@mapbox.com"
APP_NAME="Mapbox"
APK_PATH=$1
echo "submitting testrun to testmunk"
echo "uploading features..."
zip -r android/test/features.zip android/test/features/
RESPONSE=$(curl -f -H "Accept: application/vnd.testmunk.v1+json" -F "file=@android/test/features.zip" "https://${TESTMUNK_KEY}@api.testmunk.com/apps/${APP_NAME}/testcases")
echo "uploading apk..."
RESPONSE=$(curl -f -H "Accept: application/vnd.testmunk.v1+json" -F "file=@${APK_PATH}" -F "email=${EMAIL}" -F "autoStart=true" -F "public=true" "https://${TESTMUNK_KEY}@api.testmunk.com/apps/${APP_NAME}/testruns")
TESTRUN_ID=$(echo "${RESPONSE}" | jq -r '.id')
TESTRUN_NAME=$(echo "${RESPONSE}" | jq -r '.name')
echo "successully uploaded to Testmunk as '${TESTRUN_NAME}'"
echo "public link to test results: https://www.testmunk.com/testrun/${TESTRUN_ID}"

View File

@@ -1 +0,0 @@
features.zip

View File

@@ -1,5 +0,0 @@
Feature: Testapp V.1.2
Scenario: 1) Start app and load map
Given I await for 5 seconds

View File

@@ -1 +0,0 @@
require 'calabash-android/calabash_steps'

View File

@@ -1,6 +0,0 @@
Then /^I await for ([\d\.]+) second(?:s)?$/ do |num_seconds|
num_seconds = num_seconds.to_f
sleep num_seconds
end

View File

@@ -1,36 +0,0 @@
require 'calabash-android/management/app_installation'
AfterConfiguration do |config|
FeatureNameMemory.feature_name = nil
end
Before do |scenario|
@scenario_is_outline = (scenario.class == Cucumber::Ast::OutlineTable::ExampleRow)
if @scenario_is_outline
scenario = scenario.scenario_outline
end
feature_name = scenario.feature.title
if FeatureNameMemory.feature_name != feature_name \
or ENV["RESET_BETWEEN_SCENARIOS"] == "1"
if ENV["RESET_BETWEEN_SCENARIOS"] == "1"
log "New scenario - reinstalling apps"
else
log "First scenario in feature - reinstalling apps"
end
uninstall_apps
install_app(ENV["TEST_APP_PATH"])
install_app(ENV["APP_PATH"])
FeatureNameMemory.feature_name = feature_name
FeatureNameMemory.invocation = 1
else
FeatureNameMemory.invocation += 1
end
end
FeatureNameMemory = Class.new
class << FeatureNameMemory
@feature_name = nil
attr_accessor :feature_name, :invocation
end

View File

@@ -1,13 +0,0 @@
require 'calabash-android/management/adb'
require 'calabash-android/operations'
Before do |scenario|
start_test_server_in_background
end
After do |scenario|
if scenario.failed?
screenshot_embed
end
shutdown_test_server
end

View File

@@ -1 +0,0 @@
require 'calabash-android/cucumber'

1
configure vendored
View File

@@ -92,7 +92,6 @@ CONFIG="# Do not edit. Generated by the configure script.
'libraries': []
},
'variables': {
'python': '${PYTHON}',
"
if [ ! -z ${BOOST_VERSION} ]; then

View File

@@ -1,50 +1,46 @@
{
'conditions': [
['install_prefix != ""', {
'targets': [
{ 'target_name': 'install',
'type': 'none',
'hard_dependency': 1,
'dependencies': [
'core',
'platform-<(platform_lib)',
'http-<(http_lib)',
'asset-<(asset_lib)',
'cache-<(cache_lib)',
'headless-<(headless_lib)',
'standalone',
],
'copies': [
{ 'files': [ '<(PRODUCT_DIR)/libmbgl.a' ], 'destination': '<(install_prefix)/lib' },
{ 'files': [ '<(SHARED_INTERMEDIATE_DIR)/include/mbgl/util/version.hpp' ], 'destination': '<(install_prefix)/include/mbgl/util' },
],
'actions': [
{
'action_name': 'Copy header files',
'inputs': [ '../include/mbgl/mbgl.hpp' ],
'outputs': [ '../include/mbgl/mbgl.hpp' ],
'action': [ 'cp', '-r', 'include', '<(install_prefix)/' ]
},
{ 'action_name': 'mbgl-config',
'inputs': [
'../utils/mbgl-config/mbgl-config.template.sh',
'../utils/mbgl-config/build.sh',
],
'outputs': [
'<(install_prefix)/bin/mbgl-config',
],
'action': [
'./utils/mbgl-config/build.sh',
'<(install_prefix)',
'<(PRODUCT_DIR)/libmbgl.a.ldflags',
]
}
]
},
'targets': [
{ 'target_name': 'install2',
'type': 'none',
'hard_dependency': 1,
'dependencies': [
'core',
'platform-<(platform_lib)',
'http-<(http_lib)',
'asset-<(asset_lib)',
'cache-<(cache_lib)',
'headless-<(headless_lib)',
'standalone',
],
}],
'copies': [
{ 'files': [ '<(PRODUCT_DIR)/libmbgl.a' ], 'destination': '<(install_prefix)/lib' },
{ 'files': [ '<(SHARED_INTERMEDIATE_DIR)/include/mbgl/util/version.hpp' ], 'destination': '<(install_prefix)/include/mbgl/util' },
],
'actions': [
{
'action_name': 'Copy header files',
'inputs': [ '../include/mbgl/mbgl.hpp' ],
'outputs': [ '<(install_prefix)/include/mbgl/mbgl.hpp' ],
'action': [ 'cp', '-r', 'include', '<(install_prefix)/' ]
},
{ 'action_name': 'mbgl-config',
'inputs': [
'../utils/mbgl-config/mbgl-config.template.sh',
'../utils/mbgl-config/build.sh',
],
'outputs': [
'<(install_prefix)/bin/mbgl-config',
],
'action': [
'./utils/mbgl-config/build.sh',
'<(install_prefix)',
'<(PRODUCT_DIR)/libmbgl.a.ldflags',
]
}
]
},
],
}

View File

@@ -15,6 +15,19 @@
'../platform/darwin/application_root.mm',
'../platform/darwin/asset_root.mm',
'../platform/darwin/image.mm',
'../platform/darwin/reachability.m',
'../include/mbgl/ios/MGLMapView.h',
'../platform/ios/MGLMapView.mm',
'../include/mbgl/ios/MGLStyleFunctionValue.h',
'../platform/ios/MGLStyleFunctionValue.m',
'../include/mbgl/ios/MGLTypes.h',
'../platform/ios/MGLTypes.m',
'../include/mbgl/ios/NSArray+MGLAdditions.h',
'../platform/ios/NSArray+MGLAdditions.m',
'../include/mbgl/ios/NSDictionary+MGLAdditions.h',
'../platform/ios/NSDictionary+MGLAdditions.m',
'../include/mbgl/ios/UIColor+MGLAdditions.h',
'../platform/ios/UIColor+MGLAdditions.m',
],
'variables': {
@@ -26,8 +39,14 @@
'<@(uv_static_libs)',
],
'ldflags': [
'-framework CoreGraphics',
'-framework CoreLocation',
'-framework ImageIO',
'-framework GLKit',
'-framework MobileCoreServices',
'-framework OpenGLES',
'-framework SystemConfiguration',
'-framework UIKit',
],
},
@@ -37,6 +56,7 @@
'xcode_settings': {
'OTHER_CPLUSPLUSFLAGS': [ '<@(cflags_cc)' ],
'CLANG_ENABLE_OBJC_ARC': 'YES',
},
'link_settings': {
@@ -50,6 +70,9 @@
'include_dirs': [
'../include',
],
'mac_bundle_resources': [
'<!@(find ./platform/ios/resources -type f)',
],
},
},
],

View File

@@ -39,6 +39,7 @@
'xcode_settings': {
'OTHER_CPLUSPLUSFLAGS': [ '<@(cflags_cc)' ],
'CLANG_ENABLE_OBJC_ARC': 'YES',
},
'link_settings': {

View File

@@ -16,7 +16,7 @@
'<(SHARED_INTERMEDIATE_DIR)/src/shader/shaders_gl.cpp',
'<(SHARED_INTERMEDIATE_DIR)/src/shader/shaders_gles2.cpp',
],
'action': ['<@(python)', 'scripts/build-shaders.py', '<(SHARED_INTERMEDIATE_DIR)', '<@(_inputs)'],
'action': ['scripts/build-shaders.py', '<(SHARED_INTERMEDIATE_DIR)', '<@(_inputs)'],
}
],
'direct_dependent_settings': {

View File

@@ -13,7 +13,7 @@
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/include/mbgl/util/version.hpp',
],
'action': ['<@(python)', '<@(_inputs)', '<(SHARED_INTERMEDIATE_DIR)', '<!@(git describe --tags --always --abbrev=0)', '<!@(git rev-parse HEAD)'],
'action': ['<@(_inputs)', '<(SHARED_INTERMEDIATE_DIR)', '<!@(git describe --tags --always --abbrev=0)', '<!@(git rev-parse HEAD)'],
}
],
'direct_dependent_settings': {

View File

@@ -0,0 +1,203 @@
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@protocol MGLMapViewDelegate;
/** An MGLMapView object provides an embeddable map interface, similar to the one provided by Apple's MapKit. You use this class to display map information and to manipulate the map contents from your application. You can center the map on a given coordinate, specify the size of the area you want to display, and style the features of the map to fit your application's use case.
*
* Use of MGLMapView requires a Mapbox API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/account/apps/). If you instantiate an MGLMapView from Interface Builder, rendering of the map won't begin until the accessToken property has been set.
*
* @warning Please note that you are responsible for getting permission to use the map data, and for ensuring your use adheres to the relevant terms of use. */
@interface MGLMapView : UIView
#pragma mark - Initializing a Map View
/** @name Initializing a Map View */
/** Initialize a map view with a given frame, style, and access token.
* @param frame The frame with which to initialize the map view.
* @param styleJSON The map stylesheet as JSON text.
* @param accessToken A Mapbox API access token.
* @return An initialized map view, or `nil` if the map view was unable to be initialized. */
- (instancetype)initWithFrame:(CGRect)frame styleJSON:(NSString *)styleJSON accessToken:(NSString *)accessToken;
/** Initialize a map view with a given frame, the default style, and an access token.
* @param frame The frame with which to initialize the map view.
* @param accessToken A Mapbox API access token.
* @return An initialized map view, or `nil` if the map view was unable to be initialized. */
- (instancetype)initWithFrame:(CGRect)frame accessToken:(NSString *)accessToken;
- (instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("Instantiating an MGLMapView requires setting a style and/or an access token.")));
#pragma mark - Authorizing Access
/** @name Authorizing Access */
/** Sets a Mapbox API access token for the map view.
* @param accessToken A Mapbox API token. */
- (void)setAccessToken:(NSString *)accessToken;
#pragma mark - Managing Constraints
/** @name Managing Constraints */
/** A view controller whose top and bottom layout guides to use for proper setup of constraints in the map view internals.
*
* Certain components of the map view, such as the heading compass and the data attribution button, need to be aware of the view controller layout in order to avoid positioning content under a top navigation bar or a bottom toolbar. */
@property (nonatomic, weak) UIViewController *viewControllerForLayoutGuides;
#pragma mark - Accessing Map Properties
/** @name Accessing Map Properties */
/** A Boolean value that determines whether the user may zoom the map.
*
* This property controls only user interactions with the map. If you set the value of this property to `NO`, you may still change the map zoom programmatically.
*
* The default value of this property is `YES`. */
@property(nonatomic, getter=isZoomEnabled) BOOL zoomEnabled;
/** A Boolean value that determines whether the user may scroll around the map.
*
* This property controls only user interactions with the map. If you set the value of this property to `NO`, you may still change the map location programmatically.
*
* The default value of this property is `YES`. */
@property(nonatomic, getter=isScrollEnabled) BOOL scrollEnabled;
/** A Boolean value that determines whether the user may rotate the map.
*
* This property controls only user interactions with the map. If you set the value of this property to `NO`, you may still rotate the map programmatically.
*
* The default value of this property is `YES`. */
@property(nonatomic, getter=isRotateEnabled) BOOL rotateEnabled;
#pragma mark - Accessing the Delegate
/** @name Accessing the Delegate */
// TODO
@property(nonatomic, weak) id<MGLMapViewDelegate> delegate;
#pragma mark - Manipulating the Visible Portion of the Map
/** @name Manipulating the Visible Portion of the Map */
/** The map coordinate at the center of the map view.
*
* Changing the value in this property centers the map on the new coordinate without changing the current zoom level.
*
* Changing the value of this property updates the map view immediately. If you want to animate the change, use the setCenterCoordinate:animated: method instead. */
@property (nonatomic) CLLocationCoordinate2D centerCoordinate;
/** Changes the center coordinate of the map and optionally animates the change.
* @param coordinate The new center coordinate for the map.
* @param animated Specify `YES` if you want the map view to scroll to the new location or `NO` if you want the map to display the new location immediately.
*
* Changing the center coordinate centers the map on the new coordinate without changing the current zoom level. */
- (void)setCenterCoordinate:(CLLocationCoordinate2D)coordinate animated:(BOOL)animated;
/** The zoom level of the map view.
*
* Changing the value in this property zooms the map in or out without changing the center coordinate. At zoom level 0, tiles cover the entire world map; at zoom level 1, tiles cover 1/4 of the world; at zoom level 2, tiles cover 1/16 of the world, and so on.
*
* Changing the value of this property updates the map view immediately. If you want to animate the change, use the setZoomLevel:animated: method instead. */
@property (nonatomic) double zoomLevel;
/** Changes the zoom level of the map and optionally animates the change.
* @param zoomLevel The new zoom level for the map.
* @param animated Specify `YES` if you want the map view to animate the change to the new zoom level or `NO` if you want the map to display the new zoom level immediately.
*
* Changing the zoom level scales the map without changing the current center coordinate. At zoom level 0, tiles cover the entire world map; at zoom level 1, tiles cover 1/4 of the world; at zoom level 2, tiles cover 1/16 of the world, and so on. */
- (void)setZoomLevel:(double)zoomLevel animated:(BOOL)animated;
/** Changes the center coordinate and zoom level of the and optionally animates the change.
* @param centerCoordinate The new center coordinate for the map.
* @param zoomLevel The new zoom level for the map.
* @param animated Specify `YES` if you want the map view to animate scrolling and zooming to the new location or `NO` if you want the map to display the new location immediately. */
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel animated:(BOOL)animated;
/** The heading of the map (measured in degrees) relative to true north.
*
* The value `0` means that the top edge of the map view corresponds to true north. The value `90` means the top of the map is pointing due east. The value `180` means the top of the map points due south, and so on. */
@property (nonatomic) CLLocationDirection direction;
/** Changes the heading of the map and optionally animates the changes.
* @param direction The heading of the map (measured in degrees) relative to true north.
* @param animated Specify `YES` if you want the map view to animate the change to the new heading or `NO` if you want the map to display the new heading immediately.
*
* Changing the heading rotates the map without changing the current center coordinate or zoom level. */
- (void)setDirection:(CLLocationDirection)direction animated:(BOOL)animated;
/** Resets the map rotation to a northern heading. */
- (void)resetNorth;
#pragma mark - Styling the Map
/** @name Styling the Map */
/** Sets the map style.
* @param styleJSON The map stylesheet as JSON text. */
- (void)setStyleJSON:(NSString *)styleJSON;
/** Returns the raw JSON style as a native dictionary object. */
- (NSDictionary *)getRawStyle;
/** Sets the raw JSON style as a native dictionary object with a transition animation.
* @param style The style JSON as a dictionary object. */
- (void)setRawStyle:(NSDictionary *)style;
/** Returns the names of the styles bundled with the library. */
- (NSArray *)bundledStyleNames;
/** Sets the map style to a named, bundled style.
* @param styleName The map style name to use. */
- (void)useBundledStyleNamed:(NSString *)styleName;
#pragma mark - Debugging
/** @name Debugging */
/** A Boolean value that determines whether map debugging information is shown.
*
* The default value of this property is `NO`. */
@property (nonatomic, getter=isDebugActive) BOOL debugActive;
/** Toggle the current value of debugActive. */
- (void)toggleDebug;
/** Resets the map to the minimum zoom level, a center coordinate of (0, 0), and a northern heading. */
- (void)resetPosition;
@end
// TODO
@protocol MGLMapViewDelegate <NSObject>
@optional
// Responding to Map Position Changes
// TODO
- (void)mapView:(MGLMapView *)mapView regionWillChangeAnimated:(BOOL)animated;
// TODO
- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
// Loading the Map Data
// TODO
- (void)mapViewWillStartLoadingMap:(MGLMapView *)mapView;
// TODO
- (void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView;
// TODO
- (void)mapViewDidFailLoadingMap:(MGLMapView *)mapView withError:(NSError *)error;
// TODO
- (void)mapViewWillStartRenderingMap:(MGLMapView *)mapView;
// TODO
- (void)mapViewDidFinishRenderingMap:(MGLMapView *)mapView fullyRendered:(BOOL)fullyRendered;
@end

View File

@@ -0,0 +1,23 @@
#import <UIKit/UIKit.h>
@interface MGLStyleFunctionValue : NSObject
+ (instancetype)linearFunctionWithBaseZoomLevel:(CGFloat)zBase
initialValue:(CGFloat)val
slope:(CGFloat)slope
minimumValue:(CGFloat)min
maximumValue:(CGFloat)max;
+ (instancetype)exponentialFunctionWithBaseZoomLevel:(CGFloat)zBase
initialValue:(CGFloat)val
slope:(CGFloat)slope
minimumValue:(CGFloat)min
maximumValue:(CGFloat)max;
+ (instancetype)minimumZoomLevelFunction:(CGFloat)minimumZoom;
+ (instancetype)maximumZoomLevelFunction:(CGFloat)maximumZoom;
+ (instancetype)stopsFunctionWithZoomLevelsAndValues:(NSNumber *)firstZoom, ... NS_REQUIRES_NIL_TERMINATION;
@end

View File

@@ -0,0 +1,17 @@
#import <Foundation/Foundation.h>
// style property value types
//
extern NSString *const MGLStyleValueTypeBoolean;
extern NSString *const MGLStyleValueTypeNumber;
extern NSString *const MGLStyleValueTypeNumberPair;
extern NSString *const MGLStyleValueTypeColor;
extern NSString *const MGLStyleValueTypeString;
// style property function types
//
extern NSString *const MGLStyleValueTypeFunctionMinimumZoom;
extern NSString *const MGLStyleValueTypeFunctionMaximumZoom;
extern NSString *const MGLStyleValueTypeFunctionLinear;
extern NSString *const MGLStyleValueTypeFunctionExponential;
extern NSString *const MGLStyleValueTypeFunctionStops;

View File

@@ -0,0 +1,7 @@
#import <Foundation/Foundation.h>
@interface NSArray (MGLAdditions)
- (NSMutableArray *)deepMutableCopy;
@end

View File

@@ -0,0 +1,7 @@
#import <Foundation/Foundation.h>
@interface NSDictionary (MGLAdditions)
- (NSMutableDictionary *)deepMutableCopy;
@end

View File

@@ -0,0 +1,11 @@
#import <UIKit/UIKit.h>
@interface UIColor (MGLAdditions)
+ (UIColor *)colorWithRGBAString:(NSString *)rgbaString;
- (NSString *)rgbaStringFromColor;
+ (UIColor *)colorWithHexString:(NSString *)hexString;
- (NSString *)hexStringFromColor;
@end

View File

@@ -1,2 +0,0 @@
#include <GL/glx.h>
#undef None

View File

@@ -5,9 +5,12 @@
#define MBGL_USE_CGL 1
#else
#define GL_GLEXT_PROTOTYPES
#include <mbgl/platform/default/glx.h>
#define MBGL_USE_GLX 1
#undef Status
typedef struct _XDisplay Display;
typedef struct __GLXcontextRec* GLXContext;
typedef struct __GLXFBConfigRec* GLXFBConfig;
typedef long unsigned int XID;
typedef XID GLXPbuffer;
#endif
#include <mbgl/map/view.hpp>

49
ios/FAQ.md Normal file
View File

@@ -0,0 +1,49 @@
# Mapbox GL for iOS FAQ
Mapbox GL is a completely new renderer technology which will eventually replace and/or merge Mapbox's existing iOS toolsets, the [Mapbox iOS SDK](http://www.mapbox.com/mapbox-ios-sdk/) and [MBXMapKit](https://www.mapbox.com/mbxmapkit/). This FAQ shares our current plans for that migration. The plans are subject to change as Mapbox GL matures, but we wanted to both clarify our thinking as well as set expectations for where things are headed.
### When will Mapbox GL be released?
The library is [open source](https://github.com/mapbox/mapbox-gl-native) right now, but an official, production-recommended release will come later in 2015.
### What iOS versions will be supported?
Mapbox GL currently supports iOS 7 and later. This will continue to be the case. MBXMapKit also supports iOS 7 and greater, but this does mean that moving from the iOS SDK will leave behind iOS 5 and 6.
### Will the API be similar to the Mapbox iOS SDK/MBXMapKit/MapKit?
Yes. We are shooting for bringing the Mapbox GL API in line with Apple's MapKit for the easiest transition ability.
MBXMapKit is already an add-on to MapKit, so Apple's `MKMapView` API is used directly.
The Mapbox iOS SDK is "workalike", since it descends from an [upstream open source project](https://github.com/Alpstein/route-me) that predates Apple's own MapKit. It uses similar concepts like annotations (with the difference that the map view delegate provides `CALayer` instances instead of `UIView`, the intention being that Mapbox GL will support `UIView`), similar API for managing the map view center, bounds, and zoom levels, and an `RMUserLocation` API that is very much like `MKUserLocation`. But the Mapbox iOS SDK also features unique APIs like extensible tile sources, offline caching, UTFGrid interactivity, and point annotation clustering.
### Will the iOS SDK's extra APIs make it over to Mapbox GL?
The intention is yes. This includes:
#### Tile sources
The SDK uses the `RMTileSource` protocol to allow for extensible remote and local raster tile sources, as well as custom on-the-fly raster tile generation. We are planning to build a transitional API in Mapbox GL that acts as a wrapper to `RMTileSource` so that existing sources can be used to plug into the main Mapbox GL source API.
#### Offline caching
Both the Mapbox iOS SDK and MBXMapKit feature robust support for offline caching of raster tiles and the SDK features support for [MBTiles](http://mbtiles.org) tile sources.
We're likely going to take a similar approach to both performance caching and offline maps as is done with the `0.3.0` release of MBXMapKit. That is, `NSURLCache` will be used for performance caching and specific, separate offline map database management will be used for fetching areas of map tiles. This is a cleaner design than exists in the SDK, which combines performance and offline caches and has a non-intuitive configuration API.
We will likely also port over MBTiles support to Mapbox GL.
#### UTFGrid interactivity
[UTFGrid](https://github.com/mapbox/utfgrid-spec) is a technology for enabling interactive features in raster tiles. Support for the technology is provided in the Mapbox iOS SDK with categories in `RMInteractiveSource` in combination with either `RMMapboxSource` or `RMMBTilesSource`.
Mapbox GL obsoletes this sort of pixel-based interactivity since the source data used for rendering can be queried on-device, so we are unlikely to port UTFGrid over to GL.
#### Annotation clustering
We're planning on adding support for point clustering to Mapbox GL and it will likely have a similar API to the SDK's. Clustering will happen on an individual style layer level. The performance for clustering, as well as annotations in general, will hopefully be better than in the SDK, since it will be done with direct OpenGL rendering instead of Core Animation layers.
### What will the migration path look like?
Ideally, the migration will be pretty lightweight because of the APIs supported above. There may be slight syntax changes, but they likely won't be more than would be expected from something like Mapbox iOS SDK version `1.x` to a hypothetical `2.x`.

33
ios/MapboxGL.podspec Normal file
View File

@@ -0,0 +1,33 @@
Pod::Spec.new do |m|
m.name = 'MapboxGL'
m.version = '0.1.0'
m.summary = 'Open source vector map solution for iOS with full styling capabilities.'
m.description = 'Open source OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa bindings.'
m.homepage = 'https://www.mapbox.com/blog/mapbox-gl/'
m.license = 'BSD'
m.author = { 'Mapbox' => 'mobile@mapbox.com' }
m.screenshot = 'https://raw.githubusercontent.com/mapbox/mapbox-gl-cocoa/master/pkg/screenshot.png'
m.social_media_url = 'https://twitter.com/Mapbox'
m.source = { :git => 'https://github.com/mapbox/mapbox-gl-cocoa.git', :tag => m.version.to_s }
m.platform = :ios
m.ios.deployment_target = '7.0'
m.source_files = 'dist/static/Headers/*.h'
m.requires_arc = true
m.resource_bundle = { 'MapboxGL' => 'dist/static/MapboxGL.bundle/*' }
m.frameworks = 'CoreLocation', 'Foundation', 'GLKit', 'SystemConfiguration', 'UIKit'
m.libraries = 'MapboxGL', 'c++', 'sqlite3', 'z'
m.vendored_libraries = 'dist/static/libMapboxGL.a'
m.xcconfig = { 'OTHER_CPLUSPLUSFLAGS' => '-std=gnu++11 -stdlib=libc++' }
end

68
ios/README.md Normal file
View File

@@ -0,0 +1,68 @@
# Mapbox GL for iOS
Use or edit this project to get access to vector maps (via [Mapbox Vector Tiles](https://www.mapbox.com/blog/vector-tiles)) and dynamic OpenGL-based styling in your iOS apps by using `MGLMapView`.
![](./screenshot.png)
## Installation
Currently in flux. See the parent `mapbox-gl-native` project `README` for details on building this library yourself.
Static and dynamic prebuilt binaries are coming back, as is CocoaPods support.
## Example usage
### Objective-C
```objective-c
MGLMapView *mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)
accessToken:@"<access token string>"];
[mapView setCenterCoordinate:CLLocationCoordinate2DMake(28.369334, -80.743779)
zoomLevel:13
animated:NO];
[mapView useBundledStyleNamed:@"outdoors"];
[self.view addSubview:mapView];
```
### Swift
```swift
let mapView = MGLMapView(frame: CGRect(x: 0, y: 0, width: 400, height: 400),
accessToken: "<access token string>")
mapView.setCenterCoordinate(CLLocationCoordinate2D(latitude: 46.049900, longitude: -122.095678),
zoomLevel: 12,
animated: false)
mapView.useBundledStyleNamed("outdoors")
view.addSubview(mapView)
```
## Development
If you'd like to contribute to this project, go up to [Mapbox GL native](https://github.com/mapbox/mapbox-gl-native) and clone the project.
## Testing
Currently in flux and not functioning.
## Requirements
* iOS 7+
* a sense of adventure
## Styling
See the [online style reference](https://www.mapbox.com/mapbox-gl-style-spec/) for the latest documentation. Contained within the `MapboxGL.bundle` assets are a couple of starter styles in JSON format.
The project will eventually get a programmatic styling API as well.
## Related Projects
* https://github.com/mapbox/mapbox-gl-style-spec
* https://github.com/mapbox/mapbox-gl-js
* https://github.com/mapbox/vector-tile-spec

7
ios/app/MBXAppDelegate.h Normal file
View File

@@ -0,0 +1,7 @@
#import <UIKit/UIKit.h>
@interface MBXAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

15
ios/app/MBXAppDelegate.m Normal file
View File

@@ -0,0 +1,15 @@
#import "MBXAppDelegate.h"
#import "MBXViewController.h"
@implementation MBXAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[MBXViewController new]];
[self.window makeKeyAndVisible];
return YES;
}
@end

View File

@@ -0,0 +1,5 @@
#import <UIKit/UIKit.h>
@interface MBXViewController : UIViewController
@end

View File

@@ -0,0 +1,266 @@
#import "MBXViewController.h"
#import <mbgl/ios/MGLMapView.h>
#import <mbgl/platform/darwin/settings_nsuserdefaults.hpp>
#import <CoreLocation/CoreLocation.h>
static UIColor *const kTintColor = [UIColor colorWithRed:0.120 green:0.550 blue:0.670 alpha:1.000];
static NSDictionary *const kStyles = @{
@"bright-v6": @"Bright",
@"basic-v6": @"Basic",
@"outdoors-v6": @"Outdoors",
@"satellite-v6": @"Satellite"
};
@interface MBXViewController () <UIActionSheetDelegate, CLLocationManagerDelegate>
@property (nonatomic) MGLMapView *mapView;
@property (nonatomic) CLLocationManager *locationManager;
@end
@implementation MBXViewController
mbgl::Settings_NSUserDefaults *settings = nullptr;
#pragma mark - Setup
- (id)init
{
self = [super init];
if (self)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveState:) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restoreState:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *accessToken = [[NSProcessInfo processInfo] environment][@"MAPBOX_ACCESS_TOKEN"];
if (accessToken) {
// Store to preferences so that we can launch the app later on without having to specify
// token.
[[NSUserDefaults standardUserDefaults] setObject:accessToken forKey:@"access_token"];
} else {
// Try to retrieve from preferences, maybe we've stored them there previously and can reuse
// the token.
accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"];
}
if ( ! accessToken) NSLog(@"No access token set. Mapbox vector tiles won't work.");
self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds accessToken:accessToken];
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.mapView];
self.mapView.viewControllerForLayoutGuides = self;
self.view.tintColor = kTintColor;
self.navigationController.navigationBar.tintColor = kTintColor;
self.mapView.tintColor = kTintColor;
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"settings.png"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(showSettings)];
UIButton *titleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[titleButton setFrame:CGRectMake(0, 0, 120, 40)];
[titleButton setTitle:[[kStyles allValues] firstObject] forState:UIControlStateNormal];
[titleButton setTitleColor:kTintColor forState:UIControlStateNormal];
[titleButton addTarget:self action:@selector(cycleStyles) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.titleView = titleButton;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"locateUser.png"]
style:UIBarButtonItemStylePlain
target:self
action:@selector(locateUser)];
settings = new mbgl::Settings_NSUserDefaults();
[self restoreState:nil];
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
- (void)saveState:(NSNotification *)notification
{
if (self.mapView && settings)
{
settings->longitude = self.mapView.centerCoordinate.longitude;
settings->latitude = self.mapView.centerCoordinate.latitude;
settings->zoom = self.mapView.zoomLevel;
settings->bearing = self.mapView.direction;
settings->debug = self.mapView.isDebugActive;
settings->save();
}
}
- (void)restoreState:(NSNotification *)notification
{
if (self.mapView && settings) {
settings->load();
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(settings->latitude, settings->longitude) zoomLevel:settings->zoom animated:NO];
self.mapView.direction = settings->bearing;
[self.mapView setDebugActive:settings->debug];
}
}
#pragma clang diagnostic pop
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
#pragma mark - Actions
- (void)showSettings
{
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Map Settings"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Reset North", @"Reset Position", @"Toggle Debug", nil];
[sheet showFromBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES];
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == actionSheet.firstOtherButtonIndex)
{
[self.mapView resetNorth];
}
else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1)
{
[self.mapView resetPosition];
}
else if (buttonIndex == actionSheet.firstOtherButtonIndex + 2)
{
[self.mapView toggleDebug];
}
}
- (void)cycleStyles
{
UIButton *titleButton = (UIButton *)self.navigationItem.titleView;
NSString *styleName = [titleButton titleForState:UIControlStateNormal];
if ( ! styleName)
{
styleName = [[kStyles allKeys] firstObject];
}
else
{
NSUInteger index = [[kStyles allValues] indexOfObject:styleName] + 1;
if (index == [[kStyles allKeys] count]) index = 0;
styleName = [[kStyles allKeys] objectAtIndex:index];
}
[self.mapView useBundledStyleNamed:styleName];
[titleButton setTitle:kStyles[styleName] forState:UIControlStateNormal];
}
- (void)locateUser
{
if ( ! self.locationManager)
{
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;
}
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)
{
[[[UIAlertView alloc] initWithTitle:@"Authorization Denied"
message:@"Please enable location services for this app in Privacy settings."
delegate:nil
cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show];
}
else
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)])
{
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse)
{
[self.locationManager startUpdatingLocation];
}
else
{
[_locationManager requestWhenInUseAuthorization];
}
}
else
{
[self.locationManager startUpdatingLocation];
}
#else
[self.locationManager startUpdatingLocation];
#endif
}
}
#pragma mark - Destruction
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (settings)
{
[self saveState:nil];
delete settings;
settings = nullptr;
}
}
#pragma mark - Location
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status)
{
case kCLAuthorizationStatusAuthorizedAlways:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
case kCLAuthorizationStatusAuthorizedWhenInUse:
#endif
{
[manager startUpdatingLocation];
break;
}
default:
{
}
}
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *latestLocation = locations.lastObject;
if ([latestLocation distanceFromLocation:[[CLLocation alloc] initWithLatitude:self.mapView.centerCoordinate.latitude longitude:self.mapView.centerCoordinate.longitude]] > 100)
{
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(latestLocation.coordinate.latitude, latestLocation.coordinate.longitude) zoomLevel:17 animated:YES];
}
[self.locationManager stopUpdatingLocation];
}
#pragma clang diagnostic pop
@end

3
ios/app/README.md Normal file
View File

@@ -0,0 +1,3 @@
This is the app for use in the development of Mapbox GL for iOS.
If you want to run this app, head up to [`mapbox-gl-native`](https://github.com/mapbox/mapbox-gl-native) and follow the iOS installation instructions there.

51
ios/app/app-info.plist Normal file
View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.mapbox.MapboxGL</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1</string>
<key>CFBundleSignature</key>
<string>MBGL</string>
<key>CFBundleVersion</key>
<string>0.0.1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>(c) 2014 Mapbox</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>The map will be centered on the user's location.</string>
<key>UILaunchStoryboardName</key>
<string>Default</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
ios/app/img/Icon-40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

BIN
ios/app/img/Icon-40@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
ios/app/img/Icon-60.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
ios/app/img/Icon-60@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
ios/app/img/Icon-72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
ios/app/img/Icon-72@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
ios/app/img/Icon-76.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
ios/app/img/Icon-76@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
ios/app/img/Icon-Small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
ios/app/img/Icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
ios/app/img/Icon@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
ios/app/img/iTunesArtwork Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
ios/app/img/locateUser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
ios/app/img/settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

BIN
ios/app/img/settings@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

10
ios/app/main.m Normal file
View File

@@ -0,0 +1,10 @@
#import <UIKit/UIKit.h>
#import "MBXAppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([MBXAppDelegate class]));
}
}

57
ios/app/mapboxgl-app.gyp Normal file
View File

@@ -0,0 +1,57 @@
{
'includes': [
'../../gyp/common.gypi',
],
'targets': [
{ 'target_name': 'iosapp',
'product_name': 'Mapbox GL',
'type': 'executable',
'product_extension': 'app',
'mac_bundle': 1,
'mac_bundle_resources': [
'<!@(find ./img -type f)',
],
'dependencies': [
'../../mbgl.gyp:bundle_styles',
'../../mbgl.gyp:core',
'../../mbgl.gyp:platform-<(platform_lib)',
'../../mbgl.gyp:http-<(http_lib)',
'../../mbgl.gyp:asset-<(asset_lib)',
'../../mbgl.gyp:cache-<(cache_lib)',
],
'sources': [
'./main.m',
'./MBXAppDelegate.h',
'./MBXAppDelegate.m',
'./MBXViewController.h',
'./MBXViewController.mm',
'../../platform/darwin/settings_nsuserdefaults.mm',
],
'xcode_settings': {
'SDKROOT': 'iphoneos',
'SUPPORTED_PLATFORMS': 'iphonesimulator iphoneos',
'INFOPLIST_FILE': 'app-info.plist',
'TARGETED_DEVICE_FAMILY': '1,2',
'COMBINE_HIDPI_IMAGES': 'NO', # don't merge @2x.png images into .tiff files
'CLANG_ENABLE_OBJC_ARC': 'YES',
},
'configurations': {
'Debug': {
'xcode_settings': {
'CODE_SIGN_IDENTITY': 'iPhone Developer',
},
},
'Release': {
'xcode_settings': {
'CODE_SIGN_IDENTITY': 'iPhone Distribution',
'ARCHS': [ "armv7", "armv7s", "arm64", "i386", "x86_64" ],
},
},
},
}
]
}

24
ios/docs/install_docs.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
if [ -z `which appledoc` ]; then
echo "Unable to find appledoc. Consider installing it from source or Homebrew."
exit 1
fi
VERSION=$( git tag | sort -r | sed -n '1p' )
echo "Creating new docs for $VERSION..."
echo
appledoc \
--output /tmp/`uuidgen` \
--project-name "Mapbox GL $VERSION" \
--project-company Mapbox \
--create-docset \
--company-id com.mapbox \
--ignore app \
--ignore dist \
--ignore pkg \
--ignore test \
--ignore .m \
--ignore .mm \
.

7
ios/docs/remove_docs.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
echo
echo "Removing docs from ~/Library/Developer/Shared/Documentation/DocSets..."
echo
rm -rfv ~/Library/Developer/Shared/Documentation/DocSets/com.mapbox.Mapbox-GL-*

BIN
ios/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

View File

@@ -8,19 +8,20 @@
'./gyp/standalone.gypi',
'./gyp/core.gypi',
'./gyp/none.gypi',
'./gyp/install.gypi',
],
'conditions': [
['headless_lib == "cgl"', { 'includes': [ './gyp/headless-cgl.gypi' ] } ],
['headless_lib == "glx"', { 'includes': [ './gyp/headless-glx.gypi' ] } ],
['platform_lib == "osx"', { 'includes': [ './gyp/platform-osx.gypi' ] } ],
['platform_lib == "ios"', { 'includes': [ './gyp/platform-ios.gypi' ] } ],
['headless_lib == "cgl" and host == "osx"', { 'includes': [ './gyp/headless-cgl.gypi' ] } ],
['headless_lib == "glx" and host == "linux"', { 'includes': [ './gyp/headless-glx.gypi' ] } ],
['platform_lib == "osx" and host == "osx"', { 'includes': [ './gyp/platform-osx.gypi' ] } ],
['platform_lib == "ios" and host == "ios"', { 'includes': [ './gyp/platform-ios.gypi' ] } ],
['platform_lib == "linux"', { 'includes': [ './gyp/platform-linux.gypi' ] } ],
['platform_lib == "android"', { 'includes': [ './gyp/platform-android.gypi' ] } ],
['platform_lib == "android" and host == "android"', { 'includes': [ './gyp/platform-android.gypi' ] } ],
['http_lib == "curl"', { 'includes': [ './gyp/http-curl.gypi' ] } ],
['http_lib == "nsurl"', { 'includes': [ './gyp/http-nsurl.gypi' ] } ],
['http_lib == "nsurl" and (host == "osx" or host == "ios")', { 'includes': [ './gyp/http-nsurl.gypi' ] } ],
['asset_lib == "fs"', { 'includes': [ './gyp/asset-fs.gypi' ] } ],
['asset_lib == "zip"', { 'includes': [ './gyp/asset-zip.gypi' ] } ],
['cache_lib == "sqlite"', { 'includes': [ './gyp/cache-sqlite.gypi' ] } ],
['install_prefix != ""', { 'includes': ['./gyp/install.gypi' ] } ],
],
}

View File

@@ -10,7 +10,6 @@ void NSLogBackend::record(EventSeverity severity, Event event, const std::string
NSString *message =
[[NSString alloc] initWithBytes:msg.data() length:msg.size() encoding:NSUTF8StringEncoding];
NSLog(@"[%s] %s: %@", EventSeverityClass(severity).c_str(), EventClass(event).c_str(), message);
[message release];
}
void NSLogBackend::record(EventSeverity severity, Event event, const char *format, ...) {
@@ -37,7 +36,6 @@ void NSLogBackend::record(EventSeverity severity, Event event, int64_t code,
[[NSString alloc] initWithBytes:msg.data() length:msg.size() encoding:NSUTF8StringEncoding];
NSLog(@"[%s] %s: (%lld) %@", EventSeverityClass(severity).c_str(), EventClass(event).c_str(),
code, message);
[message release];
}
}

View File

@@ -13,7 +13,6 @@ std::string uppercase(const std::string &string) {
NSString *uppercase = [original uppercaseString];
const std::string result{[uppercase cStringUsingEncoding : NSUTF8StringEncoding],
[uppercase lengthOfBytesUsingEncoding:NSUTF8StringEncoding]};
[original release];
return result;
}
@@ -25,7 +24,6 @@ std::string lowercase(const std::string &string) {
NSString *lowercase = [original lowercaseString];
const std::string result{[lowercase cStringUsingEncoding : NSUTF8StringEncoding],
[lowercase lengthOfBytesUsingEncoding:NSUTF8StringEncoding]};
[original release];
return result;
}

View File

@@ -3,6 +3,10 @@
#include <cstring>
#include <stdexcept>
#if MBGL_USE_GLX
#include <GL/glx.h>
#endif
namespace mbgl {
HeadlessDisplay::HeadlessDisplay() {
@@ -52,7 +56,7 @@ HeadlessDisplay::HeadlessDisplay() {
// We're creating a dummy pbuffer anyway that we're not using.
static int pixelFormat[] = {
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
0
None
};
int configs = 0;

View File

@@ -28,6 +28,8 @@ CGLProc CGLGetProcAddress(const char *proc) {
CFRelease(name);
return symbol;
}
#elif MBGL_USE_GLX
#include <GL/glx.h>
#endif
namespace mbgl {
@@ -104,7 +106,7 @@ void HeadlessView::createContext() {
if (!glContext) {
// Try to create a legacy context
glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, 0, True);
glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
if (glContext) {
if (!glXIsDirect(xDisplay, glContext)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "Failed to create direct OpenGL Legacy context");
@@ -123,7 +125,7 @@ void HeadlessView::createContext() {
int pbufferAttributes[] = {
GLX_PBUFFER_WIDTH, 8,
GLX_PBUFFER_HEIGHT, 8,
0
None
};
glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
#endif

1616
platform/ios/MGLMapView.mm Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,190 @@
#import "MGLStyleFunctionValue.h"
#import "MGLTypes.h"
@interface MGLStyleFunctionValue ()
@property (nonatomic) NSString *functionType;
@property (nonatomic) NSDictionary *stops;
@property (nonatomic) CGFloat zBase;
@property (nonatomic) CGFloat val;
@property (nonatomic) CGFloat slope;
@property (nonatomic) CGFloat min;
@property (nonatomic) CGFloat max;
@property (nonatomic) CGFloat minimumZoom;
@property (nonatomic) CGFloat maximumZoom;
- (NSDictionary *)rawStyle;
@end
@implementation MGLStyleFunctionValue
- (id)initWithFunctionType:(NSString *)functionType
stops:(NSDictionary *)stops
zBase:(CGFloat)zBase
val:(CGFloat)val
slope:(CGFloat)slope
min:(CGFloat)min
max:(CGFloat)max
minimumZoom:(CGFloat)minimumZoom
maximumZoom:(CGFloat)maximumZoom
{
self = [super init];
if (self)
{
_functionType = functionType;
_stops = stops;
_zBase = zBase;
_val = val;
_slope = slope;
_min = min;
_max = max;
_minimumZoom = minimumZoom;
_maximumZoom = maximumZoom;
}
return self;
}
- (id)rawStyle
{
if ([self.functionType isEqualToString:MGLStyleValueTypeFunctionMinimumZoom])
{
return @[ @"min", @(self.minimumZoom) ];
}
else if ([self.functionType isEqualToString:MGLStyleValueTypeFunctionMaximumZoom])
{
return @[ @"max", @(self.maximumZoom) ];
}
else if ([self.functionType isEqualToString:MGLStyleValueTypeFunctionLinear])
{
return @[ @"linear", @(self.zBase), @(self.val), @(self.slope), @(self.min), @(self.max) ];
}
else if ([self.functionType isEqualToString:MGLStyleValueTypeFunctionExponential])
{
return @[ @"exponential", @(self.zBase), @(self.val), @(self.slope), @(self.min), @(self.max) ];
}
else if ([self.functionType isEqualToString:MGLStyleValueTypeFunctionStops])
{
NSMutableArray *returnArray = [NSMutableArray array];
for (NSNumber *z in [self.stops allKeys])
{
[returnArray addObject:@{ @"z" : z, @"val" : self.stops[z] }];
}
[returnArray insertObject:@"stops" atIndex:0];
return returnArray;
}
return nil;
}
+ (instancetype)stopsFunctionWithZoomLevelsAndValues:(NSNumber *)firstZoom, ...
{
NSMutableArray *numbersArray = [NSMutableArray array];
va_list args;
va_start(args, firstZoom);
for (NSNumber *arg = firstZoom; arg != nil; arg = va_arg(args, NSNumber *))
{
[numbersArray addObject:arg];
}
va_end(args);
NSAssert([numbersArray count] % 2 == 0, @"invalid number of arguments");
NSMutableDictionary *stops = [NSMutableDictionary dictionary];
for (NSUInteger i = 0; i < [numbersArray count]; i = i + 2)
{
stops[numbersArray[i]] = stops[numbersArray[i + 1]];
}
return [[self alloc] initWithFunctionType:MGLStyleValueTypeFunctionStops
stops:stops
zBase:0
val:0
slope:0
min:0
max:0
minimumZoom:0
maximumZoom:0];
}
+ (instancetype)linearFunctionWithBaseZoomLevel:(CGFloat)zBase
initialValue:(CGFloat)val
slope:(CGFloat)slope
minimumValue:(CGFloat)min
maximumValue:(CGFloat)max
{
NSAssert(zBase >= 0 && zBase <= 18, @"invalid base zoom level");
NSAssert(min < max, @"minimum value must be less than maximum value");
return [[self alloc] initWithFunctionType:MGLStyleValueTypeFunctionLinear
stops:nil
zBase:zBase
val:val
slope:slope
min:min
max:max
minimumZoom:0
maximumZoom:0];
}
+ (instancetype)exponentialFunctionWithBaseZoomLevel:(CGFloat)zBase
initialValue:(CGFloat)val
slope:(CGFloat)slope
minimumValue:(CGFloat)min
maximumValue:(CGFloat)max
{
NSAssert(zBase >= 0 && zBase <= 18, @"invalid base zoom level");
NSAssert(min < max, @"minimum value must be less than maximum value");
return [[self alloc] initWithFunctionType:MGLStyleValueTypeFunctionExponential
stops:nil
zBase:zBase
val:val
slope:slope
min:min
max:max
minimumZoom:0
maximumZoom:0];
}
+ (instancetype)minimumZoomLevelFunction:(CGFloat)minimumZoom
{
NSAssert(minimumZoom >= 0 && minimumZoom <= 18, @"invalid minimum zoom value");
return [[self alloc] initWithFunctionType:MGLStyleValueTypeFunctionMinimumZoom
stops:nil
zBase:0
val:0
slope:0
min:0
max:0
minimumZoom:minimumZoom
maximumZoom:0];
}
+ (instancetype)maximumZoomLevelFunction:(CGFloat)maximumZoom
{
NSAssert(maximumZoom >= 0 && maximumZoom <= 18, @"invalid maximum zoom value");
return [[self alloc] initWithFunctionType:MGLStyleValueTypeFunctionMaximumZoom
stops:nil
zBase:0
val:0
slope:0
min:0
max:0
minimumZoom:0
maximumZoom:maximumZoom];
}
@end

24
platform/ios/MGLTypes.m Normal file
View File

@@ -0,0 +1,24 @@
#import "MGLTypes.h"
NSString *const MGLStyleKeyGeneric = @"MGLStyleKeyGeneric";
NSString *const MGLStyleKeyFill = @"MGLStyleKeyFill";
NSString *const MGLStyleKeyLine = @"MGLStyleKeyLine";
NSString *const MGLStyleKeyIcon = @"MGLStyleKeyIcon";
NSString *const MGLStyleKeyText = @"MGLStyleKeyText";
NSString *const MGLStyleKeyRaster = @"MGLStyleKeyRaster";
NSString *const MGLStyleKeyComposite = @"MGLStyleKeyComposite";
NSString *const MGLStyleKeyBackground = @"MGLStyleKeyBackground";
NSString *const MGLStyleValueTypeBoolean = @"MGLStyleValueTypeBoolean";
NSString *const MGLStyleValueTypeNumber = @"MGLStyleValueTypeNumber";
NSString *const MGLStyleValueTypeNumberPair = @"MGLStyleValueTypeNumberPair";
NSString *const MGLStyleValueTypeColor = @"MGLStyleValueTypeColor";
NSString *const MGLStyleValueTypeString = @"MGLStyleValueTypeString";
NSString *const MGLStyleValueFunctionAllowed = @"MGLStyleValueFunctionAllowed";
NSString *const MGLStyleValueTypeFunctionMinimumZoom = @"MGLStyleValueTypeFunctionMinimumZoom";
NSString *const MGLStyleValueTypeFunctionMaximumZoom = @"MGLStyleValueTypeFunctionMaximumZoom";
NSString *const MGLStyleValueTypeFunctionLinear = @"MGLStyleValueTypeFunctionLinear";
NSString *const MGLStyleValueTypeFunctionExponential = @"MGLStyleValueTypeFunctionExponential";
NSString *const MGLStyleValueTypeFunctionStops = @"MGLStyleValueTypeFunctionStops";

View File

@@ -0,0 +1,10 @@
#import "NSArray+MGLAdditions.h"
@implementation NSArray (MGLAdditions)
- (NSMutableArray *)deepMutableCopy
{
return (NSMutableArray *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)self, kCFPropertyListMutableContainersAndLeaves));
}
@end

View File

@@ -0,0 +1,10 @@
#import "NSDictionary+MGLAdditions.h"
@implementation NSDictionary (MGLAdditions)
- (NSMutableDictionary *)deepMutableCopy
{
return (NSMutableDictionary *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)self, kCFPropertyListMutableContainersAndLeaves));
}
@end

View File

@@ -0,0 +1,167 @@
#import "UIColor+MGLAdditions.h"
/* Portions based on Erica Sadun's uicolor-utilities
https://github.com/erica/uicolor-utilities */
@interface UIColor (MGLAdditionsPrivate)
+ (UIColor *)colorWithRGBHex:(UInt32)hex;
- (CGColorSpaceModel)colorSpaceModel;
- (BOOL)canProvideRGBComponents;
- (BOOL)red:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha;
- (UInt32)rgbHex;
@end
@implementation UIColor (MGLAdditions)
+ (UIColor *)colorWithRGBAString:(NSString *)rgbaString
{
UIColor *color;
NSString *numberString = [rgbaString stringByReplacingOccurrencesOfString:@"rgba("
withString:@""];
numberString = [numberString stringByReplacingOccurrencesOfString:@"rgb("
withString:@""];
numberString = [numberString stringByReplacingOccurrencesOfString:@")"
withString:@""];
NSArray *numbers = [numberString componentsSeparatedByString:@","];
if ([rgbaString hasPrefix:@"rgb("] && [numbers count] == 3)
{
color = [UIColor colorWithRed:[numbers[0] floatValue] / 255
green:[numbers[1] floatValue] / 255
blue:[numbers[2] floatValue] / 255
alpha:1.0];
}
else if ([rgbaString hasPrefix:@"rgba("] && [numbers count] == 4)
{
color = [UIColor colorWithRed:[numbers[0] floatValue] / 255
green:[numbers[1] floatValue] / 255
blue:[numbers[2] floatValue] / 255
alpha:[numbers[3] floatValue]];
}
return color;
}
- (NSString *)rgbaStringFromColor
{
CGFloat r,g,b,a;
[self getRed:&r green:&g blue:&b alpha:&a];
r *= 255;
g *= 255;
b *= 255;
a *= 255;
return [NSString stringWithFormat:@"rgba(%lu,%lu,%lu,%lu)", (unsigned long)r, (unsigned long)g, (unsigned long)b, (unsigned long)a];
}
+ (UIColor *)colorWithRGBHex:(UInt32)hex
{
int r = (hex >> 16) & 0xFF;
int g = (hex >> 8) & 0xFF;
int b = (hex) & 0xFF;
return [UIColor colorWithRed:r / 255.0f
green:g / 255.0f
blue:b / 255.0f
alpha:1.0f];
}
- (CGColorSpaceModel)colorSpaceModel
{
return CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor));
}
- (BOOL)canProvideRGBComponents
{
switch (self.colorSpaceModel)
{
case kCGColorSpaceModelRGB:
case kCGColorSpaceModelMonochrome:
{
return YES;
}
default:
{
return NO;
}
}
}
- (BOOL)red:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha
{
const CGFloat *components = CGColorGetComponents(self.CGColor);
CGFloat r,g,b,a;
switch (self.colorSpaceModel)
{
case kCGColorSpaceModelMonochrome:
{
r = g = b = components[0];
a = components[1];
break;
}
case kCGColorSpaceModelRGB:
{
r = components[0];
g = components[1];
b = components[2];
a = components[3];
break;
}
default:
{
return NO;
}
}
if (red) *red = r;
if (green) *green = g;
if (blue) *blue = b;
if (alpha) *alpha = a;
return YES;
}
- (UInt32)rgbHex
{
NSAssert(self.canProvideRGBComponents, @"Must be a RGB color to use rgbHex");
CGFloat r, g, b, a;
if ( ! [self red:&r green:&g blue:&b alpha:&a])
return 0;
r = fminf(fmaxf(r, 0.0f), 1.0f);
g = fminf(fmaxf(g, 0.0f), 1.0f);
b = fminf(fmaxf(b, 0.0f), 1.0f);
return (((int)roundf(r * 255)) << 16) | (((int)roundf(g * 255)) << 8) | (((int)roundf(b * 255)));
}
- (NSString *)hexStringFromColor
{
return [NSString stringWithFormat:@"%0.6X", (unsigned int)(self.rgbHex)];
}
+ (UIColor *)colorWithHexString:(NSString *)hexString
{
NSScanner *scanner = [NSScanner scannerWithString:[hexString stringByReplacingOccurrencesOfString:@"#" withString:@""]];
unsigned hexNum;
if ( ! [scanner scanHexInt:&hexNum])
return nil;
return [UIColor colorWithRGBHex:hexNum];
}
@end

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

0
scripts/build-shaders.py Normal file → Executable file
View File

0
scripts/build-version.py Normal file → Executable file
View File

25
scripts/ios_travis/add-key.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
# This is all taken from http://www.objc.io/issue-6/travis-ci.html
# Create a custom keychain
security create-keychain -p travis ios-build.keychain
# Make the custom keychain default, so xcodebuild will use it for signing
security default-keychain -s ios-build.keychain
# Unlock the keychain
security unlock-keychain -p travis ios-build.keychain
# Set keychain timeout to 1 hour for long builds
# see http://www.egeek.me/2013/02/23/jenkins-and-xcode-user-interaction-is-not-allowed/
security set-keychain-settings -t 3600 -l ~/Library/Keychains/ios-build.keychain
# Add certificates to keychain and allow codesign to access them
security import ./scripts/ios_travis/apple.crt -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
security import ./scripts/ios_travis/ios-dist.cer -k ~/Library/Keychains/ios-build.keychain -T /usr/bin/codesign
security import ./scripts/ios_travis/ios-dist.p12 -k ~/Library/Keychains/ios-build.keychain -P $IOS_KEY_PASSWORD -T /usr/bin/codesign
# Put the provisioning profile in place
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "./scripts/ios_travis/$IOS_PROFILE_NAME.mobileprovision" ~/Library/MobileDevice/Provisioning\ Profiles/

Binary file not shown.

View File

@@ -0,0 +1,30 @@
U2FsdGVkX1/Dn0fx6y0q6CHTK5UmCnel5Nw0kQlpeCqrqpWvXnYS//Ep0updcMIQ
xj1hu+baBWjw7ccysFG/zcReSh/xgP6JrW7QKiA/kIQvqOvH0vhtzvDsnAQCB52T
VWVy492mIwFRCBANVTPbdmBbVIeHAkeQcrVkFJJIKOv4dC+CFAw9ArHm8iYrg7FV
FDK3cmrfR/pgvlQ1lQDa1C0vV1k/R5KuhqwDM3xMML1WbuBlR0RRHccs4xJRmRV7
NuAuWg2Ob+p5gOW4L3+7PnBTBgxUZl2nbukd3oUlAPBOxgwwbgQSJPDvnsw2zmgp
uv2X0Q0/fT9R8VxuoSXYkLkgIlOnVVRpyG4C4ou7HPS8VDiLP5iRWKx2PoTvaBLz
9lNPTXhXu45n2k9L9SbkYk0024u6I8x9EkAmu0wU/rQpdudw4uLO7Pxz7BZHq3/D
frwBMvtQXRogeQcsi3dKmsISrxdSEO1hax6toVnqujPSXKmFOMHXyhqJg/K9DDhs
8GAUUO0cVfAaviofVFBZAXwkOd0SaYWz3WY4qHOZHnFiuGN0MCd2lXe5kVKFXRdE
6ElXMm2+M0YLH+L55MA79hIDjqjv9JXTAAKpLy5wsOkMYEaaXvevdAEhkSW9QzIh
HGUqBED5jqdrNlm7qOPSMWDcB/9FlnizKFsqrZOjquWFQZ4L34t++8FPT0ipxKCI
XkYxBqVesZlHBOLPBYQ2bdJUuYaACkyMtB5eRebEieoWRXTB0aD4otvh6F6MYpiY
4q66GO3faCnPxcZY4OxxwSSuyotBP8qKJcACqf3/Ji0nt42IHOIWJmiwROjBzMQ2
DgYLtjsi1/b8eXLO5g+6S8o404j8g+2Z2rYXG+Hw6TaxY5bXrAH51fbUNDJP6qFR
X3K3q8YvJlXcKIU6aZi5CDqaJUz6e22FvsOeWVHjdQYB23kk+LWYQY58hvkFUDXd
/Nn2FxGPn80280sF4s8EX77YEXLGLqIo293Yg9F9JBwrq76ObY6DJbRlB4EG0Hx+
vo0WJhEWHahu2uCfwqMJPDhMTGYcYRdHcNSepJlbj+gFTmH8bdKZGI/g13ZsDYEK
HKP72rtaGQT4JYkS06TC6/Vvi+0+PxXr9SKbODCskN2yJpp0S2wXy8H6IwlpPe1R
v82oCJQAXrcD8wd65TR2Q7fg4akHzI9VX1q8UGjzNt/Y/EsPEVv48PM/zngk/Hat
Ptq6SoOFAj/JqbXOMuW0fidBI7uhq5575lgxaQ+VL4nKdDrdoHZXWJgjG/ZQO1j4
8o12Z+Fk8tNpMPofJaAf3ebuArAE/IUDK7KKB7UoSwT1XPOFI9gCVtG654i7CAtN
LfkDruwjTcD2XyaVLcVTeDUr2wMMrugE+OS4B/d0nD7jU4hVHTVn5fJxRiAFx+ql
cBG/TIf951aDZ1x7eIj4xhehletdeWTZ2wGT8RJcFPD3LIB1hddeDIFQrkfEP7Gp
IY+VdYo3tZtYcj9x0dXey/n9y0kxZw2w8oAY5iJB7NydeSANL4btPWO8y4KxXta9
P+HNq01JS78ufYxfIOnOxD8l7YtD6Z6Evr1elzGFJOzRl4nCbPUg+VXekR94Lmf8
0MBLgyG6xSoRBHvIYK6SRHEc+NuWvyfZGSOKBQVTwvf4/y4+xGcbPZy/YnUX6u+/
zRWaYPJBdRhTrwAqawz9ZLL65uFYM7jhpZPEYGhOVqFoarNsy0m0gF5HNy8r/s71
N1DBKUyVzdhR+4JZEHkkAr8JnN108d1uDIkaiI1F+hLCK2m5wnMYlZBMj2pP4kSC
1E7JiIr/EKDiIHE7rOzf3yTYwug0xusBDdNTappMzTRsTCEyJf330k3kS7y0+zoH
lwtG/9HS6qcwPY2h5buxTb6v9xQqmyWNT28Q8qEb3h8b2XS/NUyB9SQvRpkn9oUR

View File

@@ -0,0 +1,32 @@
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

View File

@@ -0,0 +1,153 @@
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
mCKBZzE+OCJOYS4bO4/Lbg==

View File

@@ -0,0 +1,4 @@
#!/bin/sh
security delete-keychain ios-build.keychain
rm -f "~/Library/MobileDevice/Provisioning Profiles/$IOS_PROFILE_NAME.mobileprovision"

75
scripts/package_ios.sh Executable file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env bash
set -e
set -o pipefail
set -u
NAME=MapboxGL
OUTPUT=build/ios/pkg
IOS_SDK_VERSION=8.1
LIBUV_VERSION=0.10.28
function step { >&2 echo -e "\033[1m\033[36m* $@\033[0m"; }
function finish { >&2 echo -en "\033[0m"; }
trap finish EXIT
rm -rf ${OUTPUT}
mkdir -p "${OUTPUT}"/static
step "Recording library version..."
VERSION="${OUTPUT}"/static/version.txt
echo -n "https://github.com/mapbox/mapbox-gl-native/commit/" > ${VERSION}
HASH=`git log | head -1 | awk '{ print $2 }' | cut -c 1-10` && true
echo -n "mapbox-gl-native "
echo ${HASH}
echo ${HASH} >> ${VERSION}
step "Creating build files..."
export MASON_PLATFORM=ios
export BUILDTYPE=${BUILDTYPE:-Release}
export HOST=ios
make Xcode/mbgl
step "Building iOS targets..."
xcodebuild -sdk iphoneos${IOS_SDK_VERSION} \
ARCHS="arm64 armv7 armv7s" \
-project ./build/ios/mbgl.xcodeproj \
-configuration ${BUILDTYPE} \
-target everything \
-jobs `sysctl -n hw.ncpu` | xcpretty -c
step "Building iOS Simulator targets..."
xcodebuild -sdk iphonesimulator${IOS_SDK_VERSION} \
ARCHS="x86_64 i386" \
-project ./build/ios/mbgl.xcodeproj \
-configuration ${BUILDTYPE} \
-target everything \
-jobs `sysctl -n hw.ncpu` | xcpretty -c
step "Building static library..."
LIBS=(core.a platform-ios.a asset-fs.a cache-sqlite.a http-nsurl.a)
libtool -static -no_warning_for_no_symbols \
-o ${OUTPUT}/static/lib${NAME}.a \
${LIBS[@]/#/build/${BUILDTYPE}-iphoneos/libmbgl-} \
${LIBS[@]/#/build/${BUILDTYPE}-iphonesimulator/libmbgl-} \
`find mason_packages/ios-${IOS_SDK_VERSION} -type f -name libuv.a`
echo "Created ${OUTPUT}/static/lib${NAME}.a"
step "Copying Headers..."
mkdir -p "${OUTPUT}/static/Headers"
cp -pv include/mbgl/ios/* "${OUTPUT}/static/Headers"
# Manually create resource bundle. We don't use a GYP target here because of
# complications between faked GYP bundles-as-executables, device build
# dependencies, and code signing.
step "Copying Resources..."
mkdir -p "${OUTPUT}/static/${NAME}.bundle"
cp -pv platform/ios/resources/* "${OUTPUT}/static/${NAME}.bundle"
cp -prv styles/styles "${OUTPUT}/static/${NAME}.bundle/styles"

View File

@@ -47,4 +47,7 @@ elif [[ ${TRAVIS_OS_NAME} == "osx" ]]; then
mapbox_time "install_awscli" \
sudo pip install awscli
mapbox_time "install_xcpretty" \
gem install xcpretty --no-rdoc --no-ri --no-document --quiet
fi

View File

@@ -44,9 +44,8 @@ elif [[ ${TRAVIS_OS_NAME} == "osx" ]]; then
#
# build iOS
#
mapbox_time "checkout_cocoa_bindings" \
git submodule update --init ios/mapbox-gl-cocoa
mapbox_time "build_ios_project" \
mapbox_time "build_ios_project_device_release" \
make ios -j$JOBS
mapbox_time "build_ios_project_simulator_debug" \
make isim -j$JOBS
fi

View File

@@ -161,8 +161,7 @@ void TileParser::applyLayoutProperties<SymbolProperties>(StyleBucket &bucket_des
applyLayoutProperty(PropertyKey::IconPadding, bucket_desc.layout, symbol.icon.padding, z);
applyLayoutProperty(PropertyKey::IconRotate, bucket_desc.layout, symbol.icon.rotate, z);
applyLayoutProperty(PropertyKey::IconKeepUpright, bucket_desc.layout, symbol.icon.keep_upright, z);
applyLayoutProperty(PropertyKey::IconOffsetX, bucket_desc.layout, symbol.icon.offset[0], z);
applyLayoutProperty(PropertyKey::IconOffsetY, bucket_desc.layout, symbol.icon.offset[1], z);
applyLayoutProperty(PropertyKey::IconOffset, bucket_desc.layout, symbol.icon.offset, z);
applyLayoutProperty(PropertyKey::TextRotationAlignment, bucket_desc.layout, symbol.text.rotation_alignment, z);
applyLayoutProperty(PropertyKey::TextField, bucket_desc.layout, symbol.text.field, z);
@@ -180,8 +179,7 @@ void TileParser::applyLayoutProperties<SymbolProperties>(StyleBucket &bucket_des
applyLayoutProperty(PropertyKey::TextAnchor, bucket_desc.layout, symbol.text.anchor, z);
applyLayoutProperty(PropertyKey::TextKeepUpright, bucket_desc.layout, symbol.text.keep_upright, z);
applyLayoutProperty(PropertyKey::TextTransform, bucket_desc.layout, symbol.text.transform, z);
applyLayoutProperty(PropertyKey::TextOffsetX, bucket_desc.layout, symbol.text.offset[0], z);
applyLayoutProperty(PropertyKey::TextOffsetY, bucket_desc.layout, symbol.text.offset[1], z);
applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, symbol.text.offset, z);
applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, symbol.text.allow_overlap, z);
}

View File

@@ -231,7 +231,7 @@ void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>&
drawClippingMasks(sources);
recordZoom(time, state.getNormalizedZoom());
frameHistory.record(time, state.getNormalizedZoom());
// Actually render the layers
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
@@ -375,39 +375,58 @@ void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc
void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
const BackgroundProperties& properties = layer_desc->getProperties<BackgroundProperties>();
if (properties.image.size()) {
if (properties.image.to.size()) {
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
return;
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.from, true);
SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.to, true);
float zoomFraction = state.getZoomFraction();
useProgram(patternShader->program);
patternShader->u_matrix = identityMatrix;
patternShader->u_pattern_tl = imagePos.tl;
patternShader->u_pattern_br = imagePos.br;
patternShader->u_mix = zoomFraction;
patternShader->u_pattern_tl_a = imagePosA.tl;
patternShader->u_pattern_br_a = imagePosA.br;
patternShader->u_pattern_tl_b = imagePosB.tl;
patternShader->u_pattern_br_b = imagePosB.br;
patternShader->u_mix = properties.image.t;
patternShader->u_opacity = properties.opacity;
std::array<float, 2> size = imagePos.size;
double lon, lat;
state.getLonLat(lon, lat);
std::array<float, 2> center = state.locationCoordinate(lon, lat);
float scale = 1 / std::pow(2, zoomFraction);
mat3 matrix;
matrix::identity(matrix);
matrix::scale(matrix, matrix,
1.0f / size[0],
1.0f / size[1]);
matrix::translate(matrix, matrix,
std::fmod(center[0] * 512, size[0]),
std::fmod(center[1] * 512, size[1]));
matrix::rotate(matrix, matrix, -state.getAngle());
matrix::scale(matrix, matrix,
std::array<float, 2> sizeA = imagePosA.size;
mat3 matrixA;
matrix::identity(matrixA);
matrix::scale(matrixA, matrixA,
1.0f / (sizeA[0] * properties.image.fromScale),
1.0f / (sizeA[1] * properties.image.fromScale));
matrix::translate(matrixA, matrixA,
std::fmod(center[0] * 512, sizeA[0] * properties.image.fromScale),
std::fmod(center[1] * 512, sizeA[1] * properties.image.fromScale));
matrix::rotate(matrixA, matrixA, -state.getAngle());
matrix::scale(matrixA, matrixA,
scale * state.getWidth() / 2,
-scale * state.getHeight() / 2);
patternShader->u_patternmatrix = matrix;
std::array<float, 2> sizeB = imagePosB.size;
mat3 matrixB;
matrix::identity(matrixB);
matrix::scale(matrixB, matrixB,
1.0f / (sizeB[0] * properties.image.toScale),
1.0f / (sizeB[1] * properties.image.toScale));
matrix::translate(matrixB, matrixB,
std::fmod(center[0] * 512, sizeB[0] * properties.image.toScale),
std::fmod(center[1] * 512, sizeB[1] * properties.image.toScale));
matrix::rotate(matrixB, matrixB, -state.getAngle());
matrix::scale(matrixB, matrixB,
scale * state.getWidth() / 2,
-scale * state.getHeight() / 2);
patternShader->u_patternmatrix_a = matrixA;
patternShader->u_patternmatrix_b = matrixB;
backgroundBuffer.bind();
patternShader->bind(0);
@@ -459,26 +478,3 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &t
return vtxMatrix;
}
}
void Painter::recordZoom(const std::chrono::steady_clock::time_point time, const float zoom) {
frameHistory.record(time, zoom);
if (lastZoom < 0) {
// first frame ever
lastIntegerZoom = std::floor(zoom);
lastZoom = zoom;
}
// check whether an integer zoom level was passed since the last frame
// and if yes, record it with the time. Used for transitioning patterns.
if (std::floor(lastZoom) < std::floor(zoom)) {
lastIntegerZoom = std::floor(zoom);
lastIntegerZoomTime = time;
} else if (std::floor(lastZoom) > std::floor(zoom)) {
lastIntegerZoom = std::floor(zoom) + 1;
lastIntegerZoomTime = time;
}
lastZoom = zoom;
}

View File

@@ -140,7 +140,6 @@ private:
mat4 translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const Tile::ID &id, TranslateAnchorType anchor);
void prepareTile(const Tile& tile);
void recordZoom(const std::chrono::steady_clock::time_point time, const float zoom);
template <typename BucketProperties, typename StyleProperties>
void renderSDF(SymbolBucket &bucket,
@@ -193,10 +192,6 @@ private:
RenderPass pass = RenderPass::Opaque;
const float strata_epsilon = 1.0f / (1 << 16);
int lastIntegerZoom;
std::chrono::steady_clock::time_point lastIntegerZoomTime = std::chrono::steady_clock::time_point::min();
float lastZoom = -1;
public:
FrameHistory frameHistory;

View File

@@ -33,13 +33,13 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
stroke_color[3] *= properties.opacity;
}
const bool pattern = properties.image.size();
const bool pattern = properties.image.from.size();
bool outline = properties.antialias && !pattern && properties.stroke_color != properties.fill_color;
bool fringeline = properties.antialias && !pattern && properties.stroke_color == properties.fill_color;
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
// befrom, we have to draw the outline first (!)
if (outline && pass == RenderPass::Translucent) {
useProgram(outlineShader->program);
outlineShader->u_matrix = vtxMatrix;
@@ -59,34 +59,32 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
if (pattern) {
// Image fill.
if (pass == RenderPass::Translucent) {
const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, true);
const SpriteAtlasPosition posA = spriteAtlas.getPosition(properties.image.from, true);
const SpriteAtlasPosition posB = spriteAtlas.getPosition(properties.image.to, true);
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
float mix;
std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
const float fraction = std::fmod(float(state.getZoom()), 1.0f);
float t = std::min(static_cast<float>((std::chrono::steady_clock::now() - lastIntegerZoomTime) / duration), 1.0f);
if (state.getZoom() > lastIntegerZoom) {
// zooming in
mix = fraction + (1.0f - fraction) * t;
factor *= 2.0;
} else {
// zooming out
mix = fraction - fraction * t;
}
mat3 patternMatrix;
matrix::identity(patternMatrix);
matrix::scale(patternMatrix, patternMatrix, 1.0f / (pos.size[0] * factor), 1.0f / (pos.size[1] * factor));
mat3 patternMatrixA;
matrix::identity(patternMatrixA);
matrix::scale(patternMatrixA, patternMatrixA,
1.0f / (posA.size[0] * factor * properties.image.fromScale),
1.0f / (posA.size[1] * factor * properties.image.fromScale));
mat3 patternMatrixB;
matrix::identity(patternMatrixB);
matrix::scale(patternMatrixB, patternMatrixB,
1.0f / (posB.size[0] * factor * properties.image.toScale),
1.0f / (posB.size[1] * factor * properties.image.toScale));
useProgram(patternShader->program);
patternShader->u_matrix = vtxMatrix;
patternShader->u_pattern_tl = pos.tl;
patternShader->u_pattern_br = pos.br;
patternShader->u_pattern_tl_a = posA.tl;
patternShader->u_pattern_br_a = posA.br;
patternShader->u_pattern_tl_b = posB.tl;
patternShader->u_pattern_br_b = posB.br;
patternShader->u_opacity = properties.opacity;
patternShader->u_image = 0;
patternShader->u_mix = mix;
patternShader->u_patternmatrix = patternMatrix;
patternShader->u_mix = properties.image.t;
patternShader->u_patternmatrix_a = patternMatrixA;
patternShader->u_patternmatrix_b = patternMatrixB;
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
spriteAtlas.bind(true);

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