Merge remote-tracking branch 'origin/master' into line-label-density
This commit is contained in:
17
README.md
17
README.md
@@ -40,19 +40,18 @@ To create projects, you can run:
|
||||
|
||||
Note that you can't have more than one project in Xcode open at a time since they the static library project is shared across the OS X, Linux and iOS project.
|
||||
|
||||
Target OS: 10.9+
|
||||
Target OS X: 10.9+
|
||||
|
||||
|
||||
## iOS
|
||||
|
||||
If you just want to install the library for iOS and try it out as an Objective-C consumer, run `./scripts/package_ios.sh`. It will require the Boost headers to be installed, so use [Homebrew](http://brew.sh/) to install it via `brew install boost`. The script will produce the statically-linked `libMapboxGL.a`, `MapboxGL.bundle` for resources, and a `Headers` folder.
|
||||
If you merely want to install the library for iOS and try it out as an Objective-C consumer, run `./scripts/package_ios.sh`. It requires the Boost headers to be installed, so use [Homebrew](http://brew.sh/) to install them (`brew install boost`). The packaging script will produce the statically-linked `libMapboxGL.a`, `MapboxGL.bundle` for resources, and a `Headers` folder.
|
||||
|
||||
If you want to build from source and/or contribute to development of the project, you can run `make iproj`, which will create and open an Xcode project which can build the entire library from source as well as an Objective-C test app.
|
||||
If you want to build from source and/or contribute to development of the project, run `make iproj`, which will create and open an Xcode project which can build the entire library from source as well as an Objective-C test app.
|
||||
|
||||
Target devices: iPhone 4S and above (5, 5c, 5s, 6, 6 Plus) and iPad 2 and above (3, 4, Mini, Air, Mini 2, Air 2).
|
||||
|
||||
iOS SDK: 8.1
|
||||
Supported iOS: 7.0+
|
||||
Target iOS: 7.0 through 8.1
|
||||
|
||||
|
||||
## Linux
|
||||
@@ -101,7 +100,11 @@ Set an access token as described below, and then run:
|
||||
|
||||
make run-linux
|
||||
|
||||
## Android (on Linux)
|
||||
## Android
|
||||
|
||||
Target devices: All Android devices on Android 4.0 or newer (API level >= 14)
|
||||
|
||||
### On Linux
|
||||
|
||||
Install a few build dependencies:
|
||||
|
||||
@@ -126,7 +129,7 @@ Run:
|
||||
|
||||
You can then open `android/java` in Android Studio via "Import Non-Android Studio Project".
|
||||
|
||||
## Android (on OS X)
|
||||
### On OS X
|
||||
|
||||
Install Oracle JDK 7 (requires license agreement) from http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
|
||||
|
||||
|
||||
@@ -16,7 +16,3 @@ make android BUILDTYPE=$BUILDTYPE JOBS=$JOBS
|
||||
|
||||
aws s3 cp ./android/java/app/build/outputs/apk/app-debug.apk s3://mapbox-gl-testing/android/${NAME}/app-debug.apk
|
||||
aws s3 cp ./android/java/app/build/outputs/apk/app-release-unsigned.apk s3://mapbox-gl-testing/android/${NAME}/app-release-unsigned.apk
|
||||
|
||||
if [[ $TESTMUNK == "yes" ]]; then
|
||||
./android/scripts/upload-testmunk.sh ./android/java/app/build/outputs/apk/app-debug.apk
|
||||
fi
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
EMAIL="leith@mapbox.com"
|
||||
APP_NAME="Mapbox"
|
||||
APK_PATH=$1
|
||||
|
||||
echo "submitting testrun to testmunk"
|
||||
|
||||
echo "uploading features..."
|
||||
|
||||
zip -r android/test/features.zip android/test/features/
|
||||
RESPONSE=$(curl -f -H "Accept: application/vnd.testmunk.v1+json" -F "file=@android/test/features.zip" "https://${TESTMUNK_KEY}@api.testmunk.com/apps/${APP_NAME}/testcases")
|
||||
|
||||
echo "uploading apk..."
|
||||
|
||||
RESPONSE=$(curl -f -H "Accept: application/vnd.testmunk.v1+json" -F "file=@${APK_PATH}" -F "email=${EMAIL}" -F "autoStart=true" -F "public=true" "https://${TESTMUNK_KEY}@api.testmunk.com/apps/${APP_NAME}/testruns")
|
||||
|
||||
TESTRUN_ID=$(echo "${RESPONSE}" | jq -r '.id')
|
||||
TESTRUN_NAME=$(echo "${RESPONSE}" | jq -r '.name')
|
||||
|
||||
echo "successully uploaded to Testmunk as '${TESTRUN_NAME}'"
|
||||
echo "public link to test results: https://www.testmunk.com/testrun/${TESTRUN_ID}"
|
||||
1
android/test/.gitignore
vendored
1
android/test/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
features.zip
|
||||
@@ -1,5 +0,0 @@
|
||||
Feature: Testapp V.1.2
|
||||
|
||||
Scenario: 1) Start app and load map
|
||||
Given I await for 5 seconds
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
require 'calabash-android/calabash_steps'
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
Then /^I await for ([\d\.]+) second(?:s)?$/ do |num_seconds|
|
||||
num_seconds = num_seconds.to_f
|
||||
sleep num_seconds
|
||||
|
||||
end
|
||||
@@ -1,36 +0,0 @@
|
||||
require 'calabash-android/management/app_installation'
|
||||
|
||||
AfterConfiguration do |config|
|
||||
FeatureNameMemory.feature_name = nil
|
||||
end
|
||||
|
||||
Before do |scenario|
|
||||
@scenario_is_outline = (scenario.class == Cucumber::Ast::OutlineTable::ExampleRow)
|
||||
if @scenario_is_outline
|
||||
scenario = scenario.scenario_outline
|
||||
end
|
||||
|
||||
feature_name = scenario.feature.title
|
||||
if FeatureNameMemory.feature_name != feature_name \
|
||||
or ENV["RESET_BETWEEN_SCENARIOS"] == "1"
|
||||
if ENV["RESET_BETWEEN_SCENARIOS"] == "1"
|
||||
log "New scenario - reinstalling apps"
|
||||
else
|
||||
log "First scenario in feature - reinstalling apps"
|
||||
end
|
||||
|
||||
uninstall_apps
|
||||
install_app(ENV["TEST_APP_PATH"])
|
||||
install_app(ENV["APP_PATH"])
|
||||
FeatureNameMemory.feature_name = feature_name
|
||||
FeatureNameMemory.invocation = 1
|
||||
else
|
||||
FeatureNameMemory.invocation += 1
|
||||
end
|
||||
end
|
||||
|
||||
FeatureNameMemory = Class.new
|
||||
class << FeatureNameMemory
|
||||
@feature_name = nil
|
||||
attr_accessor :feature_name, :invocation
|
||||
end
|
||||
@@ -1,13 +0,0 @@
|
||||
require 'calabash-android/management/adb'
|
||||
require 'calabash-android/operations'
|
||||
|
||||
Before do |scenario|
|
||||
start_test_server_in_background
|
||||
end
|
||||
|
||||
After do |scenario|
|
||||
if scenario.failed?
|
||||
screenshot_embed
|
||||
end
|
||||
shutdown_test_server
|
||||
end
|
||||
@@ -1 +0,0 @@
|
||||
require 'calabash-android/cucumber'
|
||||
1
configure
vendored
1
configure
vendored
@@ -92,7 +92,6 @@ CONFIG="# Do not edit. Generated by the configure script.
|
||||
'libraries': []
|
||||
},
|
||||
'variables': {
|
||||
'python': '${PYTHON}',
|
||||
"
|
||||
|
||||
if [ ! -z ${BOOST_VERSION} ]; then
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
'<(SHARED_INTERMEDIATE_DIR)/src/shader/shaders_gl.cpp',
|
||||
'<(SHARED_INTERMEDIATE_DIR)/src/shader/shaders_gles2.cpp',
|
||||
],
|
||||
'action': ['<@(python)', 'scripts/build-shaders.py', '<(SHARED_INTERMEDIATE_DIR)', '<@(_inputs)'],
|
||||
'action': ['scripts/build-shaders.py', '<(SHARED_INTERMEDIATE_DIR)', '<@(_inputs)'],
|
||||
}
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
'outputs': [
|
||||
'<(SHARED_INTERMEDIATE_DIR)/include/mbgl/util/version.hpp',
|
||||
],
|
||||
'action': ['<@(python)', '<@(_inputs)', '<(SHARED_INTERMEDIATE_DIR)', '<!@(git describe --tags --always --abbrev=0)', '<!@(git rev-parse HEAD)'],
|
||||
'action': ['<@(_inputs)', '<(SHARED_INTERMEDIATE_DIR)', '<!@(git describe --tags --always --abbrev=0)', '<!@(git rev-parse HEAD)'],
|
||||
}
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
#include <GL/glx.h>
|
||||
#undef None
|
||||
@@ -5,9 +5,12 @@
|
||||
#define MBGL_USE_CGL 1
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <mbgl/platform/default/glx.h>
|
||||
#define MBGL_USE_GLX 1
|
||||
#undef Status
|
||||
typedef struct _XDisplay Display;
|
||||
typedef struct __GLXcontextRec* GLXContext;
|
||||
typedef struct __GLXFBConfigRec* GLXFBConfig;
|
||||
typedef long unsigned int XID;
|
||||
typedef XID GLXPbuffer;
|
||||
#endif
|
||||
|
||||
#include <mbgl/map/view.hpp>
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#if MBGL_USE_GLX
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
HeadlessDisplay::HeadlessDisplay() {
|
||||
@@ -52,7 +56,7 @@ HeadlessDisplay::HeadlessDisplay() {
|
||||
// We're creating a dummy pbuffer anyway that we're not using.
|
||||
static int pixelFormat[] = {
|
||||
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
|
||||
0
|
||||
None
|
||||
};
|
||||
|
||||
int configs = 0;
|
||||
|
||||
@@ -28,6 +28,8 @@ CGLProc CGLGetProcAddress(const char *proc) {
|
||||
CFRelease(name);
|
||||
return symbol;
|
||||
}
|
||||
#elif MBGL_USE_GLX
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
@@ -104,7 +106,7 @@ void HeadlessView::createContext() {
|
||||
|
||||
if (!glContext) {
|
||||
// Try to create a legacy context
|
||||
glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, 0, True);
|
||||
glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
|
||||
if (glContext) {
|
||||
if (!glXIsDirect(xDisplay, glContext)) {
|
||||
mbgl::Log::Error(mbgl::Event::OpenGL, "Failed to create direct OpenGL Legacy context");
|
||||
@@ -123,7 +125,7 @@ void HeadlessView::createContext() {
|
||||
int pbufferAttributes[] = {
|
||||
GLX_PBUFFER_WIDTH, 8,
|
||||
GLX_PBUFFER_HEIGHT, 8,
|
||||
0
|
||||
None
|
||||
};
|
||||
glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
|
||||
#endif
|
||||
|
||||
@@ -219,6 +219,14 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
gl::GenVertexArrays = glGenVertexArraysOES;
|
||||
gl::IsVertexArray = glIsVertexArrayOES;
|
||||
}
|
||||
|
||||
if (extensions.find("GL_OES_packed_depth_stencil") != std::string::npos) {
|
||||
gl::isPackedDepthStencilSupported = YES;
|
||||
}
|
||||
|
||||
if (extensions.find("GL_OES_depth24") != std::string::npos) {
|
||||
gl::isDepth24Supported = YES;
|
||||
}
|
||||
}
|
||||
|
||||
// setup mbgl map
|
||||
@@ -1563,13 +1571,11 @@ class MBGLView : public mbgl::View
|
||||
{
|
||||
if (delay != std::chrono::steady_clock::duration::zero())
|
||||
{
|
||||
__weak MGLMapView *weakNativeView = nativeView;
|
||||
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, std::chrono::duration_cast<std::chrono::nanoseconds>(delay).count()), dispatch_get_main_queue(), ^
|
||||
{
|
||||
[weakNativeView performSelector:@selector(notifyMapChange:)
|
||||
withObject:@(change)
|
||||
afterDelay:0];
|
||||
[nativeView performSelector:@selector(notifyMapChange:)
|
||||
withObject:@(change)
|
||||
afterDelay:0];
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -1601,7 +1607,7 @@ class MBGLView : public mbgl::View
|
||||
}
|
||||
|
||||
private:
|
||||
MGLMapView *nativeView = nullptr;
|
||||
__weak MGLMapView *nativeView = nullptr;
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
0
scripts/build-shaders.py
Normal file → Executable file
0
scripts/build-shaders.py
Normal file → Executable file
0
scripts/build-version.py
Normal file → Executable file
0
scripts/build-version.py
Normal file → Executable file
@@ -161,8 +161,7 @@ void TileParser::applyLayoutProperties<SymbolProperties>(StyleBucket &bucket_des
|
||||
applyLayoutProperty(PropertyKey::IconPadding, bucket_desc.layout, symbol.icon.padding, z);
|
||||
applyLayoutProperty(PropertyKey::IconRotate, bucket_desc.layout, symbol.icon.rotate, z);
|
||||
applyLayoutProperty(PropertyKey::IconKeepUpright, bucket_desc.layout, symbol.icon.keep_upright, z);
|
||||
applyLayoutProperty(PropertyKey::IconOffsetX, bucket_desc.layout, symbol.icon.offset[0], z);
|
||||
applyLayoutProperty(PropertyKey::IconOffsetY, bucket_desc.layout, symbol.icon.offset[1], z);
|
||||
applyLayoutProperty(PropertyKey::IconOffset, bucket_desc.layout, symbol.icon.offset, z);
|
||||
|
||||
applyLayoutProperty(PropertyKey::TextRotationAlignment, bucket_desc.layout, symbol.text.rotation_alignment, z);
|
||||
applyLayoutProperty(PropertyKey::TextField, bucket_desc.layout, symbol.text.field, z);
|
||||
@@ -180,8 +179,7 @@ void TileParser::applyLayoutProperties<SymbolProperties>(StyleBucket &bucket_des
|
||||
applyLayoutProperty(PropertyKey::TextAnchor, bucket_desc.layout, symbol.text.anchor, z);
|
||||
applyLayoutProperty(PropertyKey::TextKeepUpright, bucket_desc.layout, symbol.text.keep_upright, z);
|
||||
applyLayoutProperty(PropertyKey::TextTransform, bucket_desc.layout, symbol.text.transform, z);
|
||||
applyLayoutProperty(PropertyKey::TextOffsetX, bucket_desc.layout, symbol.text.offset[0], z);
|
||||
applyLayoutProperty(PropertyKey::TextOffsetY, bucket_desc.layout, symbol.text.offset[1], z);
|
||||
applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, symbol.text.offset, z);
|
||||
applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, symbol.text.allow_overlap, z);
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>&
|
||||
|
||||
drawClippingMasks(sources);
|
||||
|
||||
recordZoom(time, state.getNormalizedZoom());
|
||||
frameHistory.record(time, state.getNormalizedZoom());
|
||||
|
||||
// Actually render the layers
|
||||
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
|
||||
@@ -375,39 +375,58 @@ void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc
|
||||
void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
|
||||
const BackgroundProperties& properties = layer_desc->getProperties<BackgroundProperties>();
|
||||
|
||||
if (properties.image.size()) {
|
||||
if (properties.image.to.size()) {
|
||||
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
|
||||
return;
|
||||
|
||||
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
|
||||
SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.from, true);
|
||||
SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.to, true);
|
||||
float zoomFraction = state.getZoomFraction();
|
||||
|
||||
useProgram(patternShader->program);
|
||||
patternShader->u_matrix = identityMatrix;
|
||||
patternShader->u_pattern_tl = imagePos.tl;
|
||||
patternShader->u_pattern_br = imagePos.br;
|
||||
patternShader->u_mix = zoomFraction;
|
||||
patternShader->u_pattern_tl_a = imagePosA.tl;
|
||||
patternShader->u_pattern_br_a = imagePosA.br;
|
||||
patternShader->u_pattern_tl_b = imagePosB.tl;
|
||||
patternShader->u_pattern_br_b = imagePosB.br;
|
||||
patternShader->u_mix = properties.image.t;
|
||||
patternShader->u_opacity = properties.opacity;
|
||||
|
||||
std::array<float, 2> size = imagePos.size;
|
||||
double lon, lat;
|
||||
state.getLonLat(lon, lat);
|
||||
std::array<float, 2> center = state.locationCoordinate(lon, lat);
|
||||
float scale = 1 / std::pow(2, zoomFraction);
|
||||
|
||||
mat3 matrix;
|
||||
matrix::identity(matrix);
|
||||
matrix::scale(matrix, matrix,
|
||||
1.0f / size[0],
|
||||
1.0f / size[1]);
|
||||
matrix::translate(matrix, matrix,
|
||||
std::fmod(center[0] * 512, size[0]),
|
||||
std::fmod(center[1] * 512, size[1]));
|
||||
matrix::rotate(matrix, matrix, -state.getAngle());
|
||||
matrix::scale(matrix, matrix,
|
||||
std::array<float, 2> sizeA = imagePosA.size;
|
||||
mat3 matrixA;
|
||||
matrix::identity(matrixA);
|
||||
matrix::scale(matrixA, matrixA,
|
||||
1.0f / (sizeA[0] * properties.image.fromScale),
|
||||
1.0f / (sizeA[1] * properties.image.fromScale));
|
||||
matrix::translate(matrixA, matrixA,
|
||||
std::fmod(center[0] * 512, sizeA[0] * properties.image.fromScale),
|
||||
std::fmod(center[1] * 512, sizeA[1] * properties.image.fromScale));
|
||||
matrix::rotate(matrixA, matrixA, -state.getAngle());
|
||||
matrix::scale(matrixA, matrixA,
|
||||
scale * state.getWidth() / 2,
|
||||
-scale * state.getHeight() / 2);
|
||||
patternShader->u_patternmatrix = matrix;
|
||||
|
||||
std::array<float, 2> sizeB = imagePosB.size;
|
||||
mat3 matrixB;
|
||||
matrix::identity(matrixB);
|
||||
matrix::scale(matrixB, matrixB,
|
||||
1.0f / (sizeB[0] * properties.image.toScale),
|
||||
1.0f / (sizeB[1] * properties.image.toScale));
|
||||
matrix::translate(matrixB, matrixB,
|
||||
std::fmod(center[0] * 512, sizeB[0] * properties.image.toScale),
|
||||
std::fmod(center[1] * 512, sizeB[1] * properties.image.toScale));
|
||||
matrix::rotate(matrixB, matrixB, -state.getAngle());
|
||||
matrix::scale(matrixB, matrixB,
|
||||
scale * state.getWidth() / 2,
|
||||
-scale * state.getHeight() / 2);
|
||||
|
||||
patternShader->u_patternmatrix_a = matrixA;
|
||||
patternShader->u_patternmatrix_b = matrixB;
|
||||
|
||||
backgroundBuffer.bind();
|
||||
patternShader->bind(0);
|
||||
@@ -459,26 +478,3 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &t
|
||||
return vtxMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::recordZoom(const std::chrono::steady_clock::time_point time, const float zoom) {
|
||||
frameHistory.record(time, zoom);
|
||||
|
||||
if (lastZoom < 0) {
|
||||
// first frame ever
|
||||
lastIntegerZoom = std::floor(zoom);
|
||||
lastZoom = zoom;
|
||||
}
|
||||
|
||||
// check whether an integer zoom level was passed since the last frame
|
||||
// and if yes, record it with the time. Used for transitioning patterns.
|
||||
if (std::floor(lastZoom) < std::floor(zoom)) {
|
||||
lastIntegerZoom = std::floor(zoom);
|
||||
lastIntegerZoomTime = time;
|
||||
|
||||
} else if (std::floor(lastZoom) > std::floor(zoom)) {
|
||||
lastIntegerZoom = std::floor(zoom) + 1;
|
||||
lastIntegerZoomTime = time;
|
||||
}
|
||||
|
||||
lastZoom = zoom;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,6 @@ private:
|
||||
mat4 translatedMatrix(const mat4& matrix, const std::array<float, 2> &translation, const Tile::ID &id, TranslateAnchorType anchor);
|
||||
|
||||
void prepareTile(const Tile& tile);
|
||||
void recordZoom(const std::chrono::steady_clock::time_point time, const float zoom);
|
||||
|
||||
template <typename BucketProperties, typename StyleProperties>
|
||||
void renderSDF(SymbolBucket &bucket,
|
||||
@@ -193,10 +192,6 @@ private:
|
||||
RenderPass pass = RenderPass::Opaque;
|
||||
const float strata_epsilon = 1.0f / (1 << 16);
|
||||
|
||||
int lastIntegerZoom;
|
||||
std::chrono::steady_clock::time_point lastIntegerZoomTime = std::chrono::steady_clock::time_point::min();
|
||||
float lastZoom = -1;
|
||||
|
||||
public:
|
||||
FrameHistory frameHistory;
|
||||
|
||||
|
||||
@@ -33,13 +33,13 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
stroke_color[3] *= properties.opacity;
|
||||
}
|
||||
|
||||
const bool pattern = properties.image.size();
|
||||
const bool pattern = properties.image.from.size();
|
||||
|
||||
bool outline = properties.antialias && !pattern && properties.stroke_color != properties.fill_color;
|
||||
bool fringeline = properties.antialias && !pattern && properties.stroke_color == properties.fill_color;
|
||||
|
||||
// Because we're drawing top-to-bottom, and we update the stencil mask
|
||||
// below, we have to draw the outline first (!)
|
||||
// befrom, we have to draw the outline first (!)
|
||||
if (outline && pass == RenderPass::Translucent) {
|
||||
useProgram(outlineShader->program);
|
||||
outlineShader->u_matrix = vtxMatrix;
|
||||
@@ -59,34 +59,32 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
if (pattern) {
|
||||
// Image fill.
|
||||
if (pass == RenderPass::Translucent) {
|
||||
const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, true);
|
||||
const SpriteAtlasPosition posA = spriteAtlas.getPosition(properties.image.from, true);
|
||||
const SpriteAtlasPosition posB = spriteAtlas.getPosition(properties.image.to, true);
|
||||
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
|
||||
|
||||
float mix;
|
||||
std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
|
||||
const float fraction = std::fmod(float(state.getZoom()), 1.0f);
|
||||
float t = std::min(static_cast<float>((std::chrono::steady_clock::now() - lastIntegerZoomTime) / duration), 1.0f);
|
||||
if (state.getZoom() > lastIntegerZoom) {
|
||||
// zooming in
|
||||
mix = fraction + (1.0f - fraction) * t;
|
||||
factor *= 2.0;
|
||||
} else {
|
||||
// zooming out
|
||||
mix = fraction - fraction * t;
|
||||
}
|
||||
|
||||
mat3 patternMatrix;
|
||||
matrix::identity(patternMatrix);
|
||||
matrix::scale(patternMatrix, patternMatrix, 1.0f / (pos.size[0] * factor), 1.0f / (pos.size[1] * factor));
|
||||
mat3 patternMatrixA;
|
||||
matrix::identity(patternMatrixA);
|
||||
matrix::scale(patternMatrixA, patternMatrixA,
|
||||
1.0f / (posA.size[0] * factor * properties.image.fromScale),
|
||||
1.0f / (posA.size[1] * factor * properties.image.fromScale));
|
||||
mat3 patternMatrixB;
|
||||
matrix::identity(patternMatrixB);
|
||||
matrix::scale(patternMatrixB, patternMatrixB,
|
||||
1.0f / (posB.size[0] * factor * properties.image.toScale),
|
||||
1.0f / (posB.size[1] * factor * properties.image.toScale));
|
||||
|
||||
useProgram(patternShader->program);
|
||||
patternShader->u_matrix = vtxMatrix;
|
||||
patternShader->u_pattern_tl = pos.tl;
|
||||
patternShader->u_pattern_br = pos.br;
|
||||
patternShader->u_pattern_tl_a = posA.tl;
|
||||
patternShader->u_pattern_br_a = posA.br;
|
||||
patternShader->u_pattern_tl_b = posB.tl;
|
||||
patternShader->u_pattern_br_b = posB.br;
|
||||
patternShader->u_opacity = properties.opacity;
|
||||
patternShader->u_image = 0;
|
||||
patternShader->u_mix = mix;
|
||||
patternShader->u_patternmatrix = patternMatrix;
|
||||
patternShader->u_mix = properties.image.t;
|
||||
patternShader->u_patternmatrix_a = patternMatrixA;
|
||||
patternShader->u_patternmatrix_b = patternMatrixB;
|
||||
|
||||
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
|
||||
spriteAtlas.bind(true);
|
||||
|
||||
@@ -70,11 +70,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
bucket.drawPoints(*linejoinShader);
|
||||
}
|
||||
|
||||
std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
|
||||
const float fraction = std::fmod(float(state.getZoom()), 1.0f);
|
||||
float t = std::min(static_cast<float>(std::chrono::duration<float>(std::chrono::steady_clock::now() - lastIntegerZoomTime) / duration), 1.0f);
|
||||
|
||||
if (properties.dash_array.size()) {
|
||||
if (properties.dash_array.from.size()) {
|
||||
|
||||
useProgram(linesdfShader->program);
|
||||
|
||||
@@ -85,46 +81,31 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
linesdfShader->u_blur = blur;
|
||||
linesdfShader->u_color = color;
|
||||
|
||||
LinePatternPos pos = lineAtlas.getDashPosition(properties.dash_array, bucket.properties.cap == CapType::Round);
|
||||
LinePatternPos posA = lineAtlas.getDashPosition(properties.dash_array.from, bucket.properties.cap == CapType::Round);
|
||||
LinePatternPos posB = lineAtlas.getDashPosition(properties.dash_array.to, bucket.properties.cap == CapType::Round);
|
||||
lineAtlas.bind();
|
||||
|
||||
float patternratio = std::pow(2.0, std::floor(std::log2(state.getScale())) - id.z) / 8.0;
|
||||
float scaleX = patternratio / pos.width / properties.dash_line_width;
|
||||
float scaleY = -pos.height / 2.0;
|
||||
float scaleXA = patternratio / posA.width / properties.dash_line_width / properties.dash_array.fromScale;
|
||||
float scaleYA = -posA.height / 2.0;
|
||||
float scaleXB = patternratio / posB.width / properties.dash_line_width / properties.dash_array.toScale;
|
||||
float scaleYB = -posB.height / 2.0;
|
||||
|
||||
float mix;
|
||||
if (state.getZoom() > lastIntegerZoom) {
|
||||
// zooming in
|
||||
mix = fraction + (1.0f - fraction) * t;
|
||||
scaleX /= 2.0;
|
||||
} else {
|
||||
// zooming out
|
||||
mix = fraction - fraction * t;
|
||||
}
|
||||
|
||||
linesdfShader->u_patternscale_a = {{ scaleX, scaleY }};
|
||||
linesdfShader->u_tex_y_a = pos.y;
|
||||
linesdfShader->u_patternscale_b = {{ scaleX * 2.0f, scaleY }};
|
||||
linesdfShader->u_tex_y_b = pos.y;
|
||||
linesdfShader->u_patternscale_a = {{ scaleXA, scaleYA }};
|
||||
linesdfShader->u_tex_y_a = posA.y;
|
||||
linesdfShader->u_patternscale_b = {{ scaleXB, scaleYB }};
|
||||
linesdfShader->u_tex_y_b = posB.y;
|
||||
linesdfShader->u_image = 0;
|
||||
linesdfShader->u_sdfgamma = lineAtlas.width / (properties.dash_line_width * pos.width * 256.0 * state.getPixelRatio()) / 2;
|
||||
linesdfShader->u_mix = mix;
|
||||
linesdfShader->u_sdfgamma = lineAtlas.width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * state.getPixelRatio()) / 2;
|
||||
linesdfShader->u_mix = properties.dash_array.t;
|
||||
|
||||
bucket.drawLineSDF(*linesdfShader);
|
||||
|
||||
} else if (properties.image.size()) {
|
||||
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
|
||||
} else if (properties.image.from.size()) {
|
||||
SpriteAtlasPosition imagePosA = spriteAtlas.getPosition(properties.image.from, true);
|
||||
SpriteAtlasPosition imagePosB = spriteAtlas.getPosition(properties.image.to, true);
|
||||
|
||||
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
|
||||
float fade;
|
||||
if (state.getZoom() > lastIntegerZoom) {
|
||||
// zooming in
|
||||
fade = fraction + (1.0f - fraction) * t;
|
||||
factor *= 2.0;
|
||||
} else {
|
||||
// zooming out
|
||||
fade = fraction - fraction * t;
|
||||
}
|
||||
|
||||
useProgram(linepatternShader->program);
|
||||
|
||||
@@ -134,10 +115,13 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
linepatternShader->u_ratio = ratio;
|
||||
linepatternShader->u_blur = blur;
|
||||
|
||||
linepatternShader->u_pattern_size = {{imagePos.size[0] * factor, imagePos.size[1]}};
|
||||
linepatternShader->u_pattern_tl = imagePos.tl;
|
||||
linepatternShader->u_pattern_br = imagePos.br;
|
||||
linepatternShader->u_fade = fade;
|
||||
linepatternShader->u_pattern_size_a = {{imagePosA.size[0] * factor * properties.image.fromScale, imagePosA.size[1]}};
|
||||
linepatternShader->u_pattern_tl_a = imagePosA.tl;
|
||||
linepatternShader->u_pattern_br_a = imagePosA.br;
|
||||
linepatternShader->u_pattern_size_b = {{imagePosB.size[0] * factor * properties.image.toScale, imagePosB.size[1]}};
|
||||
linepatternShader->u_pattern_tl_b = imagePosB.tl;
|
||||
linepatternShader->u_pattern_br_b = imagePosB.br;
|
||||
linepatternShader->u_fade = properties.image.t;
|
||||
linepatternShader->u_opacity = properties.opacity;
|
||||
|
||||
MBGL_CHECK_ERROR(glActiveTexture(GL_TEXTURE0));
|
||||
|
||||
@@ -2,9 +2,12 @@ uniform vec2 u_linewidth;
|
||||
uniform float u_point;
|
||||
uniform float u_blur;
|
||||
|
||||
uniform vec2 u_pattern_size;
|
||||
uniform vec2 u_pattern_tl;
|
||||
uniform vec2 u_pattern_br;
|
||||
uniform vec2 u_pattern_size_a;
|
||||
uniform vec2 u_pattern_tl_a;
|
||||
uniform vec2 u_pattern_br_a;
|
||||
uniform vec2 u_pattern_size_b;
|
||||
uniform vec2 u_pattern_tl_b;
|
||||
uniform vec2 u_pattern_br_b;
|
||||
uniform float u_fade;
|
||||
uniform float u_opacity;
|
||||
|
||||
@@ -24,13 +27,14 @@ void main() {
|
||||
// (v_linewidth.s)
|
||||
float alpha = clamp(min(dist - (u_linewidth.t - u_blur), u_linewidth.s - dist) / u_blur, 0.0, 1.0);
|
||||
|
||||
float x = mod(v_linesofar / u_pattern_size.x, 1.0);
|
||||
float y = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size.y);
|
||||
vec2 pos = mix(u_pattern_tl, u_pattern_br, vec2(x, y));
|
||||
float x2 = mod(x * 2.0, 1.0);
|
||||
vec2 pos2 = mix(u_pattern_tl, u_pattern_br, vec2(x2, y));
|
||||
float x_a = mod(v_linesofar / u_pattern_size_a.x, 1.0);
|
||||
float y_a = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size_a.y);
|
||||
vec2 pos_a = mix(u_pattern_tl_a, u_pattern_br_a, vec2(x_a, y_a));
|
||||
float x_b = mod(v_linesofar / u_pattern_size_b.x, 1.0);
|
||||
float y_b = 0.5 + (v_normal.y * u_linewidth.s / u_pattern_size_b.y);
|
||||
vec2 pos_b = mix(u_pattern_tl_b, u_pattern_br_b, vec2(x_b, y_b));
|
||||
|
||||
vec4 color = texture2D(u_image, pos) * (1.0 - u_fade) + u_fade * texture2D(u_image, pos2);
|
||||
vec4 color = mix(texture2D(u_image, pos_a), texture2D(u_image, pos_b), u_fade);
|
||||
|
||||
alpha *= u_opacity;
|
||||
|
||||
|
||||
@@ -15,9 +15,12 @@ public:
|
||||
UniformMatrix<4> u_matrix = {"u_matrix", *this};
|
||||
UniformMatrix<4> u_exmatrix = {"u_exmatrix", *this};
|
||||
Uniform<std::array<float, 2>> u_linewidth = {"u_linewidth", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_size = {"u_pattern_size", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_tl = {"u_pattern_tl", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_br = {"u_pattern_br", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_size_a = {"u_pattern_size_a", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_size_b = {"u_pattern_size_b", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
|
||||
Uniform<float> u_ratio = {"u_ratio", *this};
|
||||
Uniform<float> u_point = {"u_point", *this};
|
||||
Uniform<float> u_blur = {"u_blur", *this};
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
uniform float u_opacity;
|
||||
uniform vec2 u_pattern_tl;
|
||||
uniform vec2 u_pattern_br;
|
||||
uniform vec2 u_pattern_tl_a;
|
||||
uniform vec2 u_pattern_br_a;
|
||||
uniform vec2 u_pattern_tl_b;
|
||||
uniform vec2 u_pattern_br_b;
|
||||
uniform float u_mix;
|
||||
|
||||
uniform sampler2D u_image;
|
||||
|
||||
varying vec2 v_pos;
|
||||
varying vec2 v_pos_a;
|
||||
varying vec2 v_pos_b;
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 imagecoord = mod(v_pos, 1.0);
|
||||
vec2 pos = mix(u_pattern_tl, u_pattern_br, imagecoord);
|
||||
vec2 imagecoord = mod(v_pos_a, 1.0);
|
||||
vec2 pos = mix(u_pattern_tl_a, u_pattern_br_a, imagecoord);
|
||||
vec4 color1 = texture2D(u_image, pos);
|
||||
|
||||
vec2 imagecoord2 = mod(imagecoord * 2.0, 1.0);
|
||||
vec2 pos2 = mix(u_pattern_tl, u_pattern_br, imagecoord2);
|
||||
vec2 imagecoord_b = mod(v_pos_b, 1.0);
|
||||
vec2 pos2 = mix(u_pattern_tl_b, u_pattern_br_b, imagecoord_b);
|
||||
vec4 color2 = texture2D(u_image, pos2);
|
||||
|
||||
gl_FragColor = mix(color1, color2, u_mix) * u_opacity;
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
uniform mat4 u_matrix;
|
||||
uniform mat3 u_patternmatrix;
|
||||
uniform mat3 u_patternmatrix_a;
|
||||
uniform mat3 u_patternmatrix_b;
|
||||
|
||||
attribute vec2 a_pos;
|
||||
|
||||
varying vec2 v_pos;
|
||||
varying vec2 v_pos_a;
|
||||
varying vec2 v_pos_b;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
v_pos = (u_patternmatrix * vec3(a_pos, 1)).xy;
|
||||
v_pos_a = (u_patternmatrix_a * vec3(a_pos, 1)).xy;
|
||||
v_pos_b = (u_patternmatrix_b * vec3(a_pos, 1)).xy;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,15 @@ public:
|
||||
void bind(char *offset);
|
||||
|
||||
UniformMatrix<4> u_matrix = {"u_matrix", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_tl = {"u_pattern_tl", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_br = {"u_pattern_br", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
|
||||
Uniform<std::array<float, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
|
||||
Uniform<float> u_opacity = {"u_opacity", *this};
|
||||
Uniform<float> u_mix = {"u_mix", *this};
|
||||
Uniform<int32_t> u_image = {"u_image", *this};
|
||||
UniformMatrix<3> u_patternmatrix = {"u_patternmatrix", *this};
|
||||
UniformMatrix<3> u_patternmatrix_a = {"u_patternmatrix_a", *this};
|
||||
UniformMatrix<3> u_patternmatrix_b = {"u_patternmatrix_b", *this};
|
||||
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
|
||||
@@ -13,7 +13,18 @@ template <> inline bool defaultStopsValue() { return true; }
|
||||
template <> inline float defaultStopsValue() { return 1.0f; }
|
||||
template <> inline Color defaultStopsValue() { return {{ 0, 0, 0, 1 }}; }
|
||||
template <> inline std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
|
||||
template <> inline std::array<float, 2> defaultStopsValue() { return {{ 0, 0 }}; }
|
||||
|
||||
template <> inline std:: string defaultStopsValue() { return {}; }
|
||||
template <> inline TranslateAnchorType defaultStopsValue() { return {}; };
|
||||
template <> inline RotateAnchorType defaultStopsValue() { return {}; };
|
||||
template <> inline CapType defaultStopsValue() { return {}; };
|
||||
template <> inline JoinType defaultStopsValue() { return {}; };
|
||||
template <> inline PlacementType defaultStopsValue() { return {}; };
|
||||
template <> inline TextAnchorType defaultStopsValue() { return {}; };
|
||||
template <> inline TextJustifyType defaultStopsValue() { return {}; };
|
||||
template <> inline TextTransformType defaultStopsValue() { return {}; };
|
||||
template <> inline RotationAlignmentType defaultStopsValue() { return {}; };
|
||||
|
||||
template <typename T>
|
||||
T StopsFunction<T>::evaluate(float z) const {
|
||||
@@ -66,5 +77,16 @@ template bool StopsFunction<bool>::evaluate(float z) const;
|
||||
template float StopsFunction<float>::evaluate(float z) const;
|
||||
template Color StopsFunction<Color>::evaluate(float z) const;
|
||||
template std::vector<float> StopsFunction<std::vector<float>>::evaluate(float z) const;
|
||||
template std::array<float, 2> StopsFunction<std::array<float, 2>>::evaluate(float z) const;
|
||||
|
||||
template std::string StopsFunction<std::string>::evaluate(float z) const;
|
||||
template TranslateAnchorType StopsFunction<TranslateAnchorType>::evaluate(float z) const;
|
||||
template RotateAnchorType StopsFunction<RotateAnchorType>::evaluate(float z) const;
|
||||
template CapType StopsFunction<CapType>::evaluate(float z) const;
|
||||
template JoinType StopsFunction<JoinType>::evaluate(float z) const;
|
||||
template PlacementType StopsFunction<PlacementType>::evaluate(float z) const;
|
||||
template TextAnchorType StopsFunction<TextAnchorType>::evaluate(float z) const;
|
||||
template TextJustifyType StopsFunction<TextJustifyType>::evaluate(float z) const;
|
||||
template TextTransformType StopsFunction<TextTransformType>::evaluate(float z) const;
|
||||
template RotationAlignmentType StopsFunction<RotationAlignmentType>::evaluate(float z) const;
|
||||
}
|
||||
|
||||
52
src/mbgl/style/piecewisefunction_properties.cpp
Normal file
52
src/mbgl/style/piecewisefunction_properties.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <mbgl/style/piecewisefunction_properties.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <typename T>
|
||||
size_t getBiggestStopLessThan(std::vector<std::pair<float, T>> stops, float z) {
|
||||
for (uint32_t i = 0; i < stops.size(); i++) {
|
||||
if (stops[i].first > z) {
|
||||
return i == 0 ? i : i - 1;
|
||||
}
|
||||
}
|
||||
return stops.size() - 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T PiecewiseConstantFunction<T>::evaluate(float z, const ZoomHistory &zh) const {
|
||||
T result;
|
||||
|
||||
float fraction = std::fmod(z, 1.0f);
|
||||
float t = std::min((std::chrono::steady_clock::now() - zh.lastIntegerZoomTime) / duration, 1.0f);
|
||||
float fromScale = 1.0f;
|
||||
float toScale = 1.0f;
|
||||
size_t from, to;
|
||||
|
||||
if (z > zh.lastIntegerZoom) {
|
||||
result.t = fraction + (1.0f - fraction) * t;
|
||||
from = getBiggestStopLessThan(values, z - 1.0f);
|
||||
to = getBiggestStopLessThan(values, z);
|
||||
fromScale *= 2.0f;
|
||||
|
||||
} else {
|
||||
result.t = 1 - (1 - t) * fraction;
|
||||
to = getBiggestStopLessThan(values, z);
|
||||
from = getBiggestStopLessThan(values, z + 1.0f);
|
||||
fromScale /= 2.0f;
|
||||
}
|
||||
|
||||
|
||||
result.from = values[from].second.to;
|
||||
result.to = values[to].second.to;
|
||||
result.fromScale = fromScale;
|
||||
result.toScale = toScale;
|
||||
return result;
|
||||
}
|
||||
|
||||
template Faded<std::string> PiecewiseConstantFunction<Faded<std::string>>::evaluate(float z, const ZoomHistory &zoomHistory) const;
|
||||
template Faded<std::vector<float>> PiecewiseConstantFunction<Faded<std::vector<float>>>::evaluate(float z, const ZoomHistory &zoomHistory) const;
|
||||
|
||||
}
|
||||
24
src/mbgl/style/piecewisefunction_properties.hpp
Normal file
24
src/mbgl/style/piecewisefunction_properties.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef MBGL_STYLE_FADEDFUNCTION_PROPERTIES
|
||||
#define MBGL_STYLE_FADEDFUNCTION_PROPERTIES
|
||||
|
||||
#include <mbgl/style/zoom_history.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
template <typename T>
|
||||
struct PiecewiseConstantFunction {
|
||||
inline PiecewiseConstantFunction(const std::vector<std::pair<float, T>> &values_, std::chrono::duration<float> duration_) : values(values_), duration(duration_) {}
|
||||
inline PiecewiseConstantFunction(T &value, std::chrono::duration<float> duration_) : values({{ 0, value }}), duration(duration_) {}
|
||||
inline PiecewiseConstantFunction() : values(), duration(std::chrono::milliseconds(300)) {}
|
||||
T evaluate(float z, const ZoomHistory &zoomHistory) const;
|
||||
|
||||
private:
|
||||
const std::vector<std::pair<float, T>> values;
|
||||
const std::chrono::duration<float> duration;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,14 +9,12 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::FillOpacity, defaultStyleProperties<FillProperties>().opacity },
|
||||
{ PropertyKey::FillColor, defaultStyleProperties<FillProperties>().fill_color },
|
||||
// no FillOutlineColor on purpose.
|
||||
{ PropertyKey::FillTranslateX, defaultStyleProperties<FillProperties>().translate[0] },
|
||||
{ PropertyKey::FillTranslateY, defaultStyleProperties<FillProperties>().translate[1] },
|
||||
{ PropertyKey::FillTranslate, defaultStyleProperties<FillProperties>().translate },
|
||||
{ PropertyKey::FillTranslateAnchor, defaultStyleProperties<FillProperties>().translateAnchor },
|
||||
|
||||
{ PropertyKey::LineOpacity, defaultStyleProperties<LineProperties>().opacity },
|
||||
{ PropertyKey::LineColor, defaultStyleProperties<LineProperties>().color },
|
||||
{ PropertyKey::LineTranslateX, defaultStyleProperties<LineProperties>().translate[0] },
|
||||
{ PropertyKey::LineTranslateY, defaultStyleProperties<LineProperties>().translate[1] },
|
||||
{ PropertyKey::LineTranslate, defaultStyleProperties<LineProperties>().translate },
|
||||
{ PropertyKey::LineTranslateAnchor, defaultStyleProperties<LineProperties>().translateAnchor },
|
||||
{ PropertyKey::LineWidth, defaultStyleProperties<LineProperties>().width },
|
||||
{ PropertyKey::LineGapWidth, defaultStyleProperties<LineProperties>().gap_width },
|
||||
@@ -29,8 +27,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::IconHaloColor, defaultStyleProperties<SymbolProperties>().icon.halo_color },
|
||||
{ PropertyKey::IconHaloWidth, defaultStyleProperties<SymbolProperties>().icon.halo_width },
|
||||
{ PropertyKey::IconHaloBlur, defaultStyleProperties<SymbolProperties>().icon.halo_blur },
|
||||
{ PropertyKey::IconTranslateX, defaultStyleProperties<SymbolProperties>().icon.translate[0] },
|
||||
{ PropertyKey::IconTranslateY, defaultStyleProperties<SymbolProperties>().icon.translate[1] },
|
||||
{ PropertyKey::IconTranslate, defaultStyleProperties<SymbolProperties>().icon.translate },
|
||||
{ PropertyKey::IconTranslateAnchor, defaultStyleProperties<SymbolProperties>().icon.translate_anchor },
|
||||
|
||||
{ PropertyKey::TextOpacity, defaultStyleProperties<SymbolProperties>().text.opacity },
|
||||
@@ -39,8 +36,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::TextHaloColor, defaultStyleProperties<SymbolProperties>().text.halo_color },
|
||||
{ PropertyKey::TextHaloWidth, defaultStyleProperties<SymbolProperties>().text.halo_width },
|
||||
{ PropertyKey::TextHaloBlur, defaultStyleProperties<SymbolProperties>().text.halo_blur },
|
||||
{ PropertyKey::TextTranslateX, defaultStyleProperties<SymbolProperties>().text.translate[0] },
|
||||
{ PropertyKey::TextTranslateY, defaultStyleProperties<SymbolProperties>().text.translate[1] },
|
||||
{ PropertyKey::TextTranslate, defaultStyleProperties<SymbolProperties>().text.translate },
|
||||
{ PropertyKey::TextTranslateAnchor, defaultStyleProperties<SymbolProperties>().text.translate_anchor },
|
||||
|
||||
{ PropertyKey::RasterOpacity, defaultStyleProperties<RasterProperties>().opacity },
|
||||
@@ -72,8 +68,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::IconRotate, defaultLayoutProperties<StyleBucketSymbol>().icon.rotate },
|
||||
{ PropertyKey::IconPadding, defaultLayoutProperties<StyleBucketSymbol>().icon.padding },
|
||||
{ PropertyKey::IconKeepUpright, defaultLayoutProperties<StyleBucketSymbol>().icon.keep_upright },
|
||||
{ PropertyKey::IconOffsetX, defaultLayoutProperties<StyleBucketSymbol>().icon.offset[0] },
|
||||
{ PropertyKey::IconOffsetY, defaultLayoutProperties<StyleBucketSymbol>().icon.offset[1] },
|
||||
{ PropertyKey::IconOffset, defaultLayoutProperties<StyleBucketSymbol>().icon.offset },
|
||||
|
||||
{ PropertyKey::TextRotationAlignment, defaultLayoutProperties<StyleBucketSymbol>().text.rotation_alignment },
|
||||
{ PropertyKey::TextField, defaultLayoutProperties<StyleBucketSymbol>().text.field },
|
||||
@@ -89,8 +84,7 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::TextPadding, defaultLayoutProperties<StyleBucketSymbol>().text.padding },
|
||||
{ PropertyKey::TextKeepUpright, defaultLayoutProperties<StyleBucketSymbol>().text.keep_upright },
|
||||
{ PropertyKey::TextTransform, defaultLayoutProperties<StyleBucketSymbol>().text.transform },
|
||||
{ PropertyKey::TextOffsetX, defaultLayoutProperties<StyleBucketSymbol>().text.offset[0] },
|
||||
{ PropertyKey::TextOffsetY, defaultLayoutProperties<StyleBucketSymbol>().text.offset[1] },
|
||||
{ PropertyKey::TextOffset, defaultLayoutProperties<StyleBucketSymbol>().text.offset },
|
||||
{ PropertyKey::TextAllowOverlap, defaultLayoutProperties<StyleBucketSymbol>().text.allow_overlap },
|
||||
{ PropertyKey::TextIgnorePlacement, defaultLayoutProperties<StyleBucketSymbol>().text.ignore_placement },
|
||||
{ PropertyKey::TextOptional, defaultLayoutProperties<StyleBucketSymbol>().text.optional },
|
||||
|
||||
@@ -9,16 +9,12 @@ enum class PropertyKey {
|
||||
FillColor,
|
||||
FillOutlineColor,
|
||||
FillTranslate, // for transitions only
|
||||
FillTranslateX,
|
||||
FillTranslateY,
|
||||
FillTranslateAnchor,
|
||||
FillImage,
|
||||
|
||||
LineOpacity,
|
||||
LineColor,
|
||||
LineTranslate, // for transitions only
|
||||
LineTranslateX,
|
||||
LineTranslateY,
|
||||
LineTranslateAnchor,
|
||||
LineWidth,
|
||||
LineGapWidth,
|
||||
@@ -41,9 +37,7 @@ enum class PropertyKey {
|
||||
IconHaloColor,
|
||||
IconHaloWidth,
|
||||
IconHaloBlur,
|
||||
IconTranslate, // for transitions only
|
||||
IconTranslateX,
|
||||
IconTranslateY,
|
||||
IconTranslate,
|
||||
IconTranslateAnchor,
|
||||
|
||||
IconAllowOverlap,
|
||||
@@ -52,11 +46,10 @@ enum class PropertyKey {
|
||||
IconRotationAlignment,
|
||||
IconMaxSize,
|
||||
IconImage,
|
||||
IconOffset,
|
||||
IconPadding,
|
||||
IconRotate,
|
||||
IconKeepUpright,
|
||||
IconOffsetX,
|
||||
IconOffsetY,
|
||||
|
||||
TextOpacity,
|
||||
TextSize,
|
||||
@@ -64,9 +57,7 @@ enum class PropertyKey {
|
||||
TextHaloColor,
|
||||
TextHaloWidth,
|
||||
TextHaloBlur,
|
||||
TextTranslate, // for transitions only
|
||||
TextTranslateX,
|
||||
TextTranslateY,
|
||||
TextTranslate,
|
||||
TextTranslateAnchor,
|
||||
|
||||
TextRotationAlignment,
|
||||
@@ -85,8 +76,7 @@ enum class PropertyKey {
|
||||
TextAnchor,
|
||||
TextKeepUpright,
|
||||
TextTransform,
|
||||
TextOffsetX,
|
||||
TextOffsetY,
|
||||
TextOffset,
|
||||
TextAllowOverlap,
|
||||
|
||||
RasterOpacity,
|
||||
|
||||
@@ -3,29 +3,32 @@
|
||||
|
||||
#include <mbgl/util/variant.hpp>
|
||||
#include <mbgl/style/function_properties.hpp>
|
||||
#include <mbgl/style/piecewisefunction_properties.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
typedef mapbox::util::variant<
|
||||
std::string,
|
||||
TranslateAnchorType,
|
||||
RotateAnchorType,
|
||||
bool,
|
||||
CapType,
|
||||
JoinType,
|
||||
Function<std::string>,
|
||||
Function<TranslateAnchorType>,
|
||||
Function<RotateAnchorType>,
|
||||
Function<CapType>,
|
||||
Function<JoinType>,
|
||||
VisibilityType,
|
||||
PlacementType,
|
||||
RotationAlignmentType,
|
||||
TextTransformType,
|
||||
TextJustifyType,
|
||||
TextAnchorType,
|
||||
Function<PlacementType>,
|
||||
Function<RotationAlignmentType>,
|
||||
Function<TextTransformType>,
|
||||
Function<TextJustifyType>,
|
||||
Function<TextAnchorType>,
|
||||
Function<std::array<float, 2>>,
|
||||
Function<bool>,
|
||||
Function<float>,
|
||||
Function<Color>,
|
||||
Function<std::vector<float>>
|
||||
PiecewiseConstantFunction<Faded<std::vector<float>>>,
|
||||
PiecewiseConstantFunction<Faded<std::string>>
|
||||
> PropertyValue;
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,10 @@ Style::~Style() {}
|
||||
void Style::updateProperties(float z, std::chrono::steady_clock::time_point now) {
|
||||
uv::writelock lock(mtx);
|
||||
|
||||
zoomHistory.update(z, now);
|
||||
|
||||
if (layers) {
|
||||
layers->updateProperties(z, now);
|
||||
layers->updateProperties(z, now, zoomHistory);
|
||||
}
|
||||
|
||||
// Apply transitions after the first time.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/style/property_transition.hpp>
|
||||
#include <mbgl/style/style_source.hpp>
|
||||
#include <mbgl/style/zoom_history.hpp>
|
||||
|
||||
#include <mbgl/util/uv.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
@@ -50,6 +51,7 @@ private:
|
||||
PropertyTransition defaultTransition;
|
||||
bool initial_render_complete = false;
|
||||
std::unique_ptr<uv::rwlock> mtx;
|
||||
ZoomHistory zoomHistory;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ void StyleLayer::applyClassProperties(const ClassID class_id,
|
||||
template <typename T>
|
||||
struct PropertyEvaluator {
|
||||
typedef T result_type;
|
||||
PropertyEvaluator(float z_) : z(z_) {}
|
||||
PropertyEvaluator(float z_, const ZoomHistory &zoomHistory_) : z(z_), zoomHistory(zoomHistory_) {}
|
||||
|
||||
template <typename P, typename std::enable_if<std::is_convertible<P, T>::value, int>::type = 0>
|
||||
T operator()(const P &value) const {
|
||||
@@ -105,6 +105,10 @@ struct PropertyEvaluator {
|
||||
return mapbox::util::apply_visitor(FunctionEvaluator<T>(z), value);
|
||||
}
|
||||
|
||||
T operator()(const PiecewiseConstantFunction<T> &value) const {
|
||||
return value.evaluate(z, zoomHistory);
|
||||
}
|
||||
|
||||
template <typename P, typename std::enable_if<!std::is_convertible<P, T>::value, int>::type = 0>
|
||||
T operator()(const P &) const {
|
||||
return T();
|
||||
@@ -112,15 +116,16 @@ struct PropertyEvaluator {
|
||||
|
||||
private:
|
||||
const float z;
|
||||
const ZoomHistory &zoomHistory;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
|
||||
auto it = appliedStyle.find(key);
|
||||
if (it != appliedStyle.end()) {
|
||||
AppliedClassProperties &applied = it->second;
|
||||
// Iterate through all properties that we need to apply in order.
|
||||
const PropertyEvaluator<T> evaluator(z);
|
||||
const PropertyEvaluator<T> evaluator(z, zoomHistory);
|
||||
for (AppliedClassProperty &property : applied.properties) {
|
||||
if (now >= property.begin) {
|
||||
// We overwrite the current property with the new value.
|
||||
@@ -133,12 +138,12 @@ void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, c
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
|
||||
auto it = appliedStyle.find(key);
|
||||
if (it != appliedStyle.end()) {
|
||||
AppliedClassProperties &applied = it->second;
|
||||
// Iterate through all properties that we need to apply in order.
|
||||
const PropertyEvaluator<T> evaluator(z);
|
||||
const PropertyEvaluator<T> evaluator(z, zoomHistory);
|
||||
for (AppliedClassProperty &property : applied.properties) {
|
||||
if (now >= property.end) {
|
||||
// We overwrite the current property with the new value.
|
||||
@@ -155,95 +160,91 @@ void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, cons
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<FillProperties>(const float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::applyStyleProperties<FillProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
|
||||
properties.set<FillProperties>();
|
||||
FillProperties &fill = properties.get<FillProperties>();
|
||||
applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillOutlineColor, fill.stroke_color, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillTranslateX, fill.translate[0], z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillTranslateY, fill.translate[1], z, now);
|
||||
applyStyleProperty(PropertyKey::FillTranslateAnchor, fill.translateAnchor, z, now);
|
||||
applyStyleProperty(PropertyKey::FillImage, fill.image, z, now);
|
||||
applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillOutlineColor, fill.stroke_color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::FillTranslate, fill.translate, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::FillTranslateAnchor, fill.translateAnchor, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::FillImage, fill.image, z, now, zoomHistory);
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<LineProperties>(const float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::applyStyleProperties<LineProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
|
||||
properties.set<LineProperties>();
|
||||
LineProperties &line = properties.get<LineProperties>();
|
||||
applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineColor, line.color, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineTranslateX, line.translate[0], z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineTranslateY, line.translate[1], z, now);
|
||||
applyStyleProperty(PropertyKey::LineTranslateAnchor, line.translateAnchor, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now);
|
||||
applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now);
|
||||
applyStyleProperty(PropertyKey::LineImage, line.image, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineColor, line.color, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineTranslate, line.translate, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::LineTranslateAnchor, line.translateAnchor, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineWidth, line.width, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineGapWidth, line.gap_width, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::LineBlur, line.blur, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::LineDashArray, line.dash_array, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::LineImage, line.image, z, now, zoomHistory);
|
||||
|
||||
// for scaling dasharrays
|
||||
applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), std::chrono::steady_clock::time_point::max());
|
||||
applyStyleProperty(PropertyKey::LineWidth, line.dash_line_width, std::floor(z), std::chrono::steady_clock::time_point::max(), zoomHistory);
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::applyStyleProperties<SymbolProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
|
||||
properties.set<SymbolProperties>();
|
||||
SymbolProperties &symbol = properties.get<SymbolProperties>();
|
||||
applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconRotate, symbol.icon.rotate, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconSize, symbol.icon.size, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconColor, symbol.icon.color, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconHaloColor, symbol.icon.halo_color, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconHaloWidth, symbol.icon.halo_width, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconHaloBlur, symbol.icon.halo_blur, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconTranslateX, symbol.icon.translate[0], z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconTranslateY, symbol.icon.translate[1], z, now);
|
||||
applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconOpacity, symbol.icon.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconRotate, symbol.icon.rotate, 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);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconHaloBlur, symbol.icon.halo_blur, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::IconTranslate, symbol.icon.translate, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::IconTranslateAnchor, symbol.icon.translate_anchor, z, now, zoomHistory);
|
||||
|
||||
applyTransitionedStyleProperty(PropertyKey::TextOpacity, symbol.text.opacity, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextSize, symbol.text.size, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextColor, symbol.text.color, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextHaloColor, symbol.text.halo_color, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextHaloWidth, symbol.text.halo_width, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextHaloBlur, symbol.text.halo_blur, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextTranslateX, symbol.text.translate[0], z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::TextTranslateY, symbol.text.translate[1], z, now);
|
||||
applyStyleProperty(PropertyKey::TextTranslateAnchor, symbol.text.translate_anchor, z, now);
|
||||
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);
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
|
||||
properties.set<RasterProperties>();
|
||||
RasterProperties &raster = properties.get<RasterProperties>();
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterHueRotate, raster.hue_rotate, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterBrightnessHigh, raster.brightness[1], z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterSaturation, raster.saturation, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterContrast, raster.contrast, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterFade, raster.fade, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterHueRotate, raster.hue_rotate, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterBrightnessHigh, raster.brightness[1], z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterSaturation, raster.saturation, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterContrast, raster.contrast, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::RasterFade, raster.fade, z, now, zoomHistory);
|
||||
}
|
||||
|
||||
template <>
|
||||
void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::applyStyleProperties<BackgroundProperties>(const float z, const std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory) {
|
||||
properties.set<BackgroundProperties>();
|
||||
BackgroundProperties &background = properties.get<BackgroundProperties>();
|
||||
applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::BackgroundColor, background.color, z, now);
|
||||
applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now);
|
||||
applyTransitionedStyleProperty(PropertyKey::BackgroundOpacity, background.opacity, z, now, zoomHistory);
|
||||
applyTransitionedStyleProperty(PropertyKey::BackgroundColor, background.color, z, now, zoomHistory);
|
||||
applyStyleProperty(PropertyKey::BackgroundImage, background.image, z, now, zoomHistory);
|
||||
}
|
||||
|
||||
void StyleLayer::updateProperties(float z, const std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayer::updateProperties(float z, const std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory) {
|
||||
cleanupAppliedStyleProperties(now);
|
||||
|
||||
switch (type) {
|
||||
case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now); break;
|
||||
case StyleLayerType::Line: applyStyleProperties<LineProperties>(z, now); break;
|
||||
case StyleLayerType::Symbol: applyStyleProperties<SymbolProperties>(z, now); break;
|
||||
case StyleLayerType::Raster: applyStyleProperties<RasterProperties>(z, now); break;
|
||||
case StyleLayerType::Background: applyStyleProperties<BackgroundProperties>(z, now); break;
|
||||
case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now, zoomHistory); break;
|
||||
case StyleLayerType::Line: applyStyleProperties<LineProperties>(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;
|
||||
default: properties.set<std::false_type>(); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/style/class_properties.hpp>
|
||||
#include <mbgl/style/style_properties.hpp>
|
||||
#include <mbgl/style/applied_class_properties.hpp>
|
||||
#include <mbgl/style/zoom_history.hpp>
|
||||
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
|
||||
@@ -36,7 +37,7 @@ public:
|
||||
|
||||
// Updates the StyleProperties information in this layer by evaluating all
|
||||
// pending transitions and applied classes in order.
|
||||
void updateProperties(float z, std::chrono::steady_clock::time_point now);
|
||||
void updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory);
|
||||
|
||||
// Sets the list of classes and creates transitions to the currently applied values.
|
||||
void setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
|
||||
@@ -51,9 +52,9 @@ private:
|
||||
|
||||
// Sets the properties of this object by evaluating all pending transitions and
|
||||
// aplied classes in order.
|
||||
template <typename T> void applyStyleProperties(float z, std::chrono::steady_clock::time_point now);
|
||||
template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now);
|
||||
template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now);
|
||||
template <typename T> void applyStyleProperties(float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
|
||||
template <typename T> void applyStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
|
||||
template <typename T> void applyTransitionedStyleProperty(PropertyKey key, T &, float z, std::chrono::steady_clock::time_point now, const ZoomHistory &zoomHistory);
|
||||
|
||||
// Removes all expired style transitions.
|
||||
void cleanupAppliedStyleProperties(std::chrono::steady_clock::time_point now);
|
||||
|
||||
@@ -11,10 +11,10 @@ void StyleLayerGroup::setClasses(const std::vector<std::string> &class_names, st
|
||||
}
|
||||
}
|
||||
|
||||
void StyleLayerGroup::updateProperties(float z, std::chrono::steady_clock::time_point now) {
|
||||
void StyleLayerGroup::updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory) {
|
||||
for (const util::ptr<StyleLayer> &layer: layers) {
|
||||
if (layer) {
|
||||
layer->updateProperties(z, now);
|
||||
layer->updateProperties(z, now, zoomHistory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class StyleLayerGroup {
|
||||
public:
|
||||
void setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
|
||||
const PropertyTransition &defaultTransition);
|
||||
void updateProperties(float z, std::chrono::steady_clock::time_point now);
|
||||
void updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory);
|
||||
|
||||
bool hasTransitions() const;
|
||||
public:
|
||||
|
||||
@@ -209,7 +209,7 @@ Color parseColor(JSVal value) {
|
||||
css_color.a}};
|
||||
}
|
||||
|
||||
std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) {
|
||||
std::tuple<bool,std::vector<float>> StyleParser::parseFloatArray(JSVal value) {
|
||||
if (!value.IsArray()) {
|
||||
Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
|
||||
return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
|
||||
@@ -217,7 +217,7 @@ std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) {
|
||||
|
||||
std::vector<float> vec;
|
||||
for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
|
||||
JSVal part = value[i];
|
||||
JSVal part = replaceConstant(value[i]);
|
||||
if (!part.IsNumber()) {
|
||||
Log::Warning(Event::ParseStyle, "dasharray value must be an array of numbers");
|
||||
return std::tuple<bool, std::vector<float>> { false, std::vector<float>() };
|
||||
@@ -228,46 +228,101 @@ std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value) {
|
||||
}
|
||||
|
||||
template <>
|
||||
bool StyleParser::parseFunctionArgument(JSVal value) {
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
if (rvalue.IsBool()) {
|
||||
return rvalue.GetBool();
|
||||
} else if (rvalue.IsNumber()) {
|
||||
return rvalue.GetDouble();
|
||||
std::tuple<bool, std::array<float, 2>> StyleParser::parseProperty(JSVal value, const char*) {
|
||||
if (value.IsArray() && value.Size() == 2 &&
|
||||
value[rapidjson::SizeType(0)].IsNumber() &&
|
||||
value[rapidjson::SizeType(1)].IsNumber()) {
|
||||
|
||||
float first = value[rapidjson::SizeType(0)].GetDouble();
|
||||
float second = value[rapidjson::SizeType(1)].GetDouble();
|
||||
return std::tuple<bool, std::array<float, 2>> { false, {{ first, second }} };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "function argument must be a boolean or numeric value");
|
||||
return false;
|
||||
Log::Warning(Event::ParseStyle, "value must be array of two numbers");
|
||||
return std::tuple<bool, std::array<float, 2>> { false, {{ 0.0f, 0.0f }} };
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
float StyleParser::parseFunctionArgument(JSVal value) {
|
||||
std::tuple<bool, float> StyleParser::parseProperty(JSVal value, const char* property_name) {
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
if (rvalue.IsNumber()) {
|
||||
return rvalue.GetDouble();
|
||||
return std::tuple<bool, float> { true, rvalue.GetDouble() };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
|
||||
return 0.0f;
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", property_name);
|
||||
return std::tuple<bool, float> { false, 0.0f };
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
Color StyleParser::parseFunctionArgument(JSVal value) {
|
||||
std::tuple<bool, Color> StyleParser::parseProperty(JSVal value, const char*) {
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
return parseColor(rvalue);
|
||||
return std::tuple<bool, Color> { true, parseColor(rvalue) };
|
||||
}
|
||||
|
||||
template <>
|
||||
std::vector<float> StyleParser::parseFunctionArgument(JSVal value) {
|
||||
std::tuple<bool, Faded<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char*) {
|
||||
Faded<std::vector<float>> parsed;
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
return std::get<1>(parseFloatArray(rvalue));
|
||||
parsed.to = std::get<1>(parseFloatArray(rvalue));
|
||||
return std::tuple<bool, Faded<std::vector<float>>> { true, parsed };
|
||||
}
|
||||
|
||||
template <>
|
||||
std::tuple<bool, Faded<std::string>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
JSVal rvalue = replaceConstant(value);
|
||||
Faded<std::string> parsed;
|
||||
if (rvalue.IsString()) {
|
||||
parsed.to = { value.GetString(), value.GetStringLength() };
|
||||
return std::tuple<bool, Faded<std::string>> { true, parsed };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be a string, or a string function", property_name);
|
||||
return std::tuple<bool, Faded<std::string>> { false, parsed };
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::tuple<bool, std::vector<std::pair<float, T>>> StyleParser::parseStops(JSVal value_stops, const char *property_name) {
|
||||
|
||||
if (!value_stops.IsArray()) {
|
||||
Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
|
||||
return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
|
||||
}
|
||||
|
||||
std::vector<std::pair<float, T>> stops;
|
||||
|
||||
for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
|
||||
JSVal stop = value_stops[i];
|
||||
if (stop.IsArray()) {
|
||||
if (stop.Size() != 2) {
|
||||
Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
|
||||
return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
|
||||
}
|
||||
|
||||
JSVal z = stop[rapidjson::SizeType(0)];
|
||||
if (!z.IsNumber()) {
|
||||
Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
|
||||
return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
|
||||
}
|
||||
|
||||
stops.emplace_back(z.GetDouble(), std::get<1>(parseProperty<T>(replaceConstant(stop[rapidjson::SizeType(1)]), property_name)));
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
|
||||
return std::tuple<bool, std::vector<std::pair<float, T>>> { false, {}};
|
||||
}
|
||||
}
|
||||
return std::tuple<bool, std::vector<std::pair<float, T>>>(true, stops);
|
||||
}
|
||||
|
||||
template <typename T> inline float defaultBaseValue() { return 1.75; }
|
||||
template <> inline float defaultBaseValue<Color>() { return 1.0; }
|
||||
|
||||
template <typename T>
|
||||
std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
|
||||
std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value, const char *property_name) {
|
||||
|
||||
if (!value.IsObject()) {
|
||||
return std::tuple<bool, Function<T>> { true, ConstantFunction<T>(std::get<1>(parseProperty<T>(value, property_name))) };
|
||||
}
|
||||
|
||||
if (!value.HasMember("stops")) {
|
||||
Log::Warning(Event::ParseStyle, "function must specify a function type");
|
||||
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
|
||||
@@ -284,47 +339,47 @@ std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
|
||||
}
|
||||
}
|
||||
|
||||
JSVal value_stops = value["stops"];
|
||||
if (!value_stops.IsArray()) {
|
||||
Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
|
||||
auto stops = parseStops<T>(value["stops"], property_name);
|
||||
|
||||
if (!std::get<0>(stops)) {
|
||||
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
|
||||
}
|
||||
|
||||
std::vector<std::pair<float, T>> stops;
|
||||
for (rapidjson::SizeType i = 0; i < value_stops.Size(); ++i) {
|
||||
JSVal stop = value_stops[i];
|
||||
if (stop.IsArray()) {
|
||||
if (stop.Size() != 2) {
|
||||
Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
|
||||
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
|
||||
}
|
||||
|
||||
JSVal z = stop[rapidjson::SizeType(0)];
|
||||
if (!z.IsNumber()) {
|
||||
Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
|
||||
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
|
||||
}
|
||||
|
||||
stops.emplace_back(z.GetDouble(), parseFunctionArgument<T>(stop[rapidjson::SizeType(1)]));
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
|
||||
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
|
||||
}
|
||||
}
|
||||
|
||||
return std::tuple<bool, Function<T>> { true, StopsFunction<T>(stops, base) };
|
||||
return std::tuple<bool, Function<T>> { true, StopsFunction<T>(std::get<1>(stops), base) };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::tuple<bool, PiecewiseConstantFunction<T>> StyleParser::parsePiecewiseConstantFunction(JSVal value, std::chrono::steady_clock::duration duration) {
|
||||
if (!value.HasMember("stops")) {
|
||||
Log::Warning(Event::ParseStyle, "function must specify a function type");
|
||||
return std::tuple<bool, PiecewiseConstantFunction<T>> { false, {} };
|
||||
}
|
||||
|
||||
auto stops = parseStops<T>(value["stops"], "");
|
||||
|
||||
if (!std::get<0>(stops)) {
|
||||
return std::tuple<bool, PiecewiseConstantFunction<T>> { false, {} };
|
||||
}
|
||||
|
||||
return std::tuple<bool, PiecewiseConstantFunction<T>> { true, { std::get<1>(stops), duration } };
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass) {
|
||||
bool parsed;
|
||||
T result;
|
||||
std::tie(parsed, result) = parseProperty<T>(value, property_name);
|
||||
if (parsed) {
|
||||
klass.set(key, result);
|
||||
auto res = parseProperty<T>(value, property_name);
|
||||
if (std::get<0>(res)) {
|
||||
klass.set(key, std::get<1>(res));
|
||||
}
|
||||
return parsed;
|
||||
return std::get<0>(res);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool StyleParser::setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass, JSVal transition) {
|
||||
auto res = parseProperty<T>(value, property_name, transition);
|
||||
if (std::get<0>(res)) {
|
||||
klass.set(key, std::get<1>(res));
|
||||
}
|
||||
return std::get<0>(res);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -348,6 +403,21 @@ bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey k
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value, const char *transition_name) {
|
||||
if (!value.HasMember(property_name)) {
|
||||
return false;
|
||||
} else {
|
||||
if (value.HasMember(transition_name)) {
|
||||
return setProperty<T>(replaceConstant(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<> std::tuple<bool, std::string> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
if (!value.IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be a string", property_name);
|
||||
@@ -465,72 +535,99 @@ template<> std::tuple<bool, PropertyTransition> StyleParser::parseProperty(JSVal
|
||||
return std::tuple<bool, PropertyTransition> { true, std::move(transition) };
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<std::array<float, 2>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<std::array<float, 2>>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<std::string>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<std::string>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<TranslateAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<TranslateAnchorType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<RotateAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<RotateAnchorType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<CapType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<CapType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<JoinType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<JoinType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<PlacementType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<PlacementType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<TextAnchorType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<TextAnchorType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<TextJustifyType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<TextJustifyType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<TextTransformType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<TextTransformType>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<RotationAlignmentType>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
return parseFunction<RotationAlignmentType>(value, property_name);
|
||||
}
|
||||
|
||||
|
||||
template<> std::tuple<bool, Function<bool>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
if (value.IsObject()) {
|
||||
return parseFunction<bool>(value);
|
||||
} else if (value.IsNumber()) {
|
||||
return std::tuple<bool, Function<bool>> { true, ConstantFunction<bool>(value.GetDouble()) };
|
||||
} else if (value.IsBool()) {
|
||||
return std::tuple<bool, Function<bool>> { true, ConstantFunction<bool>(value.GetBool()) };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be convertible to boolean, or a boolean function", property_name);
|
||||
return std::tuple<bool, Function<bool>> { false, ConstantFunction<bool>(false) };
|
||||
}
|
||||
return parseFunction<bool>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<float>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
if (value.IsObject()) {
|
||||
return parseFunction<float>(value);
|
||||
} else if (value.IsNumber()) {
|
||||
return std::tuple<bool, Function<float>> { true, ConstantFunction<float>(value.GetDouble()) };
|
||||
} else if (value.IsBool()) {
|
||||
return std::tuple<bool, Function<float>> { true, ConstantFunction<float>(value.GetBool()) };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", property_name);
|
||||
return std::tuple<bool, Function<float>> { false, ConstantFunction<float>(0) };
|
||||
}
|
||||
return parseFunction<float>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<Color>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
if (value.IsObject()) {
|
||||
return parseFunction<Color>(value);
|
||||
} else if (value.IsString()) {
|
||||
return std::tuple<bool, Function<Color>> { true, ConstantFunction<Color>(parseColor(value)) };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be a color, or a color function", property_name);
|
||||
return std::tuple<bool, Function<Color>> { false, ConstantFunction<Color>(Color {{ 0, 0, 0, 0 }}) };
|
||||
}
|
||||
return parseFunction<Color>(value, property_name);
|
||||
}
|
||||
|
||||
template<> std::tuple<bool, Function<std::vector<float>>> StyleParser::parseProperty(JSVal value, const char *property_name) {
|
||||
template<> std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) {
|
||||
std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
|
||||
if (transition.HasMember("duration")) {
|
||||
duration = std::chrono::milliseconds(transition["duration"].GetUint());
|
||||
}
|
||||
|
||||
if (value.IsObject()) {
|
||||
return parseFunction<std::vector<float>>(value);
|
||||
return parsePiecewiseConstantFunction<Faded<std::vector<float>>>(value, duration);
|
||||
} else if (value.IsArray()) {
|
||||
std::tuple<bool, std::vector<float>> parsed = parseFloatArray(value);
|
||||
return std::tuple<bool, Function<std::vector<float>>> { std::get<0>(parsed), ConstantFunction<std::vector<float>>(std::get<1>(parsed)) };
|
||||
Faded<std::vector<float>> parsed;
|
||||
std::tuple<bool, std::vector<float>> floatarray = parseFloatArray(value);
|
||||
parsed.to = std::get<1>(floatarray);
|
||||
return std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> { std::get<0>(floatarray), { parsed, duration } };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers, or a number array function", property_name);
|
||||
return std::tuple<bool, Function<std::vector<float>>> { false, ConstantFunction<std::vector<float>>(std::vector<float>()) };
|
||||
return std::tuple<bool, PiecewiseConstantFunction<Faded<std::vector<float>>>> { false, {} };
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool StyleParser::parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value) {
|
||||
if (value.HasMember(property_name)) {
|
||||
JSVal rvalue = replaceConstant(value[property_name]);
|
||||
if (!rvalue.IsArray()) {
|
||||
Log::Warning(Event::ParseStyle, "array value must be an array");
|
||||
}
|
||||
template<> std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> StyleParser::parseProperty(JSVal value, const char *property_name, JSVal transition) {
|
||||
|
||||
if (rvalue.Size() != keys.size()) {
|
||||
Log::Warning(Event::ParseStyle, "array value has unexpected number of elements");
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < keys.size(); i++) {
|
||||
setProperty<T>(rvalue[(rapidjson::SizeType)i], property_name, keys[i], klass);
|
||||
}
|
||||
std::chrono::steady_clock::duration duration = std::chrono::milliseconds(300);
|
||||
if (transition.HasMember("duration")) {
|
||||
duration = std::chrono::milliseconds(transition["duration"].GetUint());
|
||||
}
|
||||
|
||||
if (value.IsObject()) {
|
||||
return parsePiecewiseConstantFunction<Faded<std::string>>(value, duration);
|
||||
} else if (value.IsString()) {
|
||||
Faded<std::string> parsed;
|
||||
parsed.to = { value.GetString(), value.GetStringLength() };
|
||||
return std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> { true, { parsed, duration } };
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value of '%s' must be string or a string function", property_name);
|
||||
return std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> { false, {} };
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma mark - Parse Layers
|
||||
@@ -654,26 +751,26 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<PropertyTransition>("fill-color-transition", Key::FillColor, klass, value);
|
||||
parseOptionalProperty<Function<Color>>("fill-outline-color", Key::FillOutlineColor, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("fill-outline-color-transition", Key::FillOutlineColor, klass, value);
|
||||
parseOptionalProperty<Function<float>>("fill-translate", { Key::FillTranslateX, Key::FillTranslateY }, klass, value);
|
||||
parseOptionalProperty<Function<std::array<float, 2>>>("fill-translate", Key::FillTranslate, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("fill-translate-transition", Key::FillTranslate, klass, value);
|
||||
parseOptionalProperty<TranslateAnchorType>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<std::string>("fill-image", Key::FillImage, 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<Function<float>>("line-opacity", Key::LineOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-opacity-transition", Key::LineOpacity, klass, value);
|
||||
parseOptionalProperty<Function<Color>>("line-color", Key::LineColor, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-color-transition", Key::LineColor, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-translate", { Key::LineTranslateX, Key::LineTranslateY }, klass, value);
|
||||
parseOptionalProperty<Function<std::array<float,2>>>("line-translate", Key::LineTranslate, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-translate-transition", Key::LineTranslate, klass, value);
|
||||
parseOptionalProperty<TranslateAnchorType>("line-translate-anchor", Key::LineTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<Function<TranslateAnchorType>>("line-translate-anchor", Key::LineTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-width", Key::LineWidth, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-width-transition", Key::LineWidth, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-gap-width", Key::LineGapWidth, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-gap-width-transition", Key::LineGapWidth, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-blur", Key::LineBlur, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("line-blur-transition", Key::LineBlur, klass, value);
|
||||
parseOptionalProperty<Function<std::vector<float>>>("line-dasharray", Key::LineDashArray, klass, value);
|
||||
parseOptionalProperty<std::string>("line-image", Key::LineImage, 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<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("icon-opacity-transition", Key::IconOpacity, klass, value);
|
||||
@@ -688,9 +785,9 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<PropertyTransition>("icon-halo-width-transition", Key::IconHaloWidth, klass, value);
|
||||
parseOptionalProperty<Function<float>>("icon-halo-blur", Key::IconHaloBlur, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("icon-halo-blur-transition", Key::IconHaloBlur, klass, value);
|
||||
parseOptionalProperty<Function<float>>("icon-translate", { Key::IconTranslateX, Key::IconTranslateY }, klass, value);
|
||||
parseOptionalProperty<Function<std::array<float, 2>>>("icon-translate", Key::IconTranslate, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("icon-translate-transition", Key::IconTranslate, klass, value);
|
||||
parseOptionalProperty<TranslateAnchorType>("icon-translate-anchor", Key::IconTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<Function<TranslateAnchorType>>("icon-translate-anchor", Key::IconTranslateAnchor, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<float>>("text-opacity", Key::TextOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("text-opacity-transition", Key::TextOpacity, klass, value);
|
||||
@@ -704,15 +801,16 @@ void StyleParser::parsePaint(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<PropertyTransition>("text-halo-width-transition", Key::TextHaloWidth, klass, value);
|
||||
parseOptionalProperty<Function<float>>("text-halo-blur", Key::TextHaloBlur, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("text-halo-blur-transition", Key::TextHaloBlur, klass, value);
|
||||
parseOptionalProperty<Function<float>>("text-translate", { Key::TextTranslateX, Key::TextTranslateY }, klass, value);
|
||||
parseOptionalProperty<Function<std::array<float, 2>>>("text-translate", Key::TextTranslate, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("text-translate-transition", Key::TextTranslate, klass, value);
|
||||
parseOptionalProperty<TranslateAnchorType>("text-translate-anchor", Key::TextTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<Function<TranslateAnchorType>>("text-translate-anchor", Key::TextTranslateAnchor, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<float>>("raster-opacity", Key::RasterOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("raster-opacity-transition", Key::RasterOpacity, klass, value);
|
||||
parseOptionalProperty<Function<float>>("raster-hue-rotate", Key::RasterHueRotate, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("raster-hue-rotate-transition", Key::RasterHueRotate, klass, value);
|
||||
parseOptionalProperty<Function<float>>("raster-brightness", { Key::RasterBrightnessLow, Key::RasterBrightnessHigh }, klass, value);
|
||||
parseOptionalProperty<Function<float>>("raster-brightness-min", Key::RasterBrightnessLow, klass, value);
|
||||
parseOptionalProperty<Function<float>>("raster-brightness-max", Key::RasterBrightnessHigh, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("raster-brightness-transition", Key::RasterBrightness, klass, value);
|
||||
parseOptionalProperty<Function<float>>("raster-saturation", Key::RasterSaturation, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("raster-saturation-transition", Key::RasterSaturation, klass, value);
|
||||
@@ -723,7 +821,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<std::string>("background-image", Key::BackgroundImage, klass, value);
|
||||
parseOptionalProperty<PiecewiseConstantFunction<Faded<std::string>>>("background-image", Key::BackgroundImage, klass, value, "background-image-transition");
|
||||
}
|
||||
|
||||
void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
|
||||
@@ -731,42 +829,42 @@ void StyleParser::parseLayout(JSVal value, util::ptr<StyleBucket> &bucket) {
|
||||
|
||||
parseVisibility<VisibilityType>(*bucket, value);
|
||||
|
||||
parseOptionalProperty<CapType>("line-cap", Key::LineCap, bucket->layout, value);
|
||||
parseOptionalProperty<JoinType>("line-join", Key::LineJoin, bucket->layout, value);
|
||||
parseOptionalProperty<Function<CapType>>("line-cap", Key::LineCap, bucket->layout, value);
|
||||
parseOptionalProperty<Function<JoinType>>("line-join", Key::LineJoin, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("line-miter-limit", Key::LineMiterLimit, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("line-round-limit", Key::LineRoundLimit, bucket->layout, value);
|
||||
|
||||
parseOptionalProperty<PlacementType>("symbol-placement", Key::SymbolPlacement, 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<bool>("symbol-avoid-edges", Key::SymbolAvoidEdges, bucket->layout, value);
|
||||
parseOptionalProperty<bool>("icon-allow-overlap", Key::IconAllowOverlap, bucket->layout, value);
|
||||
parseOptionalProperty<bool>("icon-ignore-placement", Key::IconIgnorePlacement, bucket->layout, value);
|
||||
parseOptionalProperty<bool>("icon-optional", Key::IconOptional, bucket->layout, value);
|
||||
parseOptionalProperty<RotationAlignmentType>("icon-rotation-alignment", Key::IconRotationAlignment, 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<std::string>("icon-image", Key::IconImage, 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);
|
||||
parseOptionalProperty<bool>("icon-keep-upright", Key::IconKeepUpright, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("icon-offset", { Key::IconOffsetX, Key::IconOffsetY }, bucket->layout, value);
|
||||
parseOptionalProperty<RotationAlignmentType>("text-rotation-alignment", Key::TextRotationAlignment, bucket->layout, value);
|
||||
parseOptionalProperty<std::string>("text-field", Key::TextField, bucket->layout, value);
|
||||
parseOptionalProperty<std::string>("text-font", Key::TextFont, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("icon-keep-upright", Key::IconKeepUpright, bucket->layout, value);
|
||||
parseOptionalProperty<Function<std::array<float, 2>>>("icon-offset", Key::IconOffset, bucket->layout, value);
|
||||
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-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);
|
||||
parseOptionalProperty<TextJustifyType>("text-justify", Key::TextJustify, bucket->layout, value);
|
||||
parseOptionalProperty<TextAnchorType>("text-anchor", Key::TextAnchor, bucket->layout, value);
|
||||
parseOptionalProperty<Function<TextJustifyType>>("text-justify", Key::TextJustify, bucket->layout, value);
|
||||
parseOptionalProperty<Function<TextAnchorType>>("text-anchor", Key::TextAnchor, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-max-angle", Key::TextMaxAngle, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-rotate", Key::TextRotate, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-padding", Key::TextPadding, bucket->layout, value);
|
||||
parseOptionalProperty<bool>("text-keep-upright", Key::TextKeepUpright, bucket->layout, value);
|
||||
parseOptionalProperty<TextTransformType>("text-transform", Key::TextTransform, bucket->layout, value);
|
||||
parseOptionalProperty<Function<float>>("text-offset", { Key::TextOffsetX, Key::TextOffsetY }, bucket->layout, value);
|
||||
parseOptionalProperty<bool>("text-allow-overlap", Key::TextAllowOverlap, bucket->layout, value);
|
||||
parseOptionalProperty<bool>("text-ignore-placement", Key::TextIgnorePlacement, bucket->layout, value);
|
||||
parseOptionalProperty<bool>("text-optional", Key::TextOptional, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("text-keep-upright", Key::TextKeepUpright, bucket->layout, value);
|
||||
parseOptionalProperty<Function<TextTransformType>>("text-transform", Key::TextTransform, bucket->layout, value);
|
||||
parseOptionalProperty<Function<std::array<float, 2>>>("text-offset", Key::TextOffset, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("text-allow-overlap", Key::TextAllowOverlap, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("text-ignore-placement", Key::TextIgnorePlacement, bucket->layout, value);
|
||||
parseOptionalProperty<Function<bool>>("text-optional", Key::TextOptional, bucket->layout, value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -69,17 +69,25 @@ private:
|
||||
template <typename T>
|
||||
bool parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value);
|
||||
template <typename T>
|
||||
bool parseOptionalProperty(const char *property_name, const std::vector<PropertyKey> &keys, ClassProperties &klass, JSVal value);
|
||||
bool parseOptionalProperty(const char *property_name, PropertyKey key, ClassProperties &klass, JSVal value, const char *transition_name);
|
||||
template <typename T>
|
||||
bool setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass);
|
||||
template <typename T>
|
||||
bool setProperty(JSVal value, const char *property_name, PropertyKey key, ClassProperties &klass, JSVal transition);
|
||||
|
||||
template <typename T>
|
||||
std::tuple<bool, T> parseProperty(JSVal value, const char *property_name);
|
||||
template <typename T>
|
||||
std::tuple<bool, T> parseProperty(JSVal value, const char *property_name, JSVal transition);
|
||||
|
||||
template <typename T>
|
||||
std::tuple<bool, Function<T>> parseFunction(JSVal value);
|
||||
std::tuple<bool, Function<T>> parseFunction(JSVal value, const char *);
|
||||
template <typename T>
|
||||
T parseFunctionArgument(JSVal value);
|
||||
std::tuple<bool, PiecewiseConstantFunction<T>> parsePiecewiseConstantFunction(JSVal value, std::chrono::steady_clock::duration duration);
|
||||
template <typename T>
|
||||
std::tuple<bool, std::vector<std::pair<float, T>>> parseStops(JSVal value, const char *property_name);
|
||||
|
||||
std::tuple<bool,std::vector<float>> parseFloatArray(JSVal value);
|
||||
|
||||
FilterExpression parseFilter(JSVal);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <mbgl/util/variant.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
#include <mbgl/style/function_properties.hpp>
|
||||
#include <mbgl/style/piecewisefunction_properties.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
@@ -21,7 +21,7 @@ struct FillProperties {
|
||||
Color stroke_color = {{ 0, 0, 0, -1 }};
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
TranslateAnchorType translateAnchor = TranslateAnchorType::Map;
|
||||
std::string image;
|
||||
Faded<std::string> image;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0);
|
||||
@@ -37,9 +37,9 @@ struct LineProperties {
|
||||
float width = 1;
|
||||
float gap_width = 0;
|
||||
float blur = 0;
|
||||
std::vector<float> dash_array;
|
||||
Faded<std::vector<float>> dash_array;
|
||||
float dash_line_width = 1;
|
||||
std::string image;
|
||||
Faded<std::string> image;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return opacity > 0 && color[3] > 0 && width > 0;
|
||||
@@ -96,7 +96,7 @@ struct BackgroundProperties {
|
||||
inline BackgroundProperties() {}
|
||||
float opacity = 1.0f;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
std::string image;
|
||||
Faded<std::string> image;
|
||||
};
|
||||
|
||||
typedef mapbox::util::variant<
|
||||
|
||||
@@ -11,6 +11,16 @@ namespace mbgl {
|
||||
// Stores a premultiplied color, with all four channels ranging from 0..1
|
||||
typedef std::array<float, 4> Color;
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct Faded {
|
||||
T from;
|
||||
float fromScale;
|
||||
T to;
|
||||
float toScale;
|
||||
float t;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
enum class StyleLayerType : uint8_t {
|
||||
|
||||
38
src/mbgl/style/zoom_history.hpp
Normal file
38
src/mbgl/style/zoom_history.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef MBGL_STYLE_ZOOM_HISTORY
|
||||
#define MBGL_STYLE_ZOOM_HISTORY
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct ZoomHistory {
|
||||
float lastZoom;
|
||||
float lastIntegerZoom;
|
||||
std::chrono::steady_clock::time_point lastIntegerZoomTime;
|
||||
bool first = true;
|
||||
|
||||
void update(float z, std::chrono::steady_clock::time_point now) {
|
||||
if (first) {
|
||||
first = false;
|
||||
|
||||
lastIntegerZoom = std::floor(z);
|
||||
lastIntegerZoomTime = std::chrono::steady_clock::time_point(std::chrono::steady_clock::duration(0));
|
||||
lastZoom = z;
|
||||
}
|
||||
|
||||
if (std::floor(lastZoom) < std::floor(z)) {
|
||||
lastIntegerZoom = std::floor(z);
|
||||
lastIntegerZoomTime = now;
|
||||
|
||||
} else if (std::floor(lastZoom) > std::floor(z)) {
|
||||
lastIntegerZoom = std::floor(z + 1);
|
||||
lastIntegerZoomTime = now;
|
||||
}
|
||||
|
||||
lastZoom = z;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include <mbgl/style/types.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace util {
|
||||
|
||||
@@ -22,10 +24,30 @@ inline std::array<T, 4> interpolate(const std::array<T, 4>& a, const std::array<
|
||||
}};
|
||||
}
|
||||
|
||||
inline std::vector<float> interpolate(const std::vector<float> &a, const std::vector<float>, const double) {
|
||||
return a;
|
||||
template <typename T>
|
||||
inline std::array<T, 2> interpolate(const std::array<T, 2>& a, const std::array<T, 2>& b, const double t) {
|
||||
return {{
|
||||
interpolate(a[0], b[0], t),
|
||||
interpolate(a[1], b[1], t)
|
||||
}};
|
||||
}
|
||||
|
||||
// fake interpolations that just return the first value
|
||||
template<> inline bool interpolate(const bool a, const bool, const double) { return a; }
|
||||
template<> inline std::vector<float> interpolate(const std::vector<float> a, const std::vector<float>, const double) { return a; }
|
||||
template<> inline std::string interpolate(const std::string a, const std::string, const double) { return a; }
|
||||
template<> inline TranslateAnchorType interpolate(const TranslateAnchorType a, const TranslateAnchorType, const double) { return a; }
|
||||
template<> inline RotateAnchorType interpolate(const RotateAnchorType a, const RotateAnchorType, const double) { return a; }
|
||||
template<> inline CapType interpolate(const CapType a, const CapType, const double) { return a; }
|
||||
template<> inline JoinType interpolate(const JoinType a, const JoinType, const double) { return a; }
|
||||
template<> inline PlacementType interpolate(const PlacementType a, const PlacementType, const double) { return a; }
|
||||
template<> inline TextAnchorType interpolate(const TextAnchorType a, const TextAnchorType, const double) { return a; }
|
||||
template<> inline TextJustifyType interpolate(const TextJustifyType a, const TextJustifyType, const double) { return a; }
|
||||
template<> inline TextTransformType interpolate(const TextTransformType a, const TextTransformType, const double) { return a; }
|
||||
template<> inline RotationAlignmentType interpolate(const RotationAlignmentType a, const RotationAlignmentType, const double) { return a; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
styles
2
styles
Submodule styles updated: 25b1b7dff3...9b582e2adc
6
test/fixtures/style_parser/function-string-bool-enum.info.json
vendored
Normal file
6
test/fixtures/style_parser/function-string-bool-enum.info.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"default": {
|
||||
"log": [
|
||||
]
|
||||
}
|
||||
}
|
||||
43
test/fixtures/style_parser/function-string-bool-enum.style.json
vendored
Normal file
43
test/fixtures/style_parser/function-string-bool-enum.style.json
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"version": 6,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "mapbox://mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5",
|
||||
"maxzoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [{
|
||||
"id": "waterway_river_canal",
|
||||
"type": "line",
|
||||
"source": "mapbox",
|
||||
"source-layer": "waterway",
|
||||
"filter": ["in", "type", "river", "canal"],
|
||||
"layout": {
|
||||
"line-cap": {
|
||||
"stops": [[0, "round"], [10, "round"]]
|
||||
}
|
||||
},
|
||||
"paint": {
|
||||
"line-translate-anchor": {
|
||||
"stops": [[0, "map"], [10, "viewport"]]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "label",
|
||||
"type": "symbol",
|
||||
"source": "mapbox",
|
||||
"source-layer": "waterway",
|
||||
"layout": {
|
||||
"text-font": {
|
||||
"stops": [[0, "Open Sans Regular"]]
|
||||
},
|
||||
"text-keep-upright": {
|
||||
"stops": [[0, false], [10, true]]
|
||||
}
|
||||
},
|
||||
"paint": {
|
||||
}
|
||||
}]
|
||||
}
|
||||
Submodule test/suite updated: dba0f2b1fa...d2fff4e204
Reference in New Issue
Block a user