Merge branch 'before-render' into node
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## iOS 2.0.0
|
||||
|
||||
Repackaging 2.0.0-pre.1 as it contained no issues.
|
||||
|
||||
## iOS 2.0.0-pre.1
|
||||
|
||||
Repackaging 0.5.1 as the Mapbox iOS SDK 2.0.0 series.
|
||||
|
||||
## 0.5.1
|
||||
|
||||
### iOS
|
||||
|
||||
@@ -274,8 +274,8 @@ By default, the SDK will be installed to `/usr/local/opt/android-sdk`. If you op
|
||||
|
||||
echo "export ANDROID_HOME=`brew --prefix android-sdk`" >> .bash_profile
|
||||
echo "export ANDROID_NDK_PATH=`brew --cellar android-ndk`/r10e" >> .bash_profile
|
||||
# Replace <path to JDK> with something like /Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk
|
||||
echo "export JAVA_HOME=<path to JDK>" >> .bash_profile
|
||||
# Replace <path> with something like /Library/Java/JavaVirtualMachines/jdk1.8.0_31.jdk/Contents/Home
|
||||
echo "export JAVA_HOME=<path>" >> .bash_profile
|
||||
echo "export STUDIO_JDK=$JAVA_HOME" >> .bash_profile
|
||||
|
||||
Run:
|
||||
@@ -283,7 +283,7 @@ Run:
|
||||
make android
|
||||
open -a Android\ Studio
|
||||
|
||||
You can then open `android/java` in Android Studio via "Import Non-Android Studio Project".
|
||||
You can then open `android/java` in Android Studio via "import project (Eclipse ADT, Gradle, etc.)".
|
||||
|
||||
### Setting up Android emulator
|
||||
|
||||
|
||||
@@ -159,7 +159,11 @@ void NativeMapView::invalidate() {
|
||||
detach_jni_thread(vm, &env, detach);
|
||||
}
|
||||
|
||||
void NativeMapView::swap() {
|
||||
void NativeMapView::beforeRender() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void NativeMapView::afterRender() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::swap");
|
||||
|
||||
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) {
|
||||
|
||||
@@ -12,7 +12,7 @@ POM_LICENCE_DIST=repo
|
||||
POM_DEVELOPER_ID=mapbox
|
||||
POM_DEVELOPER_NAME=Mapbox
|
||||
|
||||
ANDROID_MIN_SDK=8
|
||||
ANDROID_MIN_SDK=15
|
||||
ANDROID_BUILD_TARGET_SDK_VERSION=23
|
||||
ANDROID_BUILD_TOOLS_VERSION=23
|
||||
ANDROID_BUILD_SDK_VERSION=23
|
||||
|
||||
@@ -57,7 +57,6 @@ import com.mapzen.android.lost.api.LocationRequest;
|
||||
import com.mapzen.android.lost.api.LocationServices;
|
||||
import com.mapzen.android.lost.api.LostApiClient;
|
||||
import com.squareup.okhttp.HttpUrl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -209,7 +208,6 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
//
|
||||
|
||||
// Common initialization code goes here
|
||||
@TargetApi(16)
|
||||
private void initialize(Context context, AttributeSet attrs) {
|
||||
|
||||
// Save the context
|
||||
@@ -236,12 +234,11 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
|
||||
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
activityManager.getMemoryInfo(memoryInfo);
|
||||
long maxMemory = memoryInfo.availMem;
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
long totalMemory = memoryInfo.totalMem;
|
||||
mNativeMapView = new NativeMapView(this, cachePath, dataPath, apkPath, mScreenDensity, availableProcessors, totalMemory);
|
||||
} else {
|
||||
throw new RuntimeException("Need to implement totalMemory on pre-Jelly Bean devices.");
|
||||
maxMemory = memoryInfo.totalMem;
|
||||
}
|
||||
mNativeMapView = new NativeMapView(this, cachePath, dataPath, apkPath, mScreenDensity, availableProcessors, maxMemory);
|
||||
|
||||
// Ensure this view is interactable
|
||||
setClickable(true);
|
||||
@@ -251,11 +248,7 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
requestFocus();
|
||||
|
||||
// Register the SurfaceHolder callbacks
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
||||
surfaceView.getHolder().addCallback(new Callbacks2());
|
||||
} else {
|
||||
surfaceView.getHolder().addCallback(new Callbacks());
|
||||
}
|
||||
surfaceView.getHolder().addCallback(new CallbacksHandler());
|
||||
|
||||
// Touch gesture detectors
|
||||
mGestureDetector = new GestureDetectorCompat(context, new GestureListener());
|
||||
@@ -751,7 +744,7 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
}
|
||||
|
||||
// This class handles SurfaceHolder callbacks
|
||||
private class Callbacks implements SurfaceHolder.Callback {
|
||||
private class CallbacksHandler implements SurfaceHolder.Callback, SurfaceHolder.Callback2 {
|
||||
|
||||
// Called when the native surface buffer has been created
|
||||
// Must do all EGL/GL ES initialization here
|
||||
@@ -774,10 +767,6 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
mNativeMapView.resizeFramebuffer(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(9)
|
||||
private class Callbacks2 extends Callbacks implements SurfaceHolder.Callback2 {
|
||||
|
||||
// Called when we need to redraw the view
|
||||
// This is called before our view is first visible to prevent an initial
|
||||
@@ -843,7 +832,7 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
}
|
||||
|
||||
// Called when user touches the screen, all positions are absolute
|
||||
@Override @TargetApi(14)
|
||||
@Override
|
||||
public boolean onTouchEvent(@NonNull MotionEvent event) {
|
||||
// Check and ignore non touch or left clicks
|
||||
if ((android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) && (event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) {
|
||||
@@ -1396,7 +1385,7 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
|
||||
// Called when the mouse pointer enters or exits the view
|
||||
// or when it fades in or out due to movement
|
||||
@Override @TargetApi(14)
|
||||
@Override
|
||||
public boolean onHoverEvent(@NonNull MotionEvent event) {
|
||||
switch (event.getActionMasked()) {
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
@@ -1677,7 +1666,6 @@ public class MapView extends FrameLayout implements LocationListener {
|
||||
*/
|
||||
@Override
|
||||
public void onLocationChanged(Location location) {
|
||||
Log.i(TAG, "onLocationChanged(): " + location);
|
||||
updateLocation(location);
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -47,7 +47,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.mapbox.mapboxgl.testapp"
|
||||
minSdkVersion 8
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 23
|
||||
versionCode 4
|
||||
versionName "0.1.3"
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
<string name="styleDark">Dark</string>
|
||||
<string name="styleSatellite">Satellite</string>
|
||||
|
||||
<string name="styleURLMapboxStreets">asset://styles/mapbox-streets-v7.json</string>
|
||||
<string name="styleURLEmerald">asset://styles/emerald-v7.json</string>
|
||||
<string name="styleURLLight">asset://styles/light-v7.json</string>
|
||||
<string name="styleURLDark">asset://styles/dark-v7.json</string>
|
||||
<string name="styleURLSatellite">asset://styles/satellite-v7.json</string>
|
||||
<string name="styleURLMapboxStreets">asset://styles/streets-v8.json</string>
|
||||
<string name="styleURLEmerald">asset://styles/emerald-v8.json</string>
|
||||
<string name="styleURLLight">asset://styles/light-v8.json</string>
|
||||
<string name="styleURLDark">asset://styles/dark-v8.json</string>
|
||||
<string name="styleURLSatellite">asset://styles/satellite-v8.json</string>
|
||||
|
||||
<string-array name="outdoors_class_list">
|
||||
<item>Day</item>
|
||||
|
||||
@@ -27,7 +27,8 @@ public:
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate() override;
|
||||
void swap() override;
|
||||
void beforeRender() override;
|
||||
void afterRender() override;
|
||||
|
||||
void notifyMapChange(mbgl::MapChange) override;
|
||||
|
||||
|
||||
@@ -62,8 +62,11 @@ public:
|
||||
// (map->renderSync() from the main thread must be called as a result of this)
|
||||
virtual void invalidate() = 0;
|
||||
|
||||
// Called from the render thread before the render begins.
|
||||
virtual void beforeRender() = 0;
|
||||
|
||||
// Called from the render thread after the render is complete.
|
||||
virtual void swap() = 0;
|
||||
virtual void afterRender() = 0;
|
||||
|
||||
// Reads the pixel data from the current framebuffer. If your View implementation
|
||||
// doesn't support reading from the framebuffer, return a null pointer.
|
||||
|
||||
@@ -24,7 +24,8 @@ public:
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate() override;
|
||||
void swap() override;
|
||||
void beforeRender() override;
|
||||
void afterRender() override;
|
||||
|
||||
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
|
||||
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
|
||||
|
||||
@@ -37,9 +37,11 @@ public:
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate() override;
|
||||
void swap() override;
|
||||
void beforeRender() override;
|
||||
void afterRender() override;
|
||||
std::unique_ptr<StillImage> readStillImage() override;
|
||||
|
||||
void resizeFramebuffer();
|
||||
void resize(uint16_t width, uint16_t height);
|
||||
|
||||
private:
|
||||
@@ -52,6 +54,7 @@ private:
|
||||
std::shared_ptr<HeadlessDisplay> display;
|
||||
const float pixelRatio;
|
||||
std::array<uint16_t, 2> dimensions;
|
||||
bool needsResize;
|
||||
|
||||
#if MBGL_USE_CGL
|
||||
CGLContextObj glContext = nullptr;
|
||||
|
||||
@@ -13,8 +13,8 @@ struct Resource {
|
||||
Source,
|
||||
Tile,
|
||||
Glyphs,
|
||||
JSON,
|
||||
Image
|
||||
SpriteImage,
|
||||
SpriteJSON
|
||||
};
|
||||
|
||||
const Kind kind;
|
||||
|
||||
@@ -45,6 +45,20 @@ struct LineProperties {
|
||||
}
|
||||
};
|
||||
|
||||
struct CircleProperties {
|
||||
inline CircleProperties() {}
|
||||
float radius = 5.0f;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
float opacity = 1.0f;
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
TranslateAnchorType translateAnchor = TranslateAnchorType::Map;
|
||||
float blur = 0;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return radius > 0 && color[3] > 0 && opacity > 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct SymbolProperties {
|
||||
inline SymbolProperties() {}
|
||||
|
||||
@@ -100,6 +114,7 @@ struct BackgroundProperties {
|
||||
typedef mapbox::util::variant<
|
||||
FillProperties,
|
||||
LineProperties,
|
||||
CircleProperties,
|
||||
SymbolProperties,
|
||||
RasterProperties,
|
||||
BackgroundProperties,
|
||||
|
||||
@@ -27,6 +27,7 @@ enum class StyleLayerType : uint8_t {
|
||||
Unknown,
|
||||
Fill,
|
||||
Line,
|
||||
Circle,
|
||||
Symbol,
|
||||
Raster,
|
||||
Background
|
||||
@@ -36,6 +37,7 @@ MBGL_DEFINE_ENUM_CLASS(StyleLayerTypeClass, StyleLayerType, {
|
||||
{ StyleLayerType::Unknown, "unknown" },
|
||||
{ StyleLayerType::Fill, "fill" },
|
||||
{ StyleLayerType::Line, "line" },
|
||||
{ StyleLayerType::Circle, "circle" },
|
||||
{ StyleLayerType::Symbol, "symbol" },
|
||||
{ StyleLayerType::Raster, "raster" },
|
||||
{ StyleLayerType::Background, "background" },
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
Pod::Spec.new do |m|
|
||||
|
||||
m.name = 'Mapbox-iOS-SDK'
|
||||
m.version = '2.0.0-pre.1.symbols'
|
||||
m.version = '2.0.0-symbols'
|
||||
|
||||
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/mapbox-gl-ios/'
|
||||
m.homepage = 'https://www.mapbox.com/ios-sdk/'
|
||||
m.license = 'BSD'
|
||||
m.author = { 'Mapbox' => 'mobile@mapbox.com' }
|
||||
m.screenshot = 'https://raw.githubusercontent.com/mapbox/mapbox-gl-native/master/ios/screenshot.png'
|
||||
m.social_media_url = 'https://twitter.com/mapbox'
|
||||
m.documentation_url = 'https://www.mapbox.com/mapbox-gl-ios'
|
||||
m.documentation_url = 'https://www.mapbox.com/ios-sdk/'
|
||||
|
||||
m.source = {
|
||||
:http => "http://mapbox.s3.amazonaws.com/mapbox-gl-native/ios/builds/mapbox-gl-ios-#{m.version.to_s}.zip",
|
||||
:http => "http://mapbox.s3.amazonaws.com/mapbox-gl-native/ios/builds/mapbox-ios-sdk-#{m.version.to_s}.zip",
|
||||
:flatten => true
|
||||
}
|
||||
|
||||
|
||||
@@ -9,17 +9,14 @@
|
||||
static UIColor *const kTintColor = [UIColor colorWithRed:0.120 green:0.550 blue:0.670 alpha:1.000];
|
||||
|
||||
static NSArray *const kStyleNames = @[
|
||||
@"Mapbox Streets",
|
||||
@"Streets",
|
||||
@"Emerald",
|
||||
@"Light",
|
||||
@"Dark",
|
||||
@"Bright",
|
||||
@"Basic",
|
||||
@"Outdoors",
|
||||
@"Satellite",
|
||||
];
|
||||
|
||||
static NSString *const kStyleVersion = @"7";
|
||||
static NSUInteger const kStyleVersion = 8;
|
||||
|
||||
@interface MBXViewController () <UIActionSheetDelegate, MGLMapViewDelegate>
|
||||
|
||||
@@ -301,9 +298,9 @@ mbgl::Settings_NSUserDefaults *settings = nullptr;
|
||||
}
|
||||
|
||||
self.mapView.styleURL = [NSURL URLWithString:
|
||||
[NSString stringWithFormat:@"asset://styles/%@-v%@.json",
|
||||
[[styleName lowercaseString] stringByReplacingOccurrencesOfString:@" " withString:@"-"],
|
||||
kStyleVersion]];
|
||||
[NSString stringWithFormat:@"asset://styles/%@-v%lu.json",
|
||||
[styleName lowercaseString],
|
||||
(unsigned long)kStyleVersion]];
|
||||
|
||||
[titleButton setTitle:styleName forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
NSURL* url = [[NSURL alloc] initWithString:@"asset://styles/mapbox-streets-v7.json"];
|
||||
NSURL* url = [[NSURL alloc] initWithString:@"asset://styles/streets-v8.json"];
|
||||
self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds styleURL:url];
|
||||
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.mapView.delegate = self;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
NSURL* url = [[NSURL alloc] initWithString:@"asset://styles/mapbox-streets-v7.json"];
|
||||
NSURL* url = [[NSURL alloc] initWithString:@"asset://styles/streets-v8.json"];
|
||||
self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds accessToken:nil styleURL:url];
|
||||
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
self.mapView.delegate = self;
|
||||
|
||||
@@ -4,11 +4,11 @@ namespace mbgl {
|
||||
namespace util {
|
||||
|
||||
const std::vector<std::pair<std::string, std::string>> defaultStyles = {
|
||||
{ "asset://styles/mapbox-streets-v7.json", "Mapbox Streets" },
|
||||
{ "asset://styles/emerald-v7.json", "Emerald" },
|
||||
{ "asset://styles/light-v7.json", "Light" },
|
||||
{ "asset://styles/dark-v7.json", "Dark" },
|
||||
{ "asset://styles/satellite-v7.json", "Satellite" }
|
||||
{ "asset://styles/streets-v8.json", "Mapbox Streets" },
|
||||
{ "asset://styles/emerald-v8.json", "Emerald" },
|
||||
{ "asset://styles/light-v8.json", "Light" },
|
||||
{ "asset://styles/dark-v8.json", "Dark" },
|
||||
{ "asset://styles/satellite-v8.json", "Satellite" }
|
||||
};
|
||||
|
||||
} // end namespace util
|
||||
|
||||
@@ -386,7 +386,11 @@ void GLFWView::invalidate() {
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
||||
void GLFWView::swap() {
|
||||
void GLFWView::beforeRender() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void GLFWView::afterRender() {
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,10 +114,10 @@ bool HeadlessView::isActive() {
|
||||
return std::this_thread::get_id() == thread;
|
||||
}
|
||||
|
||||
void HeadlessView::resize(const uint16_t width, const uint16_t height) {
|
||||
activate();
|
||||
void HeadlessView::resizeFramebuffer() {
|
||||
assert(isActive());
|
||||
|
||||
dimensions = {{ width, height }};
|
||||
if (!needsResize) return;
|
||||
|
||||
clearBuffers();
|
||||
|
||||
@@ -158,7 +158,12 @@ void HeadlessView::resize(const uint16_t width, const uint16_t height) {
|
||||
throw std::runtime_error(error);
|
||||
}
|
||||
|
||||
deactivate();
|
||||
needsResize = false;
|
||||
}
|
||||
|
||||
void HeadlessView::resize(const uint16_t width, const uint16_t height) {
|
||||
dimensions = {{ width, height }};
|
||||
needsResize = true;
|
||||
}
|
||||
|
||||
std::unique_ptr<StillImage> HeadlessView::readStillImage() {
|
||||
@@ -293,7 +298,11 @@ void HeadlessView::invalidate() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void HeadlessView::swap() {
|
||||
void HeadlessView::beforeRender() {
|
||||
resizeFramebuffer();
|
||||
}
|
||||
|
||||
void HeadlessView::afterRender() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ void SQLiteCache::Impl::put(const Resource& resource, std::shared_ptr<const Resp
|
||||
putStmt->bind(6 /* expires */, response->expires);
|
||||
|
||||
std::string data;
|
||||
if (resource.kind != Resource::Image) {
|
||||
if (resource.kind != Resource::SpriteImage) {
|
||||
// Do not compress images, since they are typically compressed already.
|
||||
data = util::compress(response->data);
|
||||
}
|
||||
|
||||
@@ -39,10 +39,11 @@
|
||||
|
||||
class MBGLView;
|
||||
|
||||
NSString *const MGLDefaultStyleName = @"mapbox-streets";
|
||||
NSString *const MGLStyleVersion = @"7";
|
||||
NSString *const MGLDefaultStyleName = @"streets";
|
||||
NSString *const MGLDefaultStyleMarkerSymbolName = @"default_marker";
|
||||
NSString *const MGLMapboxSetupDocumentationURLDisplayString = @"mapbox.com/guides/first-steps-gl-ios";
|
||||
NSString *const MGLMapboxSetupDocumentationURLDisplayString = @"mapbox.com/guides/first-steps-ios-sdk";
|
||||
|
||||
NSUInteger const MGLStyleVersion = 8;
|
||||
|
||||
const NSTimeInterval MGLAnimationDuration = 0.3;
|
||||
const CGSize MGLAnnotationUpdateViewportOutset = {150, 150};
|
||||
@@ -190,9 +191,9 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
|
||||
|
||||
if ( ! styleURL)
|
||||
{
|
||||
styleURL = MGLURLForBundledStyleNamed([NSString stringWithFormat:@"%@-v%@",
|
||||
styleURL = MGLURLForBundledStyleNamed([NSString stringWithFormat:@"%@-v%lu",
|
||||
MGLDefaultStyleName.lowercaseString,
|
||||
MGLStyleVersion]);
|
||||
(unsigned long)MGLStyleVersion]);
|
||||
}
|
||||
|
||||
if ( ! [styleURL scheme])
|
||||
@@ -2942,7 +2943,12 @@ class MBGLView : public mbgl::View
|
||||
waitUntilDone:NO];
|
||||
}
|
||||
|
||||
void swap() override
|
||||
void beforeRender() override
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
void afterRender() override
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ cp -pv LICENSE.md "${OUTPUT}/static"
|
||||
mkdir -p "${OUTPUT}/static/${NAME}.bundle"
|
||||
cp -pv platform/ios/resources/* "${OUTPUT}/static/${NAME}.bundle"
|
||||
mkdir -p "${OUTPUT}/static/${NAME}.bundle/styles"
|
||||
cp -pv styles/styles/{dark,emerald,light,mapbox-streets,satellite}-v7.json "${OUTPUT}/static/${NAME}.bundle/styles"
|
||||
cp -pv styles/styles/{dark,emerald,light,streets,satellite}-v8.json "${OUTPUT}/static/${NAME}.bundle/styles"
|
||||
|
||||
step "Creating API Docs..."
|
||||
if [ -z `which appledoc` ]; then
|
||||
@@ -111,7 +111,7 @@ if [ -z `which appledoc` ]; then
|
||||
fi
|
||||
DOCS_OUTPUT="${OUTPUT}/static/Docs"
|
||||
git fetch --tags
|
||||
DOCS_VERSION=$( git tag --sort -v:refname | grep -v '\-rc.' | sed -n '1p' | sed 's/^v//' )
|
||||
DOCS_VERSION=$( git tag | sed 's/^ios-//' | sort -r | grep -v '\-rc.' | grep -v '\-pre.' | sed -n '1p' | sed 's/^v//' )
|
||||
rm -rf /tmp/mbgl
|
||||
mkdir -p /tmp/mbgl/
|
||||
README=/tmp/mbgl/README.md
|
||||
|
||||
13
src/mbgl/geometry/circle_buffer.cpp
Normal file
13
src/mbgl/geometry/circle_buffer.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <mbgl/geometry/circle_buffer.hpp>
|
||||
|
||||
#include <mbgl/platform/gl.hpp>
|
||||
|
||||
#include <climits>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
void CircleVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey) {
|
||||
vertex_type *vertices = static_cast<vertex_type *>(addElement());
|
||||
vertices[0] = (x * 2) + ((ex + 1) / 2);
|
||||
vertices[1] = (y * 2) + ((ey + 1) / 2);
|
||||
}
|
||||
27
src/mbgl/geometry/circle_buffer.hpp
Normal file
27
src/mbgl/geometry/circle_buffer.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef MBGL_GEOMETRY_CIRCLE_BUFFER
|
||||
#define MBGL_GEOMETRY_CIRCLE_BUFFER
|
||||
|
||||
#include <mbgl/geometry/buffer.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class CircleVertexBuffer : public Buffer<
|
||||
4 // 2 bytes per short * 4 of them.
|
||||
> {
|
||||
public:
|
||||
typedef int16_t vertex_type;
|
||||
|
||||
/*
|
||||
* Add a vertex to this buffer
|
||||
*
|
||||
* @param {number} x vertex position
|
||||
* @param {number} y vertex position
|
||||
* @param {number} ex extrude normal
|
||||
* @param {number} ey extrude normal
|
||||
*/
|
||||
void add(vertex_type x, vertex_type y, float ex, float ey);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MBGL_GEOMETRY_CIRCLE_BUFFER
|
||||
@@ -326,6 +326,8 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame)
|
||||
return false;
|
||||
}
|
||||
|
||||
view.beforeRender();
|
||||
|
||||
transformState = state;
|
||||
|
||||
// Cleanup OpenGL objects that we abandoned since the last render call.
|
||||
@@ -345,7 +347,7 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame)
|
||||
callback = nullptr;
|
||||
}
|
||||
|
||||
view.swap();
|
||||
view.afterRender();
|
||||
viewInvalidated = false;
|
||||
data.setNeedsRepaint(style->hasTransitions() || painter->needsAnimation());
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <mbgl/util/raster.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <mbgl/util/uv_detail.hpp>
|
||||
#include <mbgl/util/mapbox.hpp>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
@@ -49,7 +50,7 @@ Sprite::Sprite(const std::string& baseUrl, float pixelRatio_)
|
||||
loader = std::make_unique<Loader>();
|
||||
|
||||
FileSource* fs = util::ThreadContext::getFileSource();
|
||||
loader->jsonRequest = fs->request({ Resource::Kind::JSON, jsonURL }, util::RunLoop::getLoop(),
|
||||
loader->jsonRequest = fs->request({ Resource::Kind::SpriteJSON, jsonURL }, util::RunLoop::getLoop(),
|
||||
[this, jsonURL](const Response& res) {
|
||||
loader->jsonRequest = nullptr;
|
||||
if (res.status == Response::Successful) {
|
||||
@@ -65,7 +66,7 @@ Sprite::Sprite(const std::string& baseUrl, float pixelRatio_)
|
||||
});
|
||||
|
||||
loader->spriteRequest =
|
||||
fs->request({ Resource::Kind::Image, spriteURL }, util::RunLoop::getLoop(),
|
||||
fs->request({ Resource::Kind::SpriteImage, spriteURL }, util::RunLoop::getLoop(),
|
||||
[this, spriteURL](const Response& res) {
|
||||
loader->spriteRequest = nullptr;
|
||||
if (res.status == Response::Successful) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/geometry/glyph_atlas.hpp>
|
||||
#include <mbgl/renderer/fill_bucket.hpp>
|
||||
#include <mbgl/renderer/line_bucket.hpp>
|
||||
#include <mbgl/renderer/circle_bucket.hpp>
|
||||
#include <mbgl/renderer/symbol_bucket.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
@@ -47,8 +48,8 @@ Bucket* TileWorker::getBucket(const StyleLayer& layer) const {
|
||||
TileParseResult TileWorker::parse(const GeometryTile& geometryTile) {
|
||||
partialParse = false;
|
||||
|
||||
for (const auto& layer : layers) {
|
||||
parseLayer(*layer, geometryTile);
|
||||
for (auto i = layers.rbegin(); i != layers.rend(); i++) {
|
||||
parseLayer(**i, geometryTile);
|
||||
}
|
||||
|
||||
return partialParse ? TileData::State::partial : TileData::State::parsed;
|
||||
@@ -57,8 +58,8 @@ TileParseResult TileWorker::parse(const GeometryTile& geometryTile) {
|
||||
void TileWorker::redoPlacement(float angle, bool collisionDebug) {
|
||||
collision->reset(angle, 0);
|
||||
collision->setDebug(collisionDebug);
|
||||
for (const auto& layer_desc : layers) {
|
||||
auto bucket = getBucket(*layer_desc);
|
||||
for (auto i = layers.rbegin(); i != layers.rend(); i++) {
|
||||
auto bucket = getBucket(**i);
|
||||
if (bucket) {
|
||||
bucket->placeFeatures();
|
||||
}
|
||||
@@ -139,15 +140,22 @@ void TileWorker::parseLayer(const StyleLayer& layer, const GeometryTile& geometr
|
||||
|
||||
std::unique_ptr<Bucket> bucket;
|
||||
|
||||
if (styleBucket.type == StyleLayerType::Fill) {
|
||||
switch (styleBucket.type) {
|
||||
case StyleLayerType::Fill:
|
||||
bucket = createFillBucket(*geometryLayer, styleBucket);
|
||||
} else if (styleBucket.type == StyleLayerType::Line) {
|
||||
break;
|
||||
case StyleLayerType::Line:
|
||||
bucket = createLineBucket(*geometryLayer, styleBucket);
|
||||
} else if (styleBucket.type == StyleLayerType::Symbol) {
|
||||
break;
|
||||
case StyleLayerType::Circle:
|
||||
bucket = createCircleBucket(*geometryLayer, styleBucket);
|
||||
break;
|
||||
case StyleLayerType::Symbol:
|
||||
bucket = createSymbolBucket(*geometryLayer, styleBucket);
|
||||
} else if (styleBucket.type == StyleLayerType::Raster) {
|
||||
break;
|
||||
case StyleLayerType::Raster:
|
||||
return;
|
||||
} else {
|
||||
default:
|
||||
Log::Warning(Event::ParseTile, "unknown bucket render type for layer '%s' (source layer '%s')",
|
||||
styleBucket.name.c_str(), styleBucket.source_layer.c_str());
|
||||
}
|
||||
@@ -203,6 +211,17 @@ std::unique_ptr<Bucket> TileWorker::createLineBucket(const GeometryTileLayer& la
|
||||
return bucket->hasData() ? std::move(bucket) : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileWorker::createCircleBucket(const GeometryTileLayer& layer,
|
||||
const StyleBucket& bucket_desc) {
|
||||
auto bucket = std::make_unique<CircleBucket>(circleVertexBuffer,
|
||||
triangleElementsBuffer);
|
||||
|
||||
// Circle does not have layout properties to apply.
|
||||
|
||||
addBucketGeometries(bucket, layer, bucket_desc.filter);
|
||||
return bucket->hasData() ? std::move(bucket) : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer& layer,
|
||||
const StyleBucket& bucket_desc) {
|
||||
auto bucket = std::make_unique<SymbolBucket>(*collision, id.overscaling);
|
||||
@@ -215,14 +234,13 @@ std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer&
|
||||
layout.icon.rotation_alignment = RotationAlignmentType::Map;
|
||||
layout.text.rotation_alignment = RotationAlignmentType::Map;
|
||||
};
|
||||
applyLayoutProperty(PropertyKey::SymbolMinDistance, bucket_desc.layout, layout.min_distance, z);
|
||||
applyLayoutProperty(PropertyKey::SymbolSpacing, bucket_desc.layout, layout.spacing, z);
|
||||
applyLayoutProperty(PropertyKey::SymbolAvoidEdges, bucket_desc.layout, layout.avoid_edges, z);
|
||||
|
||||
applyLayoutProperty(PropertyKey::IconAllowOverlap, bucket_desc.layout, layout.icon.allow_overlap, z);
|
||||
applyLayoutProperty(PropertyKey::IconIgnorePlacement, bucket_desc.layout, layout.icon.ignore_placement, z);
|
||||
applyLayoutProperty(PropertyKey::IconOptional, bucket_desc.layout, layout.icon.optional, z);
|
||||
applyLayoutProperty(PropertyKey::IconRotationAlignment, bucket_desc.layout, layout.icon.rotation_alignment, z);
|
||||
applyLayoutProperty(PropertyKey::IconMaxSize, bucket_desc.layout, layout.icon.max_size, z);
|
||||
applyLayoutProperty(PropertyKey::IconImage, bucket_desc.layout, layout.icon.image, z);
|
||||
applyLayoutProperty(PropertyKey::IconPadding, bucket_desc.layout, layout.icon.padding, z);
|
||||
applyLayoutProperty(PropertyKey::IconRotate, bucket_desc.layout, layout.icon.rotate, z);
|
||||
@@ -232,7 +250,6 @@ std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer&
|
||||
applyLayoutProperty(PropertyKey::TextRotationAlignment, bucket_desc.layout, layout.text.rotation_alignment, z);
|
||||
applyLayoutProperty(PropertyKey::TextField, bucket_desc.layout, layout.text.field, z);
|
||||
applyLayoutProperty(PropertyKey::TextFont, bucket_desc.layout, layout.text.font, z);
|
||||
applyLayoutProperty(PropertyKey::TextMaxSize, bucket_desc.layout, layout.text.max_size, z);
|
||||
applyLayoutProperty(PropertyKey::TextMaxWidth, bucket_desc.layout, layout.text.max_width, z);
|
||||
applyLayoutProperty(PropertyKey::TextLineHeight, bucket_desc.layout, layout.text.line_height, z);
|
||||
applyLayoutProperty(PropertyKey::TextLetterSpacing, bucket_desc.layout, layout.text.letter_spacing, z);
|
||||
@@ -248,6 +265,11 @@ std::unique_ptr<Bucket> TileWorker::createSymbolBucket(const GeometryTileLayer&
|
||||
applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, layout.text.offset, z);
|
||||
applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, layout.text.allow_overlap, z);
|
||||
|
||||
applyLayoutProperty(PropertyKey::IconSize, bucket_desc.layout, layout.icon.size, z + 1);
|
||||
applyLayoutProperty(PropertyKey::IconSize, bucket_desc.layout, layout.icon.max_size, 18);
|
||||
applyLayoutProperty(PropertyKey::TextSize, bucket_desc.layout, layout.text.size, z + 1);
|
||||
applyLayoutProperty(PropertyKey::TextSize, bucket_desc.layout, layout.text.max_size, 18);
|
||||
|
||||
if (bucket->needsDependencies(layer, bucket_desc.filter, *style.glyphStore, *style.sprite)) {
|
||||
partialParse = true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/geometry/elements_buffer.hpp>
|
||||
#include <mbgl/geometry/fill_buffer.hpp>
|
||||
#include <mbgl/geometry/line_buffer.hpp>
|
||||
#include <mbgl/geometry/circle_buffer.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
#include <mbgl/style/filter_expression.hpp>
|
||||
@@ -52,6 +53,7 @@ private:
|
||||
|
||||
std::unique_ptr<Bucket> createFillBucket(const GeometryTileLayer&, const StyleBucket&);
|
||||
std::unique_ptr<Bucket> createLineBucket(const GeometryTileLayer&, const StyleBucket&);
|
||||
std::unique_ptr<Bucket> createCircleBucket(const GeometryTileLayer&, const StyleBucket&);
|
||||
std::unique_ptr<Bucket> createSymbolBucket(const GeometryTileLayer&, const StyleBucket&);
|
||||
|
||||
template <class Bucket>
|
||||
@@ -68,6 +70,7 @@ private:
|
||||
|
||||
FillVertexBuffer fillVertexBuffer;
|
||||
LineVertexBuffer lineVertexBuffer;
|
||||
CircleVertexBuffer circleVertexBuffer;
|
||||
|
||||
TriangleElementsBuffer triangleElementsBuffer;
|
||||
LineElementsBuffer lineElementsBuffer;
|
||||
|
||||
92
src/mbgl/renderer/circle_bucket.cpp
Normal file
92
src/mbgl/renderer/circle_bucket.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <mbgl/renderer/circle_bucket.hpp>
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
|
||||
#include <mbgl/shader/circle_shader.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
CircleBucket::CircleBucket(CircleVertexBuffer& vertexBuffer,
|
||||
TriangleElementsBuffer& elementsBuffer)
|
||||
: vertexBuffer_(vertexBuffer)
|
||||
, elementsBuffer_(elementsBuffer)
|
||||
, vertexStart_(vertexBuffer_.index())
|
||||
, elementsStart_(elementsBuffer_.index()) {
|
||||
}
|
||||
|
||||
CircleBucket::~CircleBucket() {
|
||||
// Do not remove. header file only contains forward definitions to unique pointers.
|
||||
}
|
||||
|
||||
void CircleBucket::upload() {
|
||||
vertexBuffer_.upload();
|
||||
elementsBuffer_.upload();
|
||||
uploaded = true;
|
||||
}
|
||||
|
||||
void CircleBucket::render(Painter& painter,
|
||||
const StyleLayer& layer_desc,
|
||||
const TileID& id,
|
||||
const mat4& matrix) {
|
||||
painter.renderCircle(*this, layer_desc, id, matrix);
|
||||
}
|
||||
|
||||
bool CircleBucket::hasData() const {
|
||||
return !triangleGroups_.empty();
|
||||
}
|
||||
|
||||
void CircleBucket::addGeometry(const GeometryCollection& geometryCollection) {
|
||||
for (auto& circle : geometryCollection) {
|
||||
for(auto & geometry : circle) {
|
||||
auto x = geometry.x;
|
||||
auto y = geometry.y;
|
||||
|
||||
// this geometry will be of the Point type, and we'll derive
|
||||
// two triangles from it.
|
||||
//
|
||||
// ┌─────────┐
|
||||
// │ 4 3 │
|
||||
// │ │
|
||||
// │ 1 2 │
|
||||
// └─────────┘
|
||||
//
|
||||
vertexBuffer_.add(x, y, -1, -1); // 1
|
||||
vertexBuffer_.add(x, y, 1, -1); // 2
|
||||
vertexBuffer_.add(x, y, 1, 1); // 3
|
||||
vertexBuffer_.add(x, y, -1, 1); // 4
|
||||
|
||||
if (!triangleGroups_.size() || (triangleGroups_.back()->vertex_length + 4 > 65535)) {
|
||||
// Move to a new group because the old one can't hold the geometry.
|
||||
triangleGroups_.emplace_back(std::make_unique<TriangleGroup>());
|
||||
}
|
||||
|
||||
TriangleGroup& group = *triangleGroups_.back();
|
||||
auto index = group.vertex_length;
|
||||
|
||||
// 1, 2, 3
|
||||
// 1, 4, 3
|
||||
elementsBuffer_.add(index, index + 1, index + 2);
|
||||
elementsBuffer_.add(index, index + 3, index + 2);
|
||||
|
||||
group.vertex_length += 4;
|
||||
group.elements_length += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CircleBucket::drawCircles(CircleShader& shader) {
|
||||
char* vertexIndex = BUFFER_OFFSET(vertexStart_ * vertexBuffer_.itemSize);
|
||||
char* elementsIndex = BUFFER_OFFSET(elementsStart_ * elementsBuffer_.itemSize);
|
||||
|
||||
for (auto& group : triangleGroups_) {
|
||||
assert(group);
|
||||
|
||||
if (!group->elements_length) continue;
|
||||
|
||||
group->array[0].bind(shader, vertexBuffer_, elementsBuffer_, vertexIndex);
|
||||
|
||||
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elementsIndex));
|
||||
|
||||
vertexIndex += group->vertex_length * vertexBuffer_.itemSize;
|
||||
elementsIndex += group->elements_length * elementsBuffer_.itemSize;
|
||||
}
|
||||
}
|
||||
46
src/mbgl/renderer/circle_bucket.hpp
Normal file
46
src/mbgl/renderer/circle_bucket.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef MBGL_RENDERER_CIRCLE_BUCKET
|
||||
#define MBGL_RENDERER_CIRCLE_BUCKET
|
||||
|
||||
#include <mbgl/renderer/bucket.hpp>
|
||||
|
||||
#include <mbgl/map/geometry_tile.hpp>
|
||||
|
||||
#include <mbgl/geometry/elements_buffer.hpp>
|
||||
#include <mbgl/geometry/circle_buffer.hpp>
|
||||
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class CircleVertexBuffer;
|
||||
class CircleShader;
|
||||
|
||||
class CircleBucket : public Bucket {
|
||||
using TriangleGroup = ElementGroup<3>;
|
||||
|
||||
public:
|
||||
CircleBucket(CircleVertexBuffer &vertexBuffer, TriangleElementsBuffer &elementsBuffer);
|
||||
~CircleBucket() override;
|
||||
|
||||
void upload() override;
|
||||
void render(Painter&, const StyleLayer&, const TileID&, const mat4&) override;
|
||||
|
||||
bool hasData() const;
|
||||
void addGeometry(const GeometryCollection&);
|
||||
|
||||
void drawCircles(CircleShader& shader);
|
||||
|
||||
private:
|
||||
CircleVertexBuffer& vertexBuffer_;
|
||||
TriangleElementsBuffer& elementsBuffer_;
|
||||
|
||||
const size_t vertexStart_;
|
||||
const size_t elementsStart_;
|
||||
|
||||
std::vector<std::unique_ptr<TriangleGroup>> triangleGroups_;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif // MBGL_RENDERER_CIRCLE_BUCKET
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <mbgl/shader/sdf_shader.hpp>
|
||||
#include <mbgl/shader/dot_shader.hpp>
|
||||
#include <mbgl/shader/box_shader.hpp>
|
||||
#include <mbgl/shader/circle_shader.hpp>
|
||||
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/util/mat3.hpp>
|
||||
@@ -66,6 +67,7 @@ void Painter::setup() {
|
||||
assert(sdfGlyphShader);
|
||||
assert(sdfIconShader);
|
||||
assert(dotShader);
|
||||
assert(circleShader);
|
||||
|
||||
|
||||
// Blending
|
||||
@@ -100,6 +102,7 @@ void Painter::setupShaders() {
|
||||
if (!sdfIconShader) sdfIconShader = std::make_unique<SDFIconShader>();
|
||||
if (!dotShader) dotShader = std::make_unique<DotShader>();
|
||||
if (!collisionBoxShader) collisionBoxShader = std::make_unique<CollisionBoxShader>();
|
||||
if (!circleShader) circleShader = std::make_unique<CircleShader>();
|
||||
}
|
||||
|
||||
void Painter::resize() {
|
||||
|
||||
@@ -38,6 +38,7 @@ struct FrameData;
|
||||
class DebugBucket;
|
||||
class FillBucket;
|
||||
class LineBucket;
|
||||
class CircleBucket;
|
||||
class SymbolBucket;
|
||||
class RasterBucket;
|
||||
|
||||
@@ -50,6 +51,7 @@ class LineShader;
|
||||
class LinejoinShader;
|
||||
class LineSDFShader;
|
||||
class LinepatternShader;
|
||||
class CircleShader;
|
||||
class PatternShader;
|
||||
class IconShader;
|
||||
class RasterShader;
|
||||
@@ -100,6 +102,7 @@ public:
|
||||
void renderDebugText(DebugBucket& bucket, const mat4 &matrix);
|
||||
void renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
|
||||
void renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
|
||||
void renderCircle(CircleBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
|
||||
void renderSymbol(SymbolBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
|
||||
void renderRaster(RasterBucket& bucket, const StyleLayer &layer_desc, const TileID& id, const mat4 &matrix);
|
||||
void renderBackground(const StyleLayer &layer_desc);
|
||||
@@ -222,6 +225,7 @@ public:
|
||||
std::unique_ptr<SDFIconShader> sdfIconShader;
|
||||
std::unique_ptr<DotShader> dotShader;
|
||||
std::unique_ptr<CollisionBoxShader> collisionBoxShader;
|
||||
std::unique_ptr<CircleShader> circleShader;
|
||||
|
||||
StaticVertexBuffer backgroundBuffer = {
|
||||
{ -1, -1 }, { 1, -1 },
|
||||
|
||||
49
src/mbgl/renderer/painter_circle.cpp
Normal file
49
src/mbgl/renderer/painter_circle.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/renderer/circle_bucket.hpp>
|
||||
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_layout.hpp>
|
||||
|
||||
#include <mbgl/map/sprite.hpp>
|
||||
#include <mbgl/map/tile_id.hpp>
|
||||
#include <mbgl/map/map_data.hpp>
|
||||
|
||||
#include <mbgl/shader/circle_shader.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
void Painter::renderCircle(CircleBucket& bucket,
|
||||
const StyleLayer& layer_desc,
|
||||
const TileID& id,
|
||||
const mat4& matrix) {
|
||||
// Abort early.
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
|
||||
config.stencilTest = false;
|
||||
|
||||
const CircleProperties& properties = layer_desc.getProperties<CircleProperties>();
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
|
||||
|
||||
Color color = properties.color;
|
||||
color[0] *= properties.opacity;
|
||||
color[1] *= properties.opacity;
|
||||
color[2] *= properties.opacity;
|
||||
color[3] *= properties.opacity;
|
||||
|
||||
// Antialiasing factor: this is a minimum blur distance that serves as
|
||||
// a faux-antialiasing for the circle. since blur is a ratio of the circle's
|
||||
// size and the intent is to keep the blur at roughly 1px, the two
|
||||
// are inversely related.
|
||||
float antialiasing = 1 / data.pixelRatio / properties.radius;
|
||||
|
||||
useProgram(circleShader->program);
|
||||
|
||||
circleShader->u_matrix = vtxMatrix;
|
||||
circleShader->u_exmatrix = projMatrix;
|
||||
circleShader->u_color = color;
|
||||
circleShader->u_blur = std::max(properties.blur, antialiasing);
|
||||
circleShader->u_size = properties.radius;
|
||||
|
||||
bucket.drawCircles(*circleShader);
|
||||
}
|
||||
@@ -49,7 +49,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
sdfShader.u_texsize = texsize;
|
||||
|
||||
// adjust min/max zooms for variable font sies
|
||||
float zoomAdjust = std::log(fontSize / bucketProperties.max_size) / std::log(2);
|
||||
float zoomAdjust = std::log(fontSize / bucketProperties.size) / std::log(2);
|
||||
|
||||
sdfShader.u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
|
||||
|
||||
@@ -69,7 +69,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
|
||||
// We're drawing in the translucent pass which is bottom-to-top, so we need
|
||||
// to draw the halo first.
|
||||
if (styleProperties.halo_color[3] > 0.0f) {
|
||||
if (styleProperties.halo_color[3] > 0.0f && styleProperties.halo_width > 0.0f) {
|
||||
sdfShader.u_gamma = styleProperties.halo_blur * blurOffset / fontScale / sdfPx + gamma;
|
||||
|
||||
if (styleProperties.opacity < 1.0f) {
|
||||
@@ -157,8 +157,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
|
||||
? state.getAngle()
|
||||
: 0;
|
||||
|
||||
// If layerStyle.size > bucket.info.fontSize then labels may collide
|
||||
const float fontSize = properties.icon.size != 0 ? properties.icon.size : layout.icon.max_size;
|
||||
const float fontSize = properties.icon.size;
|
||||
const float fontScale = fontSize / 1.0f;
|
||||
|
||||
spriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
|
||||
@@ -191,7 +190,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
|
||||
iconShader->u_texsize = {{ float(spriteAtlas->getWidth()) / 4.0f, float(spriteAtlas->getHeight()) / 4.0f }};
|
||||
|
||||
// adjust min/max zooms for variable font sies
|
||||
float zoomAdjust = std::log(fontSize / layout.icon.max_size) / std::log(2);
|
||||
float zoomAdjust = std::log(fontSize / layout.icon.size) / std::log(2);
|
||||
|
||||
iconShader->u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
|
||||
iconShader->u_fadedist = 0 * 10;
|
||||
|
||||
@@ -274,10 +274,11 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
|
||||
const float minScale = 0.5f;
|
||||
const float glyphSize = 24.0f;
|
||||
|
||||
const float fontScale = layout.text.max_size / glyphSize;
|
||||
const float fontScale = layout.text.size / glyphSize;
|
||||
const float textBoxScale = collision.tilePixelRatio * fontScale;
|
||||
const float iconBoxScale = collision.tilePixelRatio * layout.icon.max_size;
|
||||
const float symbolSpacing = collision.tilePixelRatio * layout.min_distance;
|
||||
const float textMaxBoxScale = collision.tilePixelRatio * layout.text.max_size / glyphSize;
|
||||
const float iconBoxScale = collision.tilePixelRatio * layout.icon.size;
|
||||
const float symbolSpacing = collision.tilePixelRatio * layout.spacing;
|
||||
const bool avoidEdges = layout.avoid_edges && layout.placement != PlacementType::Line;
|
||||
const float textPadding = layout.text.padding * collision.tilePixelRatio;
|
||||
const float iconPadding = layout.icon.padding * collision.tilePixelRatio;
|
||||
@@ -302,7 +303,7 @@ void SymbolBucket::addFeature(const std::vector<std::vector<Coordinate>> &lines,
|
||||
|
||||
// Calculate the anchor points around which you want to place labels
|
||||
Anchors anchors = isLine ?
|
||||
getAnchors(line, symbolSpacing, textMaxAngle, shapedText.left, shapedText.right, shapedIcon.left, shapedIcon.right, glyphSize, textBoxScale, overscaling) :
|
||||
getAnchors(line, symbolSpacing, textMaxAngle, shapedText.left, shapedText.right, shapedIcon.left, shapedIcon.right, glyphSize, textMaxBoxScale, overscaling) :
|
||||
Anchors({ Anchor(float(line[0].x), float(line[0].y), 0, minScale) });
|
||||
|
||||
// For each potential label, create the placement features used to check for collisions, and the quads use for rendering.
|
||||
|
||||
10
src/mbgl/shader/circle.fragment.glsl
Normal file
10
src/mbgl/shader/circle.fragment.glsl
Normal file
@@ -0,0 +1,10 @@
|
||||
uniform vec4 u_color;
|
||||
uniform float u_blur;
|
||||
uniform float u_size;
|
||||
|
||||
varying vec2 v_extrude;
|
||||
|
||||
void main() {
|
||||
float t = smoothstep(1.0 - u_blur, 1.0, length(v_extrude));
|
||||
gl_FragColor = u_color * (1.0 - t);
|
||||
}
|
||||
23
src/mbgl/shader/circle.vertex.glsl
Normal file
23
src/mbgl/shader/circle.vertex.glsl
Normal file
@@ -0,0 +1,23 @@
|
||||
// set by gl_util
|
||||
uniform float u_size;
|
||||
|
||||
attribute vec2 a_pos;
|
||||
|
||||
uniform mat4 u_matrix;
|
||||
uniform mat4 u_exmatrix;
|
||||
|
||||
varying vec2 v_extrude;
|
||||
|
||||
void main(void) {
|
||||
// unencode the extrusion vector that we snuck into the a_pos vector
|
||||
v_extrude = vec2(mod(a_pos, 2.0) * 2.0 - 1.0);
|
||||
|
||||
vec4 extrude = u_exmatrix * vec4(v_extrude * u_size, 0, 0);
|
||||
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
|
||||
// in extrusion data
|
||||
gl_Position = u_matrix * vec4(a_pos * 0.5, 0, 1);
|
||||
|
||||
// gl_Position is divided by gl_Position.w after this shader runs.
|
||||
// Multiply the extrude by it so that it isn't affected by it.
|
||||
gl_Position += extrude * gl_Position.w;
|
||||
}
|
||||
21
src/mbgl/shader/circle_shader.cpp
Normal file
21
src/mbgl/shader/circle_shader.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <mbgl/shader/circle_shader.hpp>
|
||||
#include <mbgl/shader/shaders.hpp>
|
||||
#include <mbgl/platform/gl.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
CircleShader::CircleShader()
|
||||
: Shader(
|
||||
"circle",
|
||||
shaders[CIRCLE_SHADER].vertex,
|
||||
shaders[CIRCLE_SHADER].fragment
|
||||
) {
|
||||
a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos"));
|
||||
}
|
||||
|
||||
void CircleShader::bind(char *offset) {
|
||||
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
|
||||
MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 4, offset));
|
||||
}
|
||||
27
src/mbgl/shader/circle_shader.hpp
Normal file
27
src/mbgl/shader/circle_shader.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef MBGL_SHADER_CIRCLE_SHADER
|
||||
#define MBGL_SHADER_CIRCLE_SHADER
|
||||
|
||||
#include <mbgl/shader/shader.hpp>
|
||||
#include <mbgl/shader/uniform.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class CircleShader : public Shader {
|
||||
public:
|
||||
CircleShader();
|
||||
|
||||
void bind(char *offset);
|
||||
|
||||
UniformMatrix<4> u_matrix = {"u_matrix", *this};
|
||||
UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
|
||||
Uniform<std::array<float, 4>> u_color = {"u_color", *this};
|
||||
Uniform<float> u_size = {"u_size", *this};
|
||||
Uniform<float> u_blur = {"u_blur", *this};
|
||||
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MBGL_SHADER_CIRCLE_SHADER
|
||||
@@ -55,6 +55,11 @@ Request* DefaultFileSource::request(const Resource& resource,
|
||||
url = util::mapbox::normalizeGlyphsURL(resource.url, accessToken);
|
||||
break;
|
||||
|
||||
case Resource::Kind::SpriteImage:
|
||||
case Resource::Kind::SpriteJSON:
|
||||
url = util::mapbox::normalizeSpriteURL(resource.url, accessToken);
|
||||
break;
|
||||
|
||||
default:
|
||||
url = resource.url;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,13 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::LineGapWidth, defaultStyleProperties<LineProperties>().gap_width },
|
||||
{ PropertyKey::LineBlur, defaultStyleProperties<LineProperties>().blur },
|
||||
|
||||
{ PropertyKey::CircleRadius, defaultStyleProperties<CircleProperties>().radius },
|
||||
{ PropertyKey::CircleColor, defaultStyleProperties<CircleProperties>().color },
|
||||
{ PropertyKey::CircleOpacity, defaultStyleProperties<CircleProperties>().opacity },
|
||||
{ PropertyKey::CircleTranslate, defaultStyleProperties<CircleProperties>().translate },
|
||||
{ PropertyKey::CircleTranslateAnchor, defaultStyleProperties<CircleProperties>().translateAnchor },
|
||||
{ PropertyKey::CircleBlur, defaultStyleProperties<CircleProperties>().blur },
|
||||
|
||||
{ PropertyKey::IconOpacity, defaultStyleProperties<SymbolProperties>().icon.opacity },
|
||||
{ PropertyKey::IconSize, defaultStyleProperties<SymbolProperties>().icon.size },
|
||||
{ PropertyKey::IconColor, defaultStyleProperties<SymbolProperties>().icon.color },
|
||||
@@ -56,14 +63,13 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::LineRoundLimit, defaultStyleLayout<StyleLayoutLine>().round_limit },
|
||||
|
||||
{ PropertyKey::SymbolPlacement, defaultStyleLayout<StyleLayoutSymbol>().placement },
|
||||
{ PropertyKey::SymbolMinDistance, defaultStyleLayout<StyleLayoutSymbol>().min_distance },
|
||||
{ PropertyKey::SymbolSpacing, defaultStyleLayout<StyleLayoutSymbol>().spacing },
|
||||
{ PropertyKey::SymbolAvoidEdges, defaultStyleLayout<StyleLayoutSymbol>().avoid_edges },
|
||||
|
||||
{ PropertyKey::IconAllowOverlap, defaultStyleLayout<StyleLayoutSymbol>().icon.allow_overlap },
|
||||
{ PropertyKey::IconIgnorePlacement, defaultStyleLayout<StyleLayoutSymbol>().icon.ignore_placement },
|
||||
{ PropertyKey::IconOptional, defaultStyleLayout<StyleLayoutSymbol>().icon.optional },
|
||||
{ PropertyKey::IconRotationAlignment, defaultStyleLayout<StyleLayoutSymbol>().icon.rotation_alignment },
|
||||
{ PropertyKey::IconMaxSize, defaultStyleLayout<StyleLayoutSymbol>().icon.max_size },
|
||||
{ PropertyKey::IconImage, defaultStyleLayout<StyleLayoutSymbol>().icon.image },
|
||||
{ PropertyKey::IconRotate, defaultStyleLayout<StyleLayoutSymbol>().icon.rotate },
|
||||
{ PropertyKey::IconPadding, defaultStyleLayout<StyleLayoutSymbol>().icon.padding },
|
||||
@@ -73,7 +79,6 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::TextRotationAlignment, defaultStyleLayout<StyleLayoutSymbol>().text.rotation_alignment },
|
||||
{ PropertyKey::TextField, defaultStyleLayout<StyleLayoutSymbol>().text.field },
|
||||
{ PropertyKey::TextFont, defaultStyleLayout<StyleLayoutSymbol>().text.font },
|
||||
{ PropertyKey::TextMaxSize, defaultStyleLayout<StyleLayoutSymbol>().text.max_size },
|
||||
{ PropertyKey::TextMaxWidth, defaultStyleLayout<StyleLayoutSymbol>().text.max_width },
|
||||
{ PropertyKey::TextLineHeight, defaultStyleLayout<StyleLayoutSymbol>().text.line_height },
|
||||
{ PropertyKey::TextLetterSpacing, defaultStyleLayout<StyleLayoutSymbol>().text.letter_spacing },
|
||||
|
||||
@@ -27,8 +27,15 @@ enum class PropertyKey {
|
||||
LineMiterLimit,
|
||||
LineRoundLimit,
|
||||
|
||||
CircleRadius,
|
||||
CircleColor,
|
||||
CircleOpacity,
|
||||
CircleTranslate,
|
||||
CircleTranslateAnchor,
|
||||
CircleBlur,
|
||||
|
||||
SymbolPlacement,
|
||||
SymbolMinDistance,
|
||||
SymbolSpacing,
|
||||
SymbolAvoidEdges,
|
||||
|
||||
IconOpacity,
|
||||
@@ -44,7 +51,6 @@ enum class PropertyKey {
|
||||
IconIgnorePlacement,
|
||||
IconOptional,
|
||||
IconRotationAlignment,
|
||||
IconMaxSize,
|
||||
IconImage,
|
||||
IconOffset,
|
||||
IconPadding,
|
||||
@@ -52,7 +58,6 @@ enum class PropertyKey {
|
||||
IconKeepUpright,
|
||||
|
||||
TextOpacity,
|
||||
TextSize,
|
||||
TextColor,
|
||||
TextHaloColor,
|
||||
TextHaloWidth,
|
||||
@@ -63,7 +68,7 @@ enum class PropertyKey {
|
||||
TextRotationAlignment,
|
||||
TextField,
|
||||
TextFont,
|
||||
TextMaxSize,
|
||||
TextSize,
|
||||
TextMaxWidth,
|
||||
TextLineHeight,
|
||||
TextLetterSpacing,
|
||||
|
||||
@@ -19,6 +19,8 @@ bool StyleLayer::isVisible() const {
|
||||
return getProperties<FillProperties>().isVisible();
|
||||
case StyleLayerType::Line:
|
||||
return getProperties<LineProperties>().isVisible();
|
||||
case StyleLayerType::Circle:
|
||||
return getProperties<CircleProperties>().isVisible();
|
||||
case StyleLayerType::Symbol:
|
||||
return getProperties<SymbolProperties>().isVisible();
|
||||
case StyleLayerType::Raster:
|
||||
@@ -208,12 +210,23 @@ void StyleLayer::applyStyleProperties<LineProperties>(const float z, const TimeP
|
||||
applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), now, zoomHistory);
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<CircleProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
|
||||
properties.set<CircleProperties>();
|
||||
CircleProperties& circle = properties.get<CircleProperties>();
|
||||
applyTransitionedStyleProperty(PropertyKey::CircleRadius, circle.radius, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::CircleColor, circle.color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::CircleOpacity, circle.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::CircleTranslate, circle.translate, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::CircleTranslateAnchor, circle.translateAnchor, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::CircleBlur, circle.blur, z, now, zoomHistory);
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const TimePoint& now, const ZoomHistory &zoomHistory) {
|
||||
properties.set<SymbolProperties>();
|
||||
SymbolProperties &symbol = properties.get<SymbolProperties>();
|
||||
applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconSize, symbol.icon.size, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconColor, symbol.icon.color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconHaloColor, symbol.icon.halo_color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconHaloWidth, symbol.icon.halo_width, z, now, zoomHistory);
|
||||
@@ -222,13 +235,24 @@ void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const Tim
|
||||
applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now, zoomHistory);
|
||||
|
||||
applyTransitionedStyleProperty(PropertyKey::TextOpacity, symbol.text.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextSize, symbol.text.size, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextColor, symbol.text.color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextHaloColor, symbol.text.halo_color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextHaloWidth, symbol.text.halo_width, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextHaloBlur, symbol.text.halo_blur, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextTranslate, symbol.text.translate, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::TextTranslateAnchor, symbol.text.translate_anchor, z, now, zoomHistory);
|
||||
|
||||
// text-size and icon-size are layout properties but they also need to be evaluated as paint properties:
|
||||
auto it = bucket->layout.properties.find(PropertyKey::IconSize);
|
||||
if (it != bucket->layout.properties.end()) {
|
||||
const PropertyEvaluator<float> evaluator(z, zoomHistory);
|
||||
symbol.icon.size = mapbox::util::apply_visitor(evaluator, it->second);
|
||||
}
|
||||
it = bucket->layout.properties.find(PropertyKey::TextSize);
|
||||
if (it != bucket->layout.properties.end()) {
|
||||
const PropertyEvaluator<float> evaluator(z, zoomHistory);
|
||||
symbol.text.size = mapbox::util::apply_visitor(evaluator, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -259,6 +283,7 @@ void StyleLayer::updateProperties(float z, const TimePoint& now, ZoomHistory &zo
|
||||
switch (type) {
|
||||
case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now, zoomHistory); break;
|
||||
case StyleLayerType::Line: applyStyleProperties<LineProperties>(z, now, zoomHistory); break;
|
||||
case StyleLayerType::Circle: applyStyleProperties<CircleProperties>(z, now, zoomHistory); break;
|
||||
case StyleLayerType::Symbol: applyStyleProperties<SymbolProperties>(z, now, zoomHistory); break;
|
||||
case StyleLayerType::Raster: applyStyleProperties<RasterProperties>(z, now, zoomHistory); break;
|
||||
case StyleLayerType::Background: applyStyleProperties<BackgroundProperties>(z, now, zoomHistory); break;
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
StyleLayoutSymbol& operator=(const StyleLayoutSymbol &) = delete;
|
||||
|
||||
PlacementType placement = PlacementType::Point;
|
||||
float min_distance = 250.0f;
|
||||
float spacing = 250.0f;
|
||||
bool avoid_edges = false;
|
||||
|
||||
struct {
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
bool ignore_placement = false;
|
||||
bool optional = false;
|
||||
RotationAlignmentType rotation_alignment = RotationAlignmentType::Viewport;
|
||||
float size = 1.0f;
|
||||
float max_size = 1.0f;
|
||||
std::string image;
|
||||
float rotate = 0.0f;
|
||||
@@ -62,6 +63,7 @@ public:
|
||||
RotationAlignmentType rotation_alignment = RotationAlignmentType::Viewport;
|
||||
std::string field;
|
||||
std::string font = "Open Sans Regular, Arial Unicode MS Regular";
|
||||
float size = 16.0f;
|
||||
float max_size = 16.0f;
|
||||
float max_width = 15.0f /* em */;
|
||||
float line_height = 1.2f /* em */;
|
||||
|
||||
@@ -27,8 +27,11 @@ StyleParser::StyleParser(MapData& data_)
|
||||
}
|
||||
|
||||
void StyleParser::parse(JSVal document) {
|
||||
if (document.HasMember("constants")) {
|
||||
parseConstants(document["constants"]);
|
||||
if (document.HasMember("version")) {
|
||||
version = document["version"].GetInt();
|
||||
if (version != 8) {
|
||||
Log::Warning(Event::ParseStyle, "current renderer implementation only supports style spec version 8; using an outdated style will cause rendering errors");
|
||||
}
|
||||
}
|
||||
|
||||
if (document.HasMember("sources")) {
|
||||
@@ -89,37 +92,11 @@ void StyleParser::parse(JSVal document) {
|
||||
}
|
||||
}
|
||||
|
||||
void StyleParser::parseConstants(JSVal value) {
|
||||
if (value.IsObject()) {
|
||||
rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
|
||||
for (; itr != value.MemberEnd(); ++itr) {
|
||||
std::string name { itr->name.GetString(), itr->name.GetStringLength() };
|
||||
// Discard constants that don't start with an @ sign.
|
||||
if (name.length() && name[0] == '@') {
|
||||
constants.emplace(std::move(name), &itr->value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "constants must be an object");
|
||||
}
|
||||
}
|
||||
|
||||
JSVal StyleParser::replaceConstant(JSVal value) {
|
||||
if (value.IsString()) {
|
||||
auto it = constants.find({ value.GetString(), value.GetStringLength() });
|
||||
if (it != constants.end()) {
|
||||
return *it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#pragma mark - Parse Render Properties
|
||||
|
||||
template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, bool &target, const char *name) {
|
||||
if (value.HasMember(name)) {
|
||||
JSVal property = replaceConstant(value[name]);
|
||||
JSVal property = value[name];
|
||||
if (property.IsBool()) {
|
||||
target = property.GetBool();
|
||||
return StyleParserSuccess;
|
||||
@@ -133,7 +110,7 @@ template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, boo
|
||||
|
||||
template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, std::string &target, const char *name) {
|
||||
if (value.HasMember(name)) {
|
||||
JSVal property = replaceConstant(value[name]);
|
||||
JSVal property = value[name];
|
||||
if (property.IsString()) {
|
||||
target = { property.GetString(), property.GetStringLength() };
|
||||
return StyleParserSuccess;
|
||||
@@ -146,7 +123,7 @@ template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, std
|
||||
|
||||
template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, float &target, const char *name) {
|
||||
if (value.HasMember(name)) {
|
||||
JSVal property = replaceConstant(value[name]);
|
||||
JSVal property = value[name];
|
||||
if (property.IsNumber()) {
|
||||
target = property.GetDouble();
|
||||
return StyleParserSuccess;
|
||||
@@ -159,7 +136,7 @@ template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, flo
|
||||
|
||||
template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, uint16_t &target, const char *name) {
|
||||
if (value.HasMember(name)) {
|
||||
JSVal property = replaceConstant(value[name]);
|
||||
JSVal property = value[name];
|
||||
if (property.IsUint()) {
|
||||
unsigned int int_value = property.GetUint();
|
||||
if (int_value > std::numeric_limits<uint16_t>::max()) {
|
||||
@@ -178,7 +155,7 @@ template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, uin
|
||||
|
||||
template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, int32_t &target, const char *name) {
|
||||
if (value.HasMember(name)) {
|
||||
JSVal property = replaceConstant(value[name]);
|
||||
JSVal property = value[name];
|
||||
if (property.IsInt()) {
|
||||
target = property.GetInt();
|
||||
return StyleParserSuccess;
|
||||
@@ -191,7 +168,7 @@ template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, int
|
||||
|
||||
template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, vec2<float> &target, const char *name) {
|
||||
if (value.HasMember(name)) {
|
||||
JSVal property = replaceConstant(value[name]);
|
||||
JSVal property = value[name];
|
||||
if (property.IsArray()) {
|
||||
if (property.Size() >= 2) {
|
||||
target.x = property[(rapidjson::SizeType)0].GetDouble();
|
||||
@@ -210,7 +187,7 @@ template<> StyleParser::Status StyleParser::parseRenderProperty(JSVal value, vec
|
||||
template<typename Parser, typename T>
|
||||
StyleParser::Status StyleParser::parseRenderProperty(JSVal value, T &target, const char *name) {
|
||||
if (value.HasMember(name)) {
|
||||
JSVal property = replaceConstant(value[name]);
|
||||
JSVal property = value[name];
|
||||
if (property.IsString()) {
|
||||
target = Parser({ property.GetString(), property.GetStringLength() });
|
||||
return StyleParserSuccess;
|
||||
@@ -270,7 +247,7 @@ StyleParser::Result<std::vector<float>> StyleParser::parseFloatArray(JSVal value
|
||||
|
||||
std::vector<float> vec;
|
||||
for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
|
||||
JSVal part = replaceConstant(value[i]);
|
||||
JSVal part = value[i];
|
||||
if (!part.IsNumber()) {
|
||||
Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
|
||||
return Result<std::vector<float>> { StyleParserFailure, std::vector<float>() };
|
||||
@@ -297,9 +274,8 @@ StyleParser::Result<std::array<float, 2>> StyleParser::parseProperty(JSVal value
|
||||
|
||||
template <>
|
||||
StyleParser::Result<float> StyleParser::parseProperty(JSVal value, const char* property_name) {
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
if (rvalue.IsNumber()) {
|
||||
return Result<float> { StyleParserSuccess, rvalue.GetDouble() };
|
||||
if (value.IsNumber()) {
|
||||
return Result<float> { StyleParserSuccess, value.GetDouble() };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", property_name);
|
||||
return Result<float> { StyleParserFailure, 0.0f };
|
||||
@@ -308,23 +284,20 @@ StyleParser::Result<float> StyleParser::parseProperty(JSVal value, const char* p
|
||||
|
||||
template <>
|
||||
StyleParser::Result<Color> StyleParser::parseProperty(JSVal value, const char*) {
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
return Result<Color> { StyleParserSuccess, parseColor(rvalue) };
|
||||
return Result<Color> { StyleParserSuccess, parseColor(value) };
|
||||
}
|
||||
|
||||
template <>
|
||||
StyleParser::Result<Faded<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char*) {
|
||||
Faded<std::vector<float>> parsed;
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
parsed.to = std::get<1>(parseFloatArray(rvalue));
|
||||
parsed.to = std::get<1>(parseFloatArray(value));
|
||||
return Result<Faded<std::vector<float>>> { StyleParserSuccess, parsed };
|
||||
}
|
||||
|
||||
template <>
|
||||
StyleParser::Result<Faded<std::string>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
Faded<std::string> parsed;
|
||||
if (rvalue.IsString()) {
|
||||
if (value.IsString()) {
|
||||
parsed.to = { value.GetString(), value.GetStringLength() };
|
||||
return Result<Faded<std::string>> { StyleParserSuccess, parsed };
|
||||
} else {
|
||||
@@ -357,7 +330,7 @@ StyleParser::Result<std::vector<std::pair<float, T>>> StyleParser::parseStops(JS
|
||||
return Result<std::vector<std::pair<float, T>>> { StyleParserFailure, {}};
|
||||
}
|
||||
|
||||
stops.emplace_back(z.GetDouble(), std::get<1>(parseProperty<T>(replaceConstant(stop[rapidjson::SizeType(1)]), property_name)));
|
||||
stops.emplace_back(z.GetDouble(), std::get<1>(parseProperty<T>(stop[rapidjson::SizeType(1)], property_name)));
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
|
||||
return Result<std::vector<std::pair<float, T>>> { StyleParserFailure, {}};
|
||||
@@ -448,7 +421,7 @@ StyleParser::Status StyleParser::parseOptionalProperty(const char *property_name
|
||||
if (!value.HasMember(property_name)) {
|
||||
return StyleParserFailure;
|
||||
} else {
|
||||
return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass);
|
||||
return setProperty<T>(value[property_name], property_name, key, klass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,32 +431,38 @@ StyleParser::Status StyleParser::parseOptionalProperty(const char *property_name
|
||||
return StyleParserFailure;
|
||||
} else {
|
||||
if (value.HasMember(transition_name)) {
|
||||
return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass, value[transition_name]);
|
||||
return setProperty<T>(value[property_name], property_name, key, klass, value[transition_name]);
|
||||
} else {
|
||||
JSVal val = JSVal(rapidjson::kObjectType);
|
||||
return setProperty<T>(replaceConstant(value[property_name]), property_name, key, klass, val);
|
||||
return setProperty<T>(value[property_name], property_name, key, klass, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string normalizeFontStack(const std::string &name) {
|
||||
namespace algo = boost::algorithm;
|
||||
std::vector<std::string> parts;
|
||||
algo::split(parts, name, algo::is_any_of(","), algo::token_compress_on);
|
||||
std::for_each(parts.begin(), parts.end(), [](std::string& str) { algo::trim(str); });
|
||||
return algo::join(parts, ", ");
|
||||
}
|
||||
|
||||
template<> StyleParser::Result<std::string> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
if (!value.IsString()) {
|
||||
if (std::string { "text-font" } == property_name) {
|
||||
if (!value.IsArray()) {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of strings", property_name);
|
||||
return Result<std::string> { StyleParserFailure, std::string() };
|
||||
} else {
|
||||
std::string result = "";
|
||||
for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
|
||||
JSVal stop = value[i];
|
||||
if (stop.IsString()) {
|
||||
result += stop.GetString();
|
||||
if (i < value.Size()-1) {
|
||||
result += ",";
|
||||
}
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "text-font members must be strings");
|
||||
return Result<std::string> { StyleParserFailure, {} };
|
||||
}
|
||||
}
|
||||
return Result<std::string> { StyleParserSuccess, result };
|
||||
}
|
||||
} else if (!value.IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
|
||||
return Result<std::string> { StyleParserFailure, std::string() };
|
||||
}
|
||||
|
||||
if (std::string { "text-font" } == property_name) {
|
||||
return Result<std::string> {
|
||||
StyleParserSuccess, normalizeFontStack({ value.GetString(), value.GetStringLength() })
|
||||
};
|
||||
} else {
|
||||
return Result<std::string> { StyleParserSuccess, { value.GetString(), value.GetStringLength() } };
|
||||
}
|
||||
@@ -767,7 +746,7 @@ void StyleParser::parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair) {
|
||||
if (value.HasMember("ref")) {
|
||||
// This layer is referencing another layer. Inherit the bucket from that layer, if we
|
||||
// already parsed it.
|
||||
parseReference(replaceConstant(value["ref"]), layer);
|
||||
parseReference(value["ref"], layer);
|
||||
} else {
|
||||
// Otherwise, parse the source/source-layer/filter/render keys to form the bucket.
|
||||
parseBucket(value, layer);
|
||||
@@ -782,10 +761,10 @@ void StyleParser::parsePaints(JSVal value, std::map<ClassID, ClassProperties> &p
|
||||
const std::string name { itr->name.GetString(), itr->name.GetStringLength() };
|
||||
|
||||
if (name == "paint") {
|
||||
parsePaint(replaceConstant(itr->value), paints[ClassID::Default]);
|
||||
parsePaint(itr->value, paints[ClassID::Default]);
|
||||
} else if (name.compare(0, 6, "paint.") == 0 && name.length() > 6) {
|
||||
const ClassID class_id = ClassDictionary::Get().lookup(name.substr(6));
|
||||
parsePaint(replaceConstant(itr->value), paints[class_id]);
|
||||
parsePaint(itr->value, paints[class_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -803,7 +782,7 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<Function<std::array<float, 2>>>("fill-translate", Key::FillTranslate, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("fill-translate-transition", Key::FillTranslate, klass, value);
|
||||
parseOptionalProperty<Function<TranslateAnchorType>>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("fill-image", Key::FillImage, klass, value, "fill-image-transition");
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("fill-pattern", Key::FillImage, klass, value, "fill-pattern-transition");
|
||||
|
||||
parseOptionalProperty<Function<float>>("line-opacity", Key::LineOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-opacity-transition", Key::LineOpacity, klass, value);
|
||||
@@ -819,7 +798,14 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value);
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::vector<float>>>>("line-dasharray", Key::LineDashArray, klass, value, "line-dasharray-transition");
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("line-image", Key::LineImage, klass, value, "line-image-transition");
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("line-pattern", Key::LineImage, klass, value, "line-pattern-transition");
|
||||
|
||||
parseOptionalProperty<Function<float>>("circle-radius", Key::CircleRadius, klass, value);
|
||||
parseOptionalProperty<Function<Color>>("circle-color", Key::CircleColor, klass, value);
|
||||
parseOptionalProperty<Function<float>>("circle-opacity", Key::CircleOpacity, klass, value);
|
||||
parseOptionalProperty<Function<std::array<float,2>>>("circle-translate", Key::CircleTranslate, klass, value);
|
||||
parseOptionalProperty<Function<TranslateAnchorType>>("circle-translate-anchor", Key::CircleTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<Function<float>>("circle-blur", Key::CircleBlur, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("icon-opacity-transition", Key::IconOpacity, klass, value);
|
||||
@@ -869,7 +855,7 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
|
||||
|
||||
parseOptionalProperty<Function<float>>("background-opacity", Key::BackgroundOpacity, klass, value);
|
||||
parseOptionalProperty<Function<Color>>("background-color", Key::BackgroundColor, klass, value);
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("background-image", Key::BackgroundImage, klass, value, "background-image-transition");
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("background-pattern", Key::BackgroundImage, klass, value, "background-pattern-transition");
|
||||
}
|
||||
|
||||
void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
|
||||
@@ -883,13 +869,13 @@ void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
|
||||
parseOptionalProperty<Function<float>>("line-round-limit", Key::LineRoundLimit, bucket->layout, value);
|
||||
|
||||
parseOptionalProperty<Function<PlacementType>>("symbol-placement", Key::SymbolPlacement, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("symbol-min-distance", Key::SymbolMinDistance, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("symbol-spacing", Key::SymbolSpacing, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("symbol-avoid-edges", Key::SymbolAvoidEdges, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("icon-allow-overlap", Key::IconAllowOverlap, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("icon-ignore-placement", Key::IconIgnorePlacement, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("icon-optional", Key::IconOptional, bucket->layout, value);
|
||||
parseOptionalProperty<Function<RotationAlignmentType>>("icon-rotation-alignment", Key::IconRotationAlignment, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("icon-max-size", Key::IconMaxSize, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("icon-size", Key::IconSize, bucket->layout, value);
|
||||
parseOptionalProperty<Function<std::string>>("icon-image", Key::IconImage, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("icon-rotate", Key::IconRotate, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("icon-padding", Key::IconPadding, bucket->layout, value);
|
||||
@@ -898,7 +884,7 @@ void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
|
||||
parseOptionalProperty<Function<RotationAlignmentType>>("text-rotation-alignment", Key::TextRotationAlignment, bucket->layout, value);
|
||||
parseOptionalProperty<Function<std::string>>("text-field", Key::TextField, bucket->layout, value);
|
||||
parseOptionalProperty<Function<std::string>>("text-font", Key::TextFont, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-max-size", Key::TextMaxSize, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-size", Key::TextSize, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-max-width", Key::TextMaxWidth, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-line-height", Key::TextLineHeight, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-letter-spacing", Key::TextLetterSpacing, bucket->layout, value);
|
||||
@@ -948,7 +934,7 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
bucket->name = layer->id;
|
||||
|
||||
if (value.HasMember("source")) {
|
||||
JSVal value_source = replaceConstant(value["source"]);
|
||||
JSVal value_source = value["source"];
|
||||
if (value_source.IsString()) {
|
||||
bucket->source = { value_source.GetString(), value_source.GetStringLength() };
|
||||
auto source_it = sourcesMap.find(bucket->source);
|
||||
@@ -961,7 +947,7 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
}
|
||||
|
||||
if (value.HasMember("source-layer")) {
|
||||
JSVal value_source_layer = replaceConstant(value["source-layer"]);
|
||||
JSVal value_source_layer = value["source-layer"];
|
||||
if (value_source_layer.IsString()) {
|
||||
bucket->source_layer = { value_source_layer.GetString(), value_source_layer.GetStringLength() };
|
||||
} else {
|
||||
@@ -970,13 +956,11 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
}
|
||||
|
||||
if (value.HasMember("filter")) {
|
||||
JSVal value_filter = replaceConstant(value["filter"]);
|
||||
bucket->filter = parseFilterExpression(value_filter);
|
||||
bucket->filter = parseFilterExpression(value["filter"]);
|
||||
}
|
||||
|
||||
if (value.HasMember("layout")) {
|
||||
JSVal value_render = replaceConstant(value["layout"]);
|
||||
parseLayout(value_render, bucket);
|
||||
parseLayout(value["layout"], bucket);
|
||||
}
|
||||
|
||||
if (value.HasMember("minzoom")) {
|
||||
|
||||
@@ -52,9 +52,6 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void parseConstants(JSVal value);
|
||||
JSVal replaceConstant(JSVal value);
|
||||
|
||||
void parseSources(JSVal value);
|
||||
void parseLayers(JSVal value);
|
||||
void parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair);
|
||||
@@ -101,7 +98,7 @@ private:
|
||||
FilterExpression parseFilter(JSVal);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, const rapidjson::Value *> constants;
|
||||
std::uint8_t version;
|
||||
|
||||
std::vector<std::unique_ptr<Source>> sources;
|
||||
std::vector<util::ptr<StyleLayer>> layers;
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace mbgl {
|
||||
|
||||
template<> const FillProperties &defaultStyleProperties() { static const FillProperties p; return p; }
|
||||
template<> const LineProperties &defaultStyleProperties() { static const LineProperties p; return p; }
|
||||
template<> const CircleProperties &defaultStyleProperties() { static const CircleProperties p; return p; }
|
||||
template<> const SymbolProperties &defaultStyleProperties() { static const SymbolProperties p; return p; }
|
||||
template<> const RasterProperties &defaultStyleProperties() { static const RasterProperties p; return p; }
|
||||
template<> const BackgroundProperties &defaultStyleProperties() { static const BackgroundProperties p; return p; }
|
||||
|
||||
Submodule src/mbgl/util/geojsonvt updated: 995ffc72c5...ed99a6290f
@@ -1,74 +1,110 @@
|
||||
#include <mbgl/util/mapbox.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace mbgl {
|
||||
namespace util {
|
||||
namespace mapbox {
|
||||
|
||||
const std::string mapbox = "mapbox://";
|
||||
const std::string protocol = "mapbox://";
|
||||
const std::string baseURL = "https://api.mapbox.com/";
|
||||
|
||||
std::string normalizeURL(const std::string& url, const std::string& pathPrefix, const std::string& accessToken) {
|
||||
if (accessToken.empty())
|
||||
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
|
||||
bool isMapboxURL(const std::string& url) {
|
||||
return url.compare(0, protocol.length(), protocol) == 0;
|
||||
}
|
||||
|
||||
return std::string("https://api.tiles.mapbox.com")
|
||||
+ pathPrefix
|
||||
+ url.substr(mapbox.length())
|
||||
+ "?access_token="
|
||||
+ accessToken;
|
||||
std::vector<std::string> getMapboxURLPathname(const std::string& url) {
|
||||
std::vector<std::string> pathname;
|
||||
std::size_t startIndex = protocol.length();
|
||||
while (startIndex < url.length()) {
|
||||
std::size_t endIndex = url.find("/", startIndex);
|
||||
if (endIndex == std::string::npos) {
|
||||
endIndex = url.find_first_of("?#");
|
||||
}
|
||||
if (endIndex == std::string::npos) {
|
||||
endIndex = url.length();
|
||||
}
|
||||
pathname.push_back(url.substr(startIndex, endIndex - startIndex));
|
||||
startIndex = endIndex + 1;
|
||||
}
|
||||
return pathname;
|
||||
}
|
||||
|
||||
std::string normalizeSourceURL(const std::string& url, const std::string& accessToken) {
|
||||
if (url.compare(0, mapbox.length(), mapbox) != 0)
|
||||
if (!isMapboxURL(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
std::string result = normalizeURL(url + ".json", "/v4/", accessToken);
|
||||
if (accessToken.empty()) {
|
||||
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
|
||||
}
|
||||
|
||||
// TileJSON requests need a secure flag appended to their URLs so
|
||||
// that the server knows to send SSL-ified resource references.
|
||||
result += "&secure";
|
||||
|
||||
return result;
|
||||
return baseURL + "v4/" + url.substr(protocol.length()) + ".json?access_token=" + accessToken + "&secure";
|
||||
}
|
||||
|
||||
std::string normalizeStyleURL(const std::string& url, const std::string& accessToken) {
|
||||
if (url.compare(0, mapbox.length(), mapbox) != 0)
|
||||
if (!isMapboxURL(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
const std::string user = url.substr(mapbox.length(), url.find('.') - mapbox.length());
|
||||
std::vector<std::string> pathname = getMapboxURLPathname(url);
|
||||
std::string user = pathname[1];
|
||||
std::string id = pathname[2];
|
||||
bool isDraft = pathname.size() > 3;
|
||||
return baseURL + "styles/v1/" + user + "/" + id + (isDraft ? "/draft" : "") + "?access_token=" + accessToken;
|
||||
}
|
||||
|
||||
return normalizeURL(url, "/styles/v1/" + user + "/", accessToken);
|
||||
std::string normalizeSpriteURL(const std::string& url, const std::string& accessToken) {
|
||||
if (!isMapboxURL(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
std::vector<std::string> pathname = getMapboxURLPathname(url);
|
||||
std::string user = pathname[1];
|
||||
bool isDraft = pathname.size() > 3;
|
||||
|
||||
std::string id, extension;
|
||||
if (isDraft) {
|
||||
size_t index = pathname[3].find_first_of("@.");
|
||||
id = pathname[2];
|
||||
extension = pathname[3].substr(index);
|
||||
} else {
|
||||
size_t index = pathname[2].find_first_of("@.");
|
||||
id = pathname[2].substr(0, index);
|
||||
extension = pathname[2].substr(index);
|
||||
}
|
||||
|
||||
return baseURL + "styles/v1/" + user + "/" + id + "/" + (isDraft ? "draft/" : "") + "sprite" + extension + "?access_token=" + accessToken;
|
||||
}
|
||||
|
||||
std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken) {
|
||||
if (url.compare(0, mapbox.length(), mapbox) != 0) {
|
||||
if (!isMapboxURL(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
const std::string fontstack = "mapbox://fontstack/";
|
||||
std::vector<std::string> pathname = getMapboxURLPathname(url);
|
||||
std::string user = pathname[1];
|
||||
std::string fontstack = pathname[2];
|
||||
std::string range = pathname[3];
|
||||
|
||||
if (url.compare(0, fontstack.length(), fontstack) == 0) {
|
||||
return normalizeURL(url, "/v4/", accessToken);
|
||||
}
|
||||
|
||||
return normalizeURL(url, "/", accessToken);
|
||||
return baseURL + "fonts/v1/" + user + "/" + fontstack + "/" + range + "?access_token=" + accessToken;
|
||||
}
|
||||
|
||||
std::string normalizeTileURL(const std::string& url, const std::string& sourceURL, SourceType sourceType) {
|
||||
if (sourceURL.empty() || sourceURL.compare(0, mapbox.length(), mapbox) != 0 ||
|
||||
sourceType != SourceType::Raster) {
|
||||
if (sourceURL.empty() || !isMapboxURL(sourceURL) || sourceType != SourceType::Raster) {
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
std::string::size_type queryIdx = url.rfind("?");
|
||||
// Trim off the right end but never touch anything before the extension dot.
|
||||
std::string urlSansParams((queryIdx == std::string::npos) ? url : url.substr(0, queryIdx));
|
||||
|
||||
|
||||
while (!urlSansParams.empty() && isdigit(urlSansParams.back())) {
|
||||
urlSansParams.pop_back();
|
||||
}
|
||||
|
||||
|
||||
std::string::size_type basenameIdx = url.rfind("/", queryIdx);
|
||||
std::string::size_type extensionIdx = url.rfind(".", queryIdx);
|
||||
if (basenameIdx == std::string::npos || extensionIdx == std::string::npos ||
|
||||
@@ -76,7 +112,7 @@ std::string normalizeTileURL(const std::string& url, const std::string& sourceUR
|
||||
// No file extension: probably not a file name we can tack a ratio onto.
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
std::string normalizedURL(url);
|
||||
normalizedURL.insert(extensionIdx, "{ratio}");
|
||||
return normalizedURL;
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace mapbox {
|
||||
|
||||
std::string normalizeSourceURL(const std::string& url, const std::string& accessToken);
|
||||
std::string normalizeStyleURL(const std::string& url, const std::string& accessToken);
|
||||
std::string normalizeSpriteURL(const std::string& url, const std::string& accessToken);
|
||||
std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken);
|
||||
std::string normalizeTileURL(const std::string& url, const std::string& sourceURL, SourceType sourceType);
|
||||
|
||||
|
||||
2
styles
2
styles
Submodule styles updated: 44bdcec816...19dde3cb1c
2
test/fixtures/api/water.json
vendored
2
test/fixtures/api/water.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 7,
|
||||
"version": 8,
|
||||
"name": "Water",
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
|
||||
2
test/fixtures/headless/pois.json
vendored
2
test/fixtures/headless/pois.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 7,
|
||||
"version": 8,
|
||||
"name": "POIs",
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
|
||||
3
test/fixtures/mock_view.hpp
vendored
3
test/fixtures/mock_view.hpp
vendored
@@ -20,7 +20,8 @@ public:
|
||||
void deactivate() override {};
|
||||
void notify() override {};
|
||||
void invalidate() override {}
|
||||
void swap() override {}
|
||||
void beforeRender() override {}
|
||||
void afterRender() override {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
6
test/fixtures/resources/style.json
vendored
6
test/fixtures/resources/style.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 1,
|
||||
"version": 8,
|
||||
"name": "Test",
|
||||
"sources": {
|
||||
"vectorsource": {
|
||||
@@ -20,7 +20,7 @@
|
||||
"source": "vectorsource",
|
||||
"source-layer": "road_label",
|
||||
"layout": {
|
||||
"text-font": "Open Sans Regular, Arial Unicode MS Regular",
|
||||
"text-font": ["Open Sans Regular", "Arial Unicode MS Regular"],
|
||||
"text-field": "{name_en}"
|
||||
}
|
||||
}, {
|
||||
@@ -29,7 +29,7 @@
|
||||
"source": "vectorsource",
|
||||
"source-layer": "poi_label",
|
||||
"layout": {
|
||||
"text-font": "Open Sans Regular, Arial Unicode MS Regular",
|
||||
"text-font": ["Open Sans Regular", "Arial Unicode MS Regular"],
|
||||
"icon-image": "{maki}_icon"
|
||||
}
|
||||
}]
|
||||
|
||||
7
test/fixtures/style_parser/circle-blur.info.json
vendored
Normal file
7
test/fixtures/style_parser/circle-blur.info.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"default": {
|
||||
"log": [
|
||||
[1, "WARNING", "ParseStyle", "value of 'circle-blur' must be a number, or a number function"]
|
||||
]
|
||||
}
|
||||
}
|
||||
18
test/fixtures/style_parser/circle-blur.style.json
vendored
Normal file
18
test/fixtures/style_parser/circle-blur.style.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "circle_blur_example",
|
||||
"type": "circle",
|
||||
"source": "mapbox",
|
||||
"paint": {
|
||||
"circle-blur": null
|
||||
}
|
||||
}]
|
||||
}
|
||||
7
test/fixtures/style_parser/circle-color.info.json
vendored
Normal file
7
test/fixtures/style_parser/circle-color.info.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"default": {
|
||||
"log": [
|
||||
[1, "WARNING", "ParseStyle", "color value must be a string"]
|
||||
]
|
||||
}
|
||||
}
|
||||
18
test/fixtures/style_parser/circle-color.style.json
vendored
Normal file
18
test/fixtures/style_parser/circle-color.style.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "circle_color_example",
|
||||
"type": "circle",
|
||||
"source": "mapbox",
|
||||
"paint": {
|
||||
"circle-color": null
|
||||
}
|
||||
}]
|
||||
}
|
||||
7
test/fixtures/style_parser/circle-opacity.info.json
vendored
Normal file
7
test/fixtures/style_parser/circle-opacity.info.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"default": {
|
||||
"log": [
|
||||
[1, "WARNING", "ParseStyle", "value of 'circle-opacity' must be a number, or a number function"]
|
||||
]
|
||||
}
|
||||
}
|
||||
18
test/fixtures/style_parser/circle-opacity.style.json
vendored
Normal file
18
test/fixtures/style_parser/circle-opacity.style.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "circle_opacity_example",
|
||||
"type": "circle",
|
||||
"source": "mapbox",
|
||||
"paint": {
|
||||
"circle-opacity": null
|
||||
}
|
||||
}]
|
||||
}
|
||||
7
test/fixtures/style_parser/circle-radius.info.json
vendored
Normal file
7
test/fixtures/style_parser/circle-radius.info.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"default": {
|
||||
"log": [
|
||||
[1, "WARNING", "ParseStyle", "value of 'circle-radius' must be a number, or a number function"]
|
||||
]
|
||||
}
|
||||
}
|
||||
18
test/fixtures/style_parser/circle-radius.style.json
vendored
Normal file
18
test/fixtures/style_parser/circle-radius.style.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "circle_radius_example",
|
||||
"type": "circle",
|
||||
"source": "mapbox",
|
||||
"paint": {
|
||||
"circle-radius": null
|
||||
}
|
||||
}]
|
||||
}
|
||||
2
test/fixtures/style_parser/colors.style.json
vendored
2
test/fixtures/style_parser/colors.style.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"constants": {
|
||||
"@land": "r44,239,225)",
|
||||
"@snow": "f4f8foNGbjf#",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
@@ -31,7 +31,7 @@
|
||||
"source-layer": "waterway",
|
||||
"layout": {
|
||||
"text-font": {
|
||||
"stops": [[0, "Open Sans Regular"]]
|
||||
"stops": [[0, ["Open Sans Regular"]]]
|
||||
},
|
||||
"text-keep-upright": {
|
||||
"stops": [[0, false], [10, true]]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": 6,
|
||||
"version": 8,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
|
||||
@@ -8,22 +8,30 @@
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(Mapbox, SourceURL) {
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "key"), "https://api.tiles.mapbox.com/v4/user.map.json?access_token=key&secure");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "token"), "https://api.tiles.mapbox.com/v4/user.map.json?access_token=token&secure");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "key"), "https://api.mapbox.com/v4/user.map.json?access_token=key&secure");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "token"), "https://api.mapbox.com/v4/user.map.json?access_token=token&secure");
|
||||
EXPECT_THROW(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", ""), std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(Mapbox, GlyphsURL) {
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("mapbox://fontstack/{fontstack}/{range}.pbf", "key"), "https://api.tiles.mapbox.com/v4/fontstack/{fontstack}/{range}.pbf?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("mapbox://fonts/v1/user/{fontstack}/{range}.pbf", "key"), "https://api.tiles.mapbox.com/fonts/v1/user/{fontstack}/{range}.pbf?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("mapbox://fonts/boxmap/Comic%20Sans/0-255.pbf", "key"), "https://api.mapbox.com/fonts/v1/boxmap/Comic%20Sans/0-255.pbf?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("mapbox://fonts/boxmap/{fontstack}/{range}.pbf", "key"), "https://api.mapbox.com/fonts/v1/boxmap/{fontstack}/{range}.pbf?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("http://path", "key"), "http://path");
|
||||
}
|
||||
|
||||
TEST(Mapbox, StyleURL) {
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("mapbox://user.style", "key"), "https://api.tiles.mapbox.com/styles/v1/user/user.style?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("mapbox://styles/user/style", "key"), "https://api.mapbox.com/styles/v1/user/style?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("mapbox://styles/user/style/draft", "key"), "https://api.mapbox.com/styles/v1/user/style/draft?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("http://path", "key"), "http://path");
|
||||
}
|
||||
|
||||
TEST(Mapbox, SpriteURL) {
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("map/box/sprites@2x.json", "key"), "map/box/sprites@2x.json");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("mapbox://sprites/mapbox/streets-v8.json", "key"), "https://api.mapbox.com/styles/v1/mapbox/streets-v8/sprite.json?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("mapbox://sprites/mapbox/streets-v8@2x.png", "key"), "https://api.mapbox.com/styles/v1/mapbox/streets-v8/sprite@2x.png?access_token=key");
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("mapbox://sprites/mapbox/streets-v8/draft@2x.png", "key"), "https://api.mapbox.com/styles/v1/mapbox/streets-v8/draft/sprite@2x.png?access_token=key");
|
||||
}
|
||||
|
||||
TEST(Mapbox, TileURL) {
|
||||
try {
|
||||
EXPECT_EQ(mbgl::util::mapbox::normalizeTileURL("http://path.png/tile.png", "mapbox://user.map", SourceType::Raster), "http://path.png/tile{ratio}.png");
|
||||
|
||||
Submodule test/suite updated: b6b8a25e76...b6828212d3
Reference in New Issue
Block a user