Merge branch 'master' of github.com:mapbox/mapbox-gl-native
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
||||
*.xcodeproj
|
||||
*.o
|
||||
*.actual.png
|
||||
*.diff.png
|
||||
/node_modules
|
||||
/mapnik-packaging
|
||||
/macosx/build
|
||||
|
||||
@@ -14,6 +14,7 @@ env:
|
||||
global:
|
||||
- secure: "bG4YYWMfl9API0MSRgmOaJrlGLv06tRg9KJNawBieZvBJbITPpxVGJZT3/l/SEJ+Rl15e2dRex4k+MGQlmT2SqPQxTEYWv1qxNigKPPcla7IWeNmWWqW8uVvFjdglojgBOK2k/xErVQtA4zDfi3mwSXH4DKwquXWsoEKmX2SV7M="
|
||||
- secure: "Cbvap9ubVKgjPe3hUhI6JGeDZzBXHpOG9RaYKh+SdoIPhKnlJiNOYm1egomi+e4uqJInlFKuVHTw7Ng9Cun6Zm0jIxpkSchv1GpsR7hmB3UGnGed19Dw8121FwuUaktN+4YnbVlsyd+u8EHD3+h58t4eELrLrZolM4rS7DL6caA="
|
||||
- secure: "RiBIBfVhhaMjU5ksuwJO3shdvG9FpinBjdSv4co9jg9171SR8edNriedHjVKSIeBhSGNmZmX+twS3dJS/By6tl/LKh9sTynA+ZAYYljkE7jn881B/gMrlYvdAA6og5KvkhV1/0iJWlhuZrMTkhpDR200iLgg3EWBhWjltzmDW/I="
|
||||
|
||||
before_install:
|
||||
- ./scripts/setup_travis.sh
|
||||
@@ -29,6 +30,7 @@ script:
|
||||
- make linux -j4 BUILDTYPE=${BUILDTYPE}
|
||||
- make test -j4 BUILDTYPE=${BUILDTYPE}
|
||||
- ./scripts/run_tests.sh
|
||||
- ./scripts/compare_images.js
|
||||
|
||||
after_script:
|
||||
- ./scripts/deploy_results.sh
|
||||
@@ -38,7 +40,7 @@ notifications:
|
||||
rooms:
|
||||
secure: "SgMjGDp8MP+UTAY/aWJwSQH2hv1Q0vhEc1BdIde59+lEL3u6gNMSexUTSJoVxRlIQTFXDJBU7v58ISdgJX8cPa+UvIC8hhLsayM+cbm+J3jgy7V9E9wllq3RpmXN33TxY7nwKgWdIms2t9YKZco3y4dKKAUyHXrtMvw8NNPQM+4="
|
||||
template:
|
||||
- 'Build <a href="%{build_url}">#%{build_number}</a>: %{author} tested <a href="%{compare_url}">%{commit}</a> in branch <a href="https://github.com/%{repository_slug}/tree/%{branch}">%{branch}</a> of <a href="https://github.com/%{repository_slug}">%{repository_name}</a>: <b>%{commit_message}</b><br>%{message} (%{duration})'
|
||||
- 'Build <a href="%{build_url}">#%{build_number}</a>: %{author} tested <a href="%{compare_url}">%{commit}</a> in branch <a href="https://github.com/%{repository_slug}/tree/%{branch}">%{branch}</a> of <a href="https://github.com/%{repository_slug}">%{repository_name}</a>: <b>%{commit_message}</b><br>%{message} (%{duration}) - Compare: <a href="http://mapbox-gl-testing.s3.amazonaws.com/headless/%{build_number}.1/index.html">1</a> <a href="http://mapbox-gl-testing.s3.amazonaws.com/headless/%{build_number}.2/index.html">2</a> <a href="http://mapbox-gl-testing.s3.amazonaws.com/headless/%{build_number}.3/index.html">3</a> <a href="http://mapbox-gl-testing.s3.amazonaws.com/headless/%{build_number}.4/index.html">4</a>'
|
||||
format: html
|
||||
|
||||
git:
|
||||
|
||||
14
Makefile
@@ -25,11 +25,11 @@ build/test/Makefile: src common config.gypi test/test.gyp
|
||||
deps/run_gyp test/test.gyp --depth=. -Goutput_dir=.. --generator-output=./build/test -f make
|
||||
|
||||
test: build/test/Makefile
|
||||
$(MAKE) -C build/test BUILDTYPE=$(BUILDTYPE) V=$(V) test
|
||||
$(MAKE) -C build/test BUILDTYPE=Testing V=$(V) test
|
||||
|
||||
test/%: build/test/Makefile
|
||||
$(MAKE) -C build/test BUILDTYPE=$(BUILDTYPE) V=$(V) $*
|
||||
(cd build/$(BUILDTYPE) && exec ./test_$*)
|
||||
$(MAKE) -C build/test BUILDTYPE=Testing V=$(V) $*
|
||||
(cd build/Testing && exec ./test_$*)
|
||||
|
||||
# build Mac OS X project for Xcode
|
||||
xtest: config.gypi clear_xcode_cache node
|
||||
@@ -42,7 +42,7 @@ xtest: config.gypi clear_xcode_cache node
|
||||
# Builds the linux app with make. This is also used by Travis CI
|
||||
linux: config.gypi linux/llmr-app.gyp node
|
||||
deps/run_gyp linux/llmr-app.gyp --depth=. -Goutput_dir=.. --generator-output=./build/linux -f make
|
||||
$(MAKE) -C build/linux BUILDTYPE=$(BUILDTYPE) V=$(V) linuxapp
|
||||
$(MAKE) -C build/linux BUILDTYPE=Testing V=$(V) linuxapp
|
||||
|
||||
# Executes the Linux binary
|
||||
run-linux: linux
|
||||
@@ -78,9 +78,9 @@ xproj: config.gypi macosx/llmr-app.gyp clear_xcode_cache node
|
||||
open ./build/macosx/llmr-app.xcodeproj
|
||||
|
||||
# build iOS project for Xcode
|
||||
iproj: config.gypi ios/llmr-app.gyp clear_xcode_cache node
|
||||
deps/run_gyp ios/llmr-app.gyp --depth=. --generator-output=./build -f xcode
|
||||
open ./build/ios/llmr-app.xcodeproj
|
||||
iproj: config.gypi ios/mapbox-gl-cocoa/app/llmr-app.gyp clear_xcode_cache node
|
||||
deps/run_gyp ios/mapbox-gl-cocoa/app/llmr-app.gyp --depth=. --generator-output=./build -f xcode
|
||||
open ./build/ios/mapbox-gl-cocoa/app/llmr-app.xcodeproj
|
||||
|
||||
# build Linux project for Xcode (Runs on Mac OS X too, but without platform-specific code)
|
||||
lproj: config.gypi linux/llmr-app.gyp clear_xcode_cache node
|
||||
|
||||
15
README.md
@@ -27,9 +27,18 @@ First off: if you hit problems during development try:
|
||||
|
||||
This will clear cached build data and update to the latest versions of dependencies.
|
||||
|
||||
### Mapbox API access tokens
|
||||
|
||||
The demo applications use Mapbox vector tiles, which **require a Mapbox account and API access token**. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/account/apps/).
|
||||
|
||||
## OS X
|
||||
|
||||
First run:
|
||||
in the Xcode project, click on the Target icon next to the Run/Stop button, and then "Edit Scheme". In the screen, add an environment variable with the name `MAPBOX_ACCESS_TOKEN` to the targets you want to run.
|
||||
|
||||

|
||||
|
||||
|
||||
Run:
|
||||
|
||||
make setup
|
||||
|
||||
@@ -52,6 +61,8 @@ First, pull down the submodule(s):
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
Insert your access token into `MBXViewController.h`.
|
||||
|
||||
Then run:
|
||||
|
||||
make setup
|
||||
@@ -64,6 +75,8 @@ Target devices: iPhone 4 and above (4S, 5, 5c, 5s) and iPad 2 and above (3, 4, m
|
||||
|
||||
## Ubuntu
|
||||
|
||||
Set the environment variable `MAPBOX_ACCESS_TOKEN` to your token.
|
||||
|
||||
Ensure you have git and other build essentials:
|
||||
|
||||
sudo apt-get update
|
||||
|
||||
643
bin/style.js
10
common.gypi
@@ -33,6 +33,16 @@
|
||||
'DEAD_CODE_STRIPPING': 'YES',
|
||||
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES'
|
||||
}
|
||||
},
|
||||
'Testing': {
|
||||
'cflags_cc': [ '-O3' ],
|
||||
'defines': [ 'NDEBUG', 'TESTING' ],
|
||||
'xcode_settings': {
|
||||
'GCC_OPTIMIZATION_LEVEL': '3',
|
||||
'GCC_GENERATE_DEBUGGING_SYMBOLS': 'NO',
|
||||
'DEAD_CODE_STRIPPING': 'YES',
|
||||
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
21
common/nslog_log.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef LLMR_COMMON_NSLOG_LOG
|
||||
#define LLMR_COMMON_NSLOG_LOG
|
||||
|
||||
#include <llmr/platform/log.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class NSLogBackend : public LogBackend {
|
||||
public:
|
||||
inline ~NSLogBackend() = default;
|
||||
|
||||
void record(EventSeverity severity, Event event, const std::string &msg);
|
||||
void record(EventSeverity severity, Event event, const char* format, ...);
|
||||
void record(EventSeverity severity, Event event, int64_t code);
|
||||
void record(EventSeverity severity, Event event, int64_t code, const std::string &msg);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
37
common/nslog_log.mm
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "nslog_log.hpp"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
void NSLogBackend::record(EventSeverity severity, Event event, const std::string &msg) {
|
||||
NSLog(@"[%s] %s: %@", stringifyEventSeverity(severity), stringifyEvent(event),
|
||||
[[NSString alloc] initWithBytes:msg.data()
|
||||
length:msg.size()
|
||||
encoding:NSUTF8StringEncoding]);
|
||||
}
|
||||
|
||||
|
||||
void NSLogBackend::record(EventSeverity severity, Event event, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
const int len = vsnprintf(NULL, 0, format, args);
|
||||
va_end(args);
|
||||
std::unique_ptr<char[]> buffer(new char[len + 1]);
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer.get(), len + 1, format, args);
|
||||
va_end(args);
|
||||
NSLog(@"[%s] %s: %s", stringifyEventSeverity(severity), stringifyEvent(event), buffer.get());
|
||||
}
|
||||
|
||||
void NSLogBackend::record(EventSeverity severity, Event event, int64_t code) {
|
||||
NSLog(@"[%s] %s: (%lld)", stringifyEventSeverity(severity), stringifyEvent(event), code);
|
||||
}
|
||||
|
||||
void NSLogBackend::record(EventSeverity severity, Event event, int64_t code, const std::string &msg) {
|
||||
NSLog(@"[%s] %s: (%lld) %@", stringifyEventSeverity(severity), stringifyEvent(event), code,
|
||||
[[NSString alloc] initWithBytes:msg.data()
|
||||
length:msg.size()
|
||||
encoding:NSUTF8StringEncoding]);
|
||||
}
|
||||
}
|
||||
29
common/stderr_log.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "stderr_log.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, const std::string &msg) {
|
||||
std::cerr << "[" << severity << "] " << event << ": " << msg << std::endl;
|
||||
}
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, const char* format, ...) {
|
||||
std::cerr << "[" << severity << "] " << event << ": ";
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, int64_t code) {
|
||||
std::cerr << "[" << severity << "] " << event << ": (" << code << ")" << std::endl;
|
||||
}
|
||||
|
||||
void StderrLogBackend::record(EventSeverity severity, Event event, int64_t code, const std::string &msg) {
|
||||
std::cerr << "[" << severity << "] " << event << ": (" << code << ") " << msg << std::endl;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
21
common/stderr_log.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef LLMR_COMMON_STDERR_LOG
|
||||
#define LLMR_COMMON_STDERR_LOG
|
||||
|
||||
#include <llmr/platform/log.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class StderrLogBackend : public LogBackend {
|
||||
public:
|
||||
inline ~StderrLogBackend() = default;
|
||||
|
||||
void record(EventSeverity severity, Event event, const std::string &msg);
|
||||
void record(EventSeverity severity, Event event, const char* format, ...);
|
||||
void record(EventSeverity severity, Event event, int64_t code);
|
||||
void record(EventSeverity severity, Event event, int64_t code, const std::string &msg);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -55,10 +55,11 @@ public:
|
||||
void setAppliedClasses(const std::vector<std::string> &classes);
|
||||
void toggleClass(const std::string &name);
|
||||
const std::vector<std::string> &getAppliedClasses() const;
|
||||
void setAppliedClasses(std::vector<std::string> &class_names);
|
||||
void setDefaultTransitionDuration(uint64_t duration_milliseconds = 0);
|
||||
void setStyleJSON(std::string newStyleJSON);
|
||||
std::string getStyleJSON() const;
|
||||
void setAccessToken(std::string access_token);
|
||||
std::string getAccessToken() const;
|
||||
|
||||
// Transition
|
||||
void cancelTransitions();
|
||||
@@ -166,6 +167,7 @@ private:
|
||||
Painter painter;
|
||||
|
||||
std::string styleJSON = "";
|
||||
std::string accessToken = "";
|
||||
|
||||
bool debug = false;
|
||||
timestamp animationTime = 0;
|
||||
|
||||
@@ -23,7 +23,8 @@ class Texturepool;
|
||||
class Source : public std::enable_shared_from_this<Source>, private util::noncopyable {
|
||||
public:
|
||||
Source(SourceType type = SourceType::Vector, const std::string &url = "",
|
||||
uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22);
|
||||
uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22,
|
||||
const std::string &access_token = "");
|
||||
|
||||
bool update(Map &map);
|
||||
void updateMatrices(const mat4 &projMatrix, const TransformState &transform);
|
||||
@@ -35,7 +36,7 @@ public:
|
||||
std::forward_list<Tile::ID> getIDs() const;
|
||||
void updateClipIDs(const std::map<Tile::ID, ClipID> &mapping);
|
||||
|
||||
static std::string normalizeSourceURL(const std::string &url);
|
||||
static std::string normalizeSourceURL(const std::string &url, const std::string &access_token);
|
||||
|
||||
public:
|
||||
const SourceType type;
|
||||
|
||||
63
include/llmr/platform/event.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef LLMR_PLATFORM_EVENT
|
||||
#define LLMR_PLATFORM_EVENT
|
||||
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
enum class EventSeverity : uint8_t {
|
||||
Debug,
|
||||
Info,
|
||||
Test,
|
||||
Warning,
|
||||
Error,
|
||||
};
|
||||
|
||||
EventSeverity parseEventSeverity(const char *name);
|
||||
const char *stringifyEventSeverity(EventSeverity eventSeverity);
|
||||
::std::ostream& operator<<(::std::ostream& os, EventSeverity eventSeverity);
|
||||
|
||||
enum class Event : uint8_t {
|
||||
General,
|
||||
Setup,
|
||||
Shader,
|
||||
ParseStyle,
|
||||
ParseTile,
|
||||
Render,
|
||||
HttpRequest,
|
||||
};
|
||||
|
||||
Event parseEvent(const char *name);
|
||||
const char *stringifyEvent(Event event);
|
||||
::std::ostream& operator<<(::std::ostream& os, Event event);
|
||||
|
||||
struct EventPermutation {
|
||||
const EventSeverity severity;
|
||||
const Event event;
|
||||
|
||||
constexpr bool operator==(const EventPermutation &rhs) const {
|
||||
return severity == rhs.severity && event == rhs.event;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr EventSeverity disabledEventSeverities[] = {
|
||||
#if !DEBUG
|
||||
EventSeverity::Debug,
|
||||
#endif
|
||||
#if !TESTING
|
||||
EventSeverity::Test,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
constexpr Event disabledEvents[] = {
|
||||
};
|
||||
|
||||
constexpr EventPermutation disabledEventPermutations[] = {
|
||||
{ EventSeverity::Debug, Event::Shader }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
71
include/llmr/platform/log.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef LLMR_PLATFORM_LOG
|
||||
#define LLMR_PLATFORM_LOG
|
||||
|
||||
#include "event.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class LogBackend {
|
||||
public:
|
||||
virtual inline ~LogBackend() = default;
|
||||
virtual void record(EventSeverity severity, Event event, const std::string &msg) = 0;
|
||||
virtual void record(EventSeverity severity, Event event, const char* format, ...) = 0;
|
||||
virtual void record(EventSeverity severity, Event event, int64_t code) = 0;
|
||||
virtual void record(EventSeverity severity, Event event, int64_t code, const std::string &msg) = 0;
|
||||
};
|
||||
|
||||
class Log {
|
||||
private:
|
||||
template <typename T>
|
||||
constexpr static bool includes(const T e, T const *l, const size_t i = 0) {
|
||||
return i >= sizeof l ? false : *(l + i) == e ? true : includes(e, l, i + 1);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename ...Args>
|
||||
static inline void Debug(Event event, Args&& ...args) {
|
||||
Record(EventSeverity::Debug, event, ::std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
static inline void Info(Event event, Args&& ...args) {
|
||||
Record(EventSeverity::Info, event, ::std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
static inline void Warning(Event event, Args&& ...args) {
|
||||
Record(EventSeverity::Warning, event, ::std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
static inline void Error(Event event, Args&& ...args) {
|
||||
Record(EventSeverity::Error, event, ::std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
static inline void Record(EventSeverity severity, Event event, Args&& ...args) {
|
||||
if (!includes(severity, disabledEventSeverities) &&
|
||||
!includes(event, disabledEvents) &&
|
||||
!includes({ severity, event }, disabledEventPermutations)) {
|
||||
if (Backend) {
|
||||
Backend->record(severity, event, ::std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename ...Args>
|
||||
static inline const T &Set(Args&& ...args) {
|
||||
Backend = ::std::unique_ptr<T>(new T(::std::forward<Args>(args)...));
|
||||
return *dynamic_cast<T *>(Backend.get());
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<LogBackend> Backend;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
enum class GeometryType : uint8_t {
|
||||
Any,
|
||||
Point,
|
||||
Line,
|
||||
LineString,
|
||||
Polygon
|
||||
};
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ private:
|
||||
|
||||
template <typename T>
|
||||
struct ExponentialFunction {
|
||||
inline ExponentialFunction(const T &value, float z_base, float slope, const T &min,
|
||||
inline ExponentialFunction(const T &value, float z_base, float exp_base, float slope, const T &min,
|
||||
const T &max)
|
||||
: value(value), min(min), max(max), z_base(z_base), slope(slope) {}
|
||||
: value(value), min(min), max(max), z_base(z_base), exp_base(exp_base), slope(slope) {}
|
||||
T evaluate(float z) const;
|
||||
|
||||
private:
|
||||
const T value, min, max;
|
||||
const float z_base, slope;
|
||||
const float z_base, exp_base, slope;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
namespace llmr {
|
||||
|
||||
enum class PropertyKey {
|
||||
FillEnabled,
|
||||
FillAntialias,
|
||||
FillOpacity,
|
||||
FillColor,
|
||||
@@ -15,7 +14,6 @@ enum class PropertyKey {
|
||||
FillTranslateAnchor,
|
||||
FillImage,
|
||||
|
||||
LineEnabled,
|
||||
LineOpacity,
|
||||
LineColor,
|
||||
LineTranslate, // for transitions only
|
||||
@@ -30,12 +28,10 @@ enum class PropertyKey {
|
||||
LineDashGap,
|
||||
LineImage,
|
||||
|
||||
IconEnabled,
|
||||
IconOpacity,
|
||||
IconRotate,
|
||||
IconRotateAnchor,
|
||||
|
||||
TextEnabled,
|
||||
TextOpacity,
|
||||
TextSize,
|
||||
TextColor,
|
||||
@@ -43,10 +39,8 @@ enum class PropertyKey {
|
||||
TextHaloWidth,
|
||||
TextHaloBlur,
|
||||
|
||||
CompositeEnabled,
|
||||
CompositeOpacity,
|
||||
|
||||
RasterEnabled,
|
||||
RasterOpacity,
|
||||
RasterSpin,
|
||||
RasterBrightnessLow,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class Map;
|
||||
class Sprite;
|
||||
class Source;
|
||||
class StyleLayer;
|
||||
@@ -27,7 +28,7 @@ public:
|
||||
struct exception : std::runtime_error { exception(const char *msg) : std::runtime_error(msg) {} };
|
||||
|
||||
public:
|
||||
Style();
|
||||
Style(Map &map);
|
||||
|
||||
void loadJSON(const uint8_t *const data);
|
||||
|
||||
@@ -63,6 +64,7 @@ private:
|
||||
|
||||
|
||||
private:
|
||||
Map ↦
|
||||
std::set<std::shared_ptr<Source>> activeSources;
|
||||
PropertyTransition defaultTransition;
|
||||
bool initial_render_complete = false;
|
||||
|
||||
@@ -71,7 +71,8 @@ class StyleBucket {
|
||||
public:
|
||||
typedef std::shared_ptr<StyleBucket> Ptr;
|
||||
|
||||
BucketType type = BucketType::None;
|
||||
StyleBucket(StyleLayerType type);
|
||||
|
||||
std::string name;
|
||||
std::shared_ptr<Source> source;
|
||||
std::string source_layer;
|
||||
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
// The name of this layer.
|
||||
const std::string id;
|
||||
|
||||
StyleLayerType type = StyleLayerType::Unknown;
|
||||
|
||||
// Bucket information, telling the renderer how to generate the geometries
|
||||
// for this layer (feature property filters, tessellation instructions, ...).
|
||||
std::shared_ptr<StyleBucket> bucket;
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace llmr {
|
||||
|
||||
enum class ClassID : uint32_t;
|
||||
|
||||
class Map;
|
||||
class StyleLayer;
|
||||
class StyleLayerGroup;
|
||||
|
||||
@@ -24,6 +25,8 @@ class StyleParser {
|
||||
public:
|
||||
using JSVal = const rapidjson::Value&;
|
||||
|
||||
StyleParser(Map &map);
|
||||
|
||||
void parse(JSVal document);
|
||||
|
||||
std::shared_ptr<StyleLayerGroup> getLayers() {
|
||||
@@ -92,6 +95,8 @@ private:
|
||||
std::forward_list<Value> parseValues(JSVal values);
|
||||
|
||||
private:
|
||||
Map ↦
|
||||
|
||||
std::unordered_map<std::string, const rapidjson::Value *> constants;
|
||||
|
||||
std::unordered_map<std::string, const std::shared_ptr<Source>> sources;
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace llmr {
|
||||
|
||||
struct FillProperties {
|
||||
FillProperties() {}
|
||||
bool enabled = true;
|
||||
bool antialias = true;
|
||||
float opacity = 1.0f;
|
||||
Color fill_color = {{ 0, 0, 0, 1 }};
|
||||
@@ -24,13 +23,12 @@ struct FillProperties {
|
||||
std::string image;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return enabled && opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0);
|
||||
return opacity > 0 && (fill_color[3] > 0 || stroke_color[3] > 0);
|
||||
}
|
||||
};
|
||||
|
||||
struct LineProperties {
|
||||
inline LineProperties() {}
|
||||
bool enabled = true;
|
||||
float opacity = 1.0f;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
@@ -42,25 +40,23 @@ struct LineProperties {
|
||||
std::string image;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return enabled && opacity > 0 && color[3] > 0 && width > 0;
|
||||
return opacity > 0 && color[3] > 0 && width > 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct IconProperties {
|
||||
inline IconProperties() {}
|
||||
bool enabled = true;
|
||||
float opacity = 1.0f;
|
||||
float rotate = 0.0f;
|
||||
RotateAnchorType rotate_anchor = RotateAnchorType::Default;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return enabled && opacity > 0;
|
||||
return opacity > 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct TextProperties {
|
||||
inline TextProperties() {}
|
||||
bool enabled = true;
|
||||
float opacity = 1.0f;
|
||||
float size = 12.0f;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
@@ -69,23 +65,21 @@ struct TextProperties {
|
||||
float halo_blur = 1.0f;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return enabled && opacity > 0 && (color[3] > 0 || halo_color[3] > 0) && size > 0;
|
||||
return opacity > 0 && (color[3] > 0 || halo_color[3] > 0) && size > 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct CompositeProperties {
|
||||
inline CompositeProperties() {}
|
||||
bool enabled = true;
|
||||
float opacity = 1.0f;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return enabled && opacity > 0;
|
||||
return opacity > 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct RasterProperties {
|
||||
inline RasterProperties() {}
|
||||
bool enabled = true;
|
||||
float opacity = 1.0f;
|
||||
float spin = 0.0f;
|
||||
std::array<float, 2> brightness = {{ 0, 1 }};
|
||||
@@ -94,7 +88,7 @@ struct RasterProperties {
|
||||
float fade = 0.0f;
|
||||
|
||||
inline bool isVisible() const {
|
||||
return enabled && opacity > 0;
|
||||
return opacity > 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,19 +9,20 @@ namespace llmr {
|
||||
// Stores a premultiplied color, with all four channels ranging from 0..1
|
||||
typedef std::array<float, 4> Color;
|
||||
|
||||
enum class BucketType : uint8_t {
|
||||
None,
|
||||
enum class StyleLayerType : uint8_t {
|
||||
Unknown,
|
||||
Fill,
|
||||
Line,
|
||||
Icon,
|
||||
Text,
|
||||
Raster,
|
||||
Default = None
|
||||
Composite,
|
||||
Background
|
||||
};
|
||||
|
||||
BucketType parseBucketType(const std::string &type);
|
||||
const char *stringifyBucketType(BucketType type);
|
||||
std::ostream& operator<<(std::ostream&, BucketType type);
|
||||
StyleLayerType parseStyleLayerType(const std::string &type);
|
||||
const char *stringifyStyleLayerType(StyleLayerType type);
|
||||
std::ostream& operator<<(std::ostream&, StyleLayerType type);
|
||||
|
||||
|
||||
enum class WindingType : uint8_t {
|
||||
|
||||
@@ -10,12 +10,6 @@ typedef util::variant<bool, int64_t, uint64_t, double, std::string> Value;
|
||||
|
||||
std::string toString(const Value &value);
|
||||
|
||||
inline std::string& operator+=(std::string& out, const Value& value) {
|
||||
out += toString(value);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Value parseValue(pbf data);
|
||||
|
||||
namespace util {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef LLMR_UTIL_TIMER
|
||||
#define LLMR_UTIL_TIMER
|
||||
|
||||
#include <llmr/platform/event.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace llmr {
|
||||
@@ -9,24 +11,29 @@ namespace util {
|
||||
#ifndef DISABLE_TIMER
|
||||
class timer {
|
||||
public:
|
||||
timer();
|
||||
timer(const std::string &name);
|
||||
timer(Event event = Event::General);
|
||||
timer(EventSeverity severity, Event event = Event::General);
|
||||
timer(const std::string &name, Event event = Event::General);
|
||||
timer(const std::string &name, EventSeverity severity, Event event = Event::General);
|
||||
void report(const std::string &name);
|
||||
~timer();
|
||||
|
||||
private:
|
||||
const std::string name;
|
||||
EventSeverity severity = EventSeverity::Debug;
|
||||
Event event = Event::General;
|
||||
uint64_t start;
|
||||
};
|
||||
#else
|
||||
class timer {
|
||||
inline timer() {}
|
||||
inline timer(const std::string &name) {}
|
||||
inline void report (const std::string &name) {}
|
||||
inline timer(Event event = Event::General);
|
||||
inline timer(EventSeverity severity, Event event = Event::General);
|
||||
inline timer(const std::string &name, Event event = Event::General);
|
||||
inline timer(const std::string &name, EventSeverity severity, Event event = Event::General);
|
||||
inline void report(const std::string &name) {}
|
||||
inline ~timer() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,40 +9,43 @@ namespace regex_impl = boost;
|
||||
namespace regex_impl = std;
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace llmr {
|
||||
namespace util {
|
||||
|
||||
namespace detail {
|
||||
const regex_impl::regex tokenRegex("\\{\\{(\\w+)\\}\\}");
|
||||
const regex_impl::regex tokenRegex("\\{(\\w+)\\}");
|
||||
const regex_impl::sregex_token_iterator tokensEnd = regex_impl::sregex_token_iterator();
|
||||
}
|
||||
|
||||
template <typename Tokens>
|
||||
std::string replaceTokens(const std::string &source, const Tokens &tokens) {
|
||||
template <typename Lookup>
|
||||
std::string replaceTokens(const std::string &source, const Lookup &lookup) {
|
||||
std::string result;
|
||||
result.reserve(source.size());
|
||||
|
||||
bool token = false;
|
||||
for (auto token_it = regex_impl::sregex_token_iterator(source.begin(), source.end(),
|
||||
detail::tokenRegex, {-1, 1});
|
||||
token_it != detail::tokensEnd; ++token_it, token = !token) {
|
||||
token_it != detail::tokensEnd; ++token_it, token = !token) {
|
||||
if (!token_it->matched) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token) {
|
||||
const auto it_prop = tokens.find(token_it->str());
|
||||
if (it_prop != tokens.end()) {
|
||||
result += it_prop->second;
|
||||
}
|
||||
} else {
|
||||
result += token_it->str();
|
||||
}
|
||||
result += token ? lookup(token_it->str()) : token_it->str();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string replaceTokens(const std::string &source, const std::map<std::string, T> &properties) {
|
||||
return replaceTokens(source, [&properties](const std::string &token) -> std::string {
|
||||
const auto it_prop = properties.find(token);
|
||||
return it_prop != properties.end() ? toString(it_prop->second) : "";
|
||||
});
|
||||
}
|
||||
|
||||
} // end namespace util
|
||||
} // end namespace llmr
|
||||
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.mapbox.${PRODUCT_NAME:rfc1034identifier}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.0.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>LLMR</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.0.1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>(c) 2014 Mapbox</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// MBXAppDelegate.h
|
||||
// ios
|
||||
//
|
||||
// Created by Justin R. Miller on 1/27/14.
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface MBXAppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// MBXAppDelegate.m
|
||||
// ios
|
||||
//
|
||||
// Created by Justin R. Miller on 1/27/14.
|
||||
//
|
||||
//
|
||||
|
||||
#import "MBXAppDelegate.h"
|
||||
|
||||
#import "MBXViewController.h"
|
||||
|
||||
@implementation MBXAppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
self.window.rootViewController = [MBXViewController new];
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,5 +0,0 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface MBXViewController : UIViewController
|
||||
|
||||
@end
|
||||
@@ -1,214 +0,0 @@
|
||||
#import "MBXViewController.h"
|
||||
|
||||
#import "MGLMapView.h"
|
||||
|
||||
#import "../common/settings_nsuserdefaults.hpp"
|
||||
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
|
||||
@interface MBXViewController () <CLLocationManagerDelegate>
|
||||
|
||||
@property (nonatomic) MGLMapView *mapView;
|
||||
@property (nonatomic) BOOL debug;
|
||||
@property (nonatomic) UIView *palette;
|
||||
@property (nonatomic) CLLocationManager *locationManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MBXViewController
|
||||
|
||||
llmr::Settings_NSUserDefaults *settings = nullptr;
|
||||
|
||||
#pragma mark - Setup
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveState:) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restoreState:) name:UIApplicationWillEnterForegroundNotification object:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds];
|
||||
self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[self.view addSubview:self.mapView];
|
||||
|
||||
self.mapView.viewControllerForLayoutGuides = self;
|
||||
|
||||
settings = new llmr::Settings_NSUserDefaults();
|
||||
[self restoreState:nil];
|
||||
|
||||
[self setupDebugUI];
|
||||
|
||||
self.locationManager = [CLLocationManager new];
|
||||
self.locationManager.delegate = self;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
- (void)saveState:(NSNotification *)notification
|
||||
{
|
||||
if (self.mapView && settings)
|
||||
{
|
||||
settings->longitude = self.mapView.centerCoordinate.longitude;
|
||||
settings->latitude = self.mapView.centerCoordinate.latitude;
|
||||
settings->zoom = self.mapView.zoomLevel;
|
||||
settings->angle = self.mapView.direction;
|
||||
settings->debug = self.mapView.isDebugActive;
|
||||
settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)restoreState:(NSNotification *)notification
|
||||
{
|
||||
if (self.mapView && settings) {
|
||||
settings->load();
|
||||
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(settings->latitude, settings->longitude) zoomLevel:settings->zoom animated:NO];
|
||||
self.mapView.direction = settings->angle;
|
||||
[self.mapView setDebugActive:settings->debug];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
- (void)setupDebugUI
|
||||
{
|
||||
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
|
||||
singleTap.numberOfTapsRequired = 1;
|
||||
[self.mapView addGestureRecognizer:singleTap];
|
||||
|
||||
NSArray *selectorNames = @[ @"unrotate", @"resetPosition", @"toggleDebug", @"toggleStyle", @"locateUser" ];
|
||||
CGFloat buttonSize = 40;
|
||||
CGFloat bufferSize = 20;
|
||||
CGFloat alpha = 0.75;
|
||||
CGFloat paletteWidth = buttonSize + (2 * bufferSize);
|
||||
CGFloat paletteHeight = [selectorNames count] * (buttonSize + bufferSize) + bufferSize;
|
||||
self.palette = [[UIView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width - paletteWidth,
|
||||
(self.view.bounds.size.height - paletteHeight) / 2,
|
||||
paletteWidth,
|
||||
paletteHeight)];
|
||||
self.palette.backgroundColor = [UIColor colorWithWhite:0 alpha:alpha];
|
||||
self.palette.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.palette.layer.cornerRadius = bufferSize;
|
||||
[self.view addSubview:self.palette];
|
||||
for (NSString *selectorName in selectorNames)
|
||||
{
|
||||
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
button.frame = CGRectMake(bufferSize,
|
||||
([selectorNames indexOfObject:selectorName] * (buttonSize + bufferSize)) + bufferSize,
|
||||
buttonSize,
|
||||
buttonSize);
|
||||
[button setImage:[UIImage imageNamed:[selectorName stringByAppendingString:@".png"]] forState:UIControlStateNormal];
|
||||
[button addTarget:self action:NSSelectorFromString(selectorName) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self.palette addSubview:button];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
return UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
|
||||
#pragma mark - Debugging UI
|
||||
|
||||
- (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap
|
||||
{
|
||||
if (singleTap.state == UIGestureRecognizerStateEnded)
|
||||
{
|
||||
[self togglePalette];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)togglePalette
|
||||
{
|
||||
if (self.palette.alpha < 1)
|
||||
{
|
||||
self.palette.userInteractionEnabled = YES;
|
||||
|
||||
[UIView animateWithDuration:0.25 animations:^(void)
|
||||
{
|
||||
self.palette.alpha = 1;
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.palette.userInteractionEnabled = NO;
|
||||
|
||||
[UIView animateWithDuration:0.25 animations:^(void)
|
||||
{
|
||||
self.palette.alpha = 0;
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unrotate
|
||||
{
|
||||
[self.mapView resetNorth];
|
||||
}
|
||||
|
||||
- (void)resetPosition
|
||||
{
|
||||
[self.mapView resetPosition];
|
||||
}
|
||||
|
||||
- (void)toggleDebug
|
||||
{
|
||||
[self.mapView toggleDebug];
|
||||
|
||||
self.debug = ! self.debug;
|
||||
}
|
||||
|
||||
- (void)toggleStyle
|
||||
{
|
||||
[self.mapView toggleStyle];
|
||||
}
|
||||
|
||||
- (void)locateUser
|
||||
{
|
||||
[self.locationManager startUpdatingLocation];
|
||||
}
|
||||
|
||||
#pragma mark - Destruction
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
if (settings)
|
||||
{
|
||||
[self saveState:nil];
|
||||
delete settings;
|
||||
settings = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - User location
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
|
||||
{
|
||||
CLLocation *latestLocation = locations.lastObject;
|
||||
|
||||
if ([latestLocation distanceFromLocation:[[CLLocation alloc] initWithLatitude:self.mapView.centerCoordinate.latitude longitude:self.mapView.centerCoordinate.longitude]] > 100)
|
||||
{
|
||||
[self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(latestLocation.coordinate.latitude, latestLocation.coordinate.longitude) zoomLevel:17 animated:YES];
|
||||
}
|
||||
|
||||
[self.locationManager stopUpdatingLocation];
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
@end
|
||||
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 951 B |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 684 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 951 B |
|
Before Width: | Height: | Size: 1.5 KiB |
BIN
ios/img/Icon.png
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 646 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
@@ -1,70 +0,0 @@
|
||||
{
|
||||
'includes': [
|
||||
'../common.gypi',
|
||||
'../config.gypi'
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
"target_name": "iosapp",
|
||||
"product_name": "Mapbox GL",
|
||||
"type": "executable",
|
||||
"sources": [
|
||||
"./main.m",
|
||||
"./MBXAppDelegate.h",
|
||||
"./MBXAppDelegate.m",
|
||||
"./MBXViewController.h",
|
||||
"./MBXViewController.mm",
|
||||
'<!@(find mapbox-gl-cocoa/mapbox-gl-cocoa -type f -name "*.h")',
|
||||
'<!@(find mapbox-gl-cocoa/mapbox-gl-cocoa -type f -name "*.m")',
|
||||
'<!@(find mapbox-gl-cocoa/mapbox-gl-cocoa -type f -name "*.mm")',
|
||||
"../common/settings_nsuserdefaults.hpp",
|
||||
"../common/settings_nsuserdefaults.mm",
|
||||
"../common/foundation_request.h",
|
||||
"../common/foundation_request.mm",
|
||||
],
|
||||
'product_extension': 'app',
|
||||
'mac_bundle': 1,
|
||||
'mac_bundle_resources': [
|
||||
'<!@(find img -type f)',
|
||||
'<!@(find mapbox-gl-cocoa/mapbox-gl-cocoa/Resources -type f)',
|
||||
'<(SHARED_INTERMEDIATE_DIR)/bin/style.min.js'
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'$(SDKROOT)/System/Library/Frameworks/UIKit.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/OpenGLES.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/GLKit.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/CoreLocation.framework',
|
||||
'$(SDKROOT)/System/Library/Frameworks/CoreGraphics.framework'
|
||||
],
|
||||
},
|
||||
'xcode_settings': {
|
||||
'SDKROOT': 'iphoneos',
|
||||
'SUPPORTED_PLATFORMS':['iphonesimulator','iphoneos'],
|
||||
'ARCHS': [ "armv7", "armv7s", "arm64", "i386" ],
|
||||
'INFOPLIST_FILE': 'Info.plist',
|
||||
'CLANG_CXX_LIBRARY': 'libc++',
|
||||
'CLANG_CXX_LANGUAGE_STANDARD':'c++11',
|
||||
'IPHONEOS_DEPLOYMENT_TARGET':'7.0',
|
||||
'TARGETED_DEVICE_FAMILY': '1,2',
|
||||
'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
|
||||
'CLANG_ENABLE_OBJC_ARC': 'YES'
|
||||
},
|
||||
'configurations': {
|
||||
'Debug': {
|
||||
'xcode_settings': {
|
||||
'CODE_SIGN_IDENTITY': 'iPhone Developer',
|
||||
}
|
||||
},
|
||||
'Release': {
|
||||
'xcode_settings': {
|
||||
'CODE_SIGN_IDENTITY': 'iPhone Distribution',
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": [
|
||||
"../llmr.gyp:llmr-ios"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
18
ios/main.m
@@ -1,18 +0,0 @@
|
||||
//
|
||||
// main.m
|
||||
// ios
|
||||
//
|
||||
// Created by Justin R. Miller on 1/27/14.
|
||||
//
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "MBXAppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([MBXAppDelegate class]));
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
'../common/glfw_view.hpp',
|
||||
'../common/glfw_view.cpp',
|
||||
'../common/curl_request.cpp',
|
||||
'../common/stderr_log.hpp',
|
||||
'../common/stderr_log.cpp',
|
||||
],
|
||||
|
||||
'conditions': [
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "../common/settings_json.hpp"
|
||||
#include "../common/glfw_view.hpp"
|
||||
#include "../common/stderr_log.hpp"
|
||||
|
||||
GLFWView *view = nullptr;
|
||||
|
||||
@@ -22,6 +23,8 @@ void quit_handler(int) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
llmr::Log::Set<llmr::StderrLogBackend>();
|
||||
|
||||
int fullscreen_flag = 0;
|
||||
|
||||
const struct option long_options[] = {
|
||||
@@ -60,6 +63,14 @@ int main(int argc, char *argv[]) {
|
||||
map.setAngle(settings.angle);
|
||||
map.setDebug(settings.debug);
|
||||
|
||||
// Set access token if present
|
||||
const char *token = getenv("MAPBOX_ACCESS_TOKEN");
|
||||
if (token == nullptr) {
|
||||
llmr::Log::Warning(llmr::Event::Setup, "no access token set. mapbox.com tiles won't work.");
|
||||
} else {
|
||||
map.setAccessToken(std::string(token));
|
||||
}
|
||||
|
||||
// Load style
|
||||
map.setStyleJSON(stylejson.str());
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Icon from http://dryicons.com/icon/architecture-blueprint-icons-set/map/
|
||||
@@ -16,6 +16,8 @@
|
||||
'../common/glfw_view.cpp',
|
||||
'../common/foundation_request.h',
|
||||
'../common/foundation_request.mm',
|
||||
'../common/nslog_log.hpp',
|
||||
'../common/nslog_log.mm',
|
||||
],
|
||||
'product_extension': 'app',
|
||||
'mac_bundle': 1,
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#include "../common/settings_nsuserdefaults.hpp"
|
||||
#include "../common/glfw_view.hpp"
|
||||
#include "../common/nslog_log.hpp"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
int main() {
|
||||
llmr::Log::Set<llmr::NSLogBackend>();
|
||||
|
||||
GLFWView view;
|
||||
llmr::Map map(view);
|
||||
|
||||
@@ -13,6 +16,14 @@ int main() {
|
||||
map.setAngle(settings.angle);
|
||||
map.setDebug(settings.debug);
|
||||
|
||||
// Set access token if present
|
||||
const char *token = getenv("MAPBOX_ACCESS_TOKEN");
|
||||
if (token == nullptr) {
|
||||
llmr::Log::Warning(llmr::Event::Setup, "no access token set. mapbox.com tiles won't work.");
|
||||
} else {
|
||||
map.setAccessToken(std::string(token));
|
||||
}
|
||||
|
||||
// Load style
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"style.min" ofType:@"js"];
|
||||
NSString *json = [NSString stringWithContentsOfFile:path
|
||||
@@ -20,8 +31,6 @@ int main() {
|
||||
error:nil];
|
||||
map.setStyleJSON((std::string)[json cStringUsingEncoding:[NSString defaultCStringEncoding]]);
|
||||
|
||||
// fprintf(stderr, "lon: %f, lat: %f, zoom: %f, angle: %f, debug: %d\n", settings.l)
|
||||
|
||||
int ret = view.run();
|
||||
|
||||
// Save settings
|
||||
|
||||
117
scripts/compare_images.js
Executable file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
var base_dir = path.join(path.resolve('.'), 'test/fixtures/styles');
|
||||
|
||||
var files = fs.readdirSync(base_dir).filter(function(name) {
|
||||
return name.match(/\.info\.json$/);
|
||||
});
|
||||
|
||||
var html =
|
||||
'<style>\n' +
|
||||
' body { font-family: Helvetica; }\n' +
|
||||
' h2 a { color:white; text-decoration:none; }\n' +
|
||||
'</style>\n' +
|
||||
'<table>\n' +
|
||||
'<tr>\n' +
|
||||
' <th>Actual</th>\n' +
|
||||
' <th>Expected</th>\n' +
|
||||
' <th>Info</th>\n' +
|
||||
'</tr>\n';
|
||||
|
||||
var exitCode = 0;
|
||||
var failures = 0;
|
||||
|
||||
processFiles();
|
||||
|
||||
function processFiles() {
|
||||
if (!files.length) return done();
|
||||
|
||||
var name = files.shift();
|
||||
|
||||
var info = require(path.join(base_dir, name));
|
||||
|
||||
var keys = Object.keys(info);
|
||||
|
||||
processFileTest();
|
||||
|
||||
function processFileTest() {
|
||||
if (!keys.length) return processFiles();
|
||||
|
||||
var key = keys.shift();
|
||||
|
||||
var base = path.basename(name, '.info.json');
|
||||
|
||||
var actual = path.join(base_dir, base + '/' + key + '.actual.png');
|
||||
var expected = path.join(base_dir, base + '/' + key + '.expected.png');
|
||||
var diff = path.join(base_dir, base + '/' + key + '.diff.png');
|
||||
|
||||
var compare = spawn('compare', ['-metric', 'MAE', actual, expected, diff ]);
|
||||
var error = '';
|
||||
compare.stderr.on('data', function(data) {
|
||||
error += data.toString();
|
||||
});
|
||||
compare.on('exit', function(code, signal) {
|
||||
// The compare program returns 2 on error otherwise 0 if the images are similar or 1 if they are dissimilar.
|
||||
if (code == 2) {
|
||||
writeResult(base, key, info[key], error.trim(), Infinity);
|
||||
exitCode = 2;
|
||||
} else {
|
||||
var match = error.match(/^\d+(?:\.\d+)?\s+\(([^\)]+)\)\s*$/);
|
||||
var difference = match ? parseFloat(match[1]) : Infinity;
|
||||
writeResult(base, key, info[key], match ? '' : error, difference);
|
||||
|
||||
}
|
||||
processFileTest();
|
||||
});
|
||||
compare.stdin.end();
|
||||
}
|
||||
}
|
||||
|
||||
function writeResult(base, key, info, error, difference) {
|
||||
var color = 'green';
|
||||
var allowedDifference = ('diff' in info) ? info.diff : 0.01;
|
||||
if (difference > allowedDifference) {
|
||||
color = 'red';
|
||||
if (exitCode < 1) {
|
||||
exitCode = 1;
|
||||
}
|
||||
failures++;
|
||||
}
|
||||
|
||||
html +=
|
||||
'<tr>\n' +
|
||||
' <td><img src="' + base + '/' + key + '.actual.png" onmouseover="this.src=\'' + base + '/' + key + '.expected.png\'" onmouseout="this.src=\'' + base + '/' + key + '.actual.png\'"></td>\n' +
|
||||
' <td><img src="' + base + '/' + key + '.expected.png" onmouseover="this.src=\'' + base + '/' + key + '.diff.png\'" onmouseout="this.src=\'' + base + '/' + key + '.expected.png\'"></td>\n' +
|
||||
' <td>\n' +
|
||||
' <h2 style="text-align:center; background:' + color + '"><a href="' + base + '.style.json">' + base + '/' + key + '</a></h2>\n' +
|
||||
(error ? ' <p>' + error + '</p>\n' : '') +
|
||||
' <ul>\n' +
|
||||
' <li>diff: <strong>' + difference + '</strong></li>\n' +
|
||||
' <li>zoom: <strong>' + (info.zoom || 0) + '</strong></li>\n' +
|
||||
' <li>center: <strong>' + (info.center || [0, 0]) + '</strong></li>\n' +
|
||||
' <li>bearing: <strong>' + (info.bearing || 0) + '</strong></li>\n' +
|
||||
' <li>width: <strong>' + (info.width || 512) + '</strong></li>\n' +
|
||||
' <li>height: <strong>' + (info.height || 512) + '</strong></li>\n' +
|
||||
' </ul>\n' +
|
||||
' </td>\n' +
|
||||
'</tr>\n'
|
||||
;
|
||||
}
|
||||
|
||||
function done() {
|
||||
html += "</table>\n";
|
||||
|
||||
fs.writeFileSync(path.join(base_dir, 'index.html'), html);
|
||||
console.warn('Results at: ' + path.join(base_dir, 'index.html'));
|
||||
if (failures) {
|
||||
console.warn('\x1B[1m\x1B[31m' + failures + ' ' + (failures == 1 ? 'image doesn\'t' : 'images don\'t') + ' match\x1B[39m\x1B[22m');
|
||||
} else {
|
||||
console.warn('\x1B[1m\x1B[32mAll images match\x1B[39m\x1B[22m');
|
||||
}
|
||||
|
||||
process.exit(exitCode);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var html =
|
||||
'<style>body { font-family: Helvetica; }</style>\n' +
|
||||
'<table>\n' +
|
||||
'<tr>\n' +
|
||||
' <th>Actual</th>\n' +
|
||||
' <th>Expected</th>\n' +
|
||||
' <th>Info</th>\n' +
|
||||
'</tr>\n';
|
||||
|
||||
var dir = fs.readdirSync('./test/fixtures/styles').filter(function(name) {
|
||||
return name.match(/\.info\.json$/);
|
||||
}).forEach(function(name) {
|
||||
var info = require(path.join(path.resolve('.'), './test/fixtures/styles', name));
|
||||
var base = path.basename(name, '.info.json');
|
||||
|
||||
html +=
|
||||
'<tr>\n' +
|
||||
' <td><img src="' + base + '.actual.png"></td>\n' +
|
||||
' <td><img src="https://raw.githubusercontent.com/mapbox/mapbox-gl-native/' + process.env.TRAVIS_COMMIT + '/test/fixtures/styles/' + base + '.expected.png"></td>\n' +
|
||||
' <td>\n' +
|
||||
' <h2 style="text-align:center"><a href="https://raw.githubusercontent.com/mapbox/mapbox-gl-native/' + process.env.TRAVIS_COMMIT + '/test/fixtures/styles/' + base + '.style.json">' + base + '</a></h2>\n' +
|
||||
' <ul>\n' +
|
||||
' <li>zoom: <strong>' + (info.zoom || 0) + '</strong></li>\n' +
|
||||
' <li>latitude: <strong>' + (info.latitude || 0) + '</strong></li>\n' +
|
||||
' <li>longitude: <strong>' + (info.longitude || 0) + '</strong></li>\n' +
|
||||
' <li>angle: <strong>' + (info.angle || 0) + '</strong></li>\n' +
|
||||
' <li>width: <strong>' + (info.width || 0) + '</strong></li>\n' +
|
||||
' <li>height: <strong>' + (info.height || 0) + '</strong></li>\n' +
|
||||
' </ul>\n' +
|
||||
' </td>\n' +
|
||||
'</tr>\n'
|
||||
;
|
||||
});
|
||||
|
||||
html += "</table\n";
|
||||
|
||||
fs.writeFileSync('./test/fixtures/styles/index.html', html);
|
||||
@@ -3,9 +3,6 @@
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
node scripts/
|
||||
aws s3 cp test/fixtures/styles/ s3://mapbox-gl-testing/headless/$TRAVIS_JOB_NUMBER/ --acl public-read --recursive
|
||||
|
||||
aws s3 cp test/fixtures/styles/ s3://mapbox-gl-testing/headless/$TRAVIS_BUILD_NUMBER/$TRAVIS_JOB_NUMBER/ --acl public-read --recursive --exclude "*" --include "*.actual.png" --include "*.html"
|
||||
|
||||
|
||||
echo http://mapbox-gl-testing.s3.amazonaws.com/headless/$TRAVIS_BUILD_NUMBER/$TRAVIS_JOB_NUMBER/index.html
|
||||
echo http://mapbox-gl-testing.s3.amazonaws.com/headless/$TRAVIS_JOB_NUMBER/index.html
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
BUILDTYPE="${BUILDTYPE:-Release}"
|
||||
|
||||
cd build/${BUILDTYPE}
|
||||
cd build/Testing
|
||||
|
||||
for TEST in ./test_* ; do
|
||||
${TEST}
|
||||
|
||||
@@ -22,7 +22,7 @@ using namespace llmr;
|
||||
Map::Map(View& view)
|
||||
: view(view),
|
||||
transform(),
|
||||
style(std::make_shared<Style>()),
|
||||
style(std::make_shared<Style>(*this)),
|
||||
glyphAtlas(std::make_shared<GlyphAtlas>(1024, 1024)),
|
||||
spriteAtlas(std::make_shared<SpriteAtlas>(512, 512)),
|
||||
texturepool(std::make_shared<Texturepool>()),
|
||||
@@ -183,6 +183,14 @@ std::string Map::getStyleJSON() const {
|
||||
return styleJSON;
|
||||
}
|
||||
|
||||
void Map::setAccessToken( std::string access_token) {
|
||||
accessToken.swap(access_token);
|
||||
}
|
||||
|
||||
std::string Map::getAccessToken() const {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
#pragma mark - Size
|
||||
|
||||
// Note: This function is called from another thread. Make sure you only call threadsafe functions!
|
||||
@@ -397,10 +405,6 @@ const std::vector<std::string> &Map::getAppliedClasses() const {
|
||||
return style->getAppliedClasses();
|
||||
}
|
||||
|
||||
void Map::setAppliedClasses(std::vector<std::string> &class_names) {
|
||||
style->setAppliedClasses(class_names);
|
||||
}
|
||||
|
||||
void Map::setDefaultTransitionDuration(uint64_t duration_milliseconds) {
|
||||
style->setDefaultTransitionDuration(duration_milliseconds);
|
||||
}
|
||||
@@ -600,23 +604,23 @@ void Map::renderLayer(std::shared_ptr<StyleLayer> layer_desc, RenderPass pass) {
|
||||
|
||||
// Abort early if we can already deduce from the bucket type that
|
||||
// we're not going to render anything anyway during this pass.
|
||||
switch (layer_desc->bucket->type) {
|
||||
case BucketType::Fill:
|
||||
switch (layer_desc->type) {
|
||||
case StyleLayerType::Fill:
|
||||
if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Line:
|
||||
case StyleLayerType::Line:
|
||||
if (pass == Opaque) return;
|
||||
if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Icon:
|
||||
case StyleLayerType::Icon:
|
||||
if (pass == Opaque) return;
|
||||
if (!layer_desc->getProperties<IconProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Text:
|
||||
case StyleLayerType::Text:
|
||||
if (pass == Opaque) return;
|
||||
if (!layer_desc->getProperties<TextProperties>().isVisible()) return;
|
||||
break;
|
||||
case BucketType::Raster:
|
||||
case StyleLayerType::Raster:
|
||||
if (pass == Translucent) return;
|
||||
if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
|
||||
break;
|
||||
@@ -626,7 +630,7 @@ void Map::renderLayer(std::shared_ptr<StyleLayer> layer_desc, RenderPass pass) {
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
|
||||
<< layer_desc->bucket->type << ")" << std::endl;
|
||||
<< layer_desc->type << ")" << std::endl;
|
||||
}
|
||||
|
||||
layer_desc->bucket->source->render(painter, layer_desc);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <llmr/util/string.hpp>
|
||||
#include <llmr/util/texturepool.hpp>
|
||||
#include <llmr/util/vec.hpp>
|
||||
#include <llmr/util/token.hpp>
|
||||
#include <llmr/util/std.hpp>
|
||||
#include <llmr/geometry/glyph_atlas.hpp>
|
||||
#include <llmr/style/style_layer.hpp>
|
||||
@@ -18,23 +19,26 @@
|
||||
namespace llmr {
|
||||
|
||||
Source::Source(SourceType type, const std::string &url,
|
||||
uint32_t tile_size, uint32_t min_zoom, uint32_t max_zoom)
|
||||
uint32_t tile_size, uint32_t min_zoom, uint32_t max_zoom,
|
||||
const std::string &access_token)
|
||||
: type(type),
|
||||
url(normalizeSourceURL(url)),
|
||||
url(normalizeSourceURL(url, access_token)),
|
||||
tile_size(tile_size),
|
||||
min_zoom(min_zoom),
|
||||
max_zoom(max_zoom) {}
|
||||
|
||||
std::string Source::normalizeSourceURL(const std::string &url) {
|
||||
std::string Source::normalizeSourceURL(const std::string &url, const std::string &access_token) {
|
||||
const std::string t = "mapbox://";
|
||||
if (url.compare(0, t.length(), t) == 0) {
|
||||
return std::string("http://api.tiles.mapbox.com/v3/") + url.substr(t.length()) + "/%d/%d/%d.vector.pbf";
|
||||
if (access_token.empty()) {
|
||||
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
|
||||
}
|
||||
return std::string("https://api.tiles.mapbox.com/v4/") + url.substr(t.length()) + "/{z}/{x}/{y}.vector.pbf?access_token=" + access_token;
|
||||
} else {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Source::update(Map &map) {
|
||||
if (map.getTime() > updated) {
|
||||
return updateTiles(map);
|
||||
@@ -142,14 +146,17 @@ TileData::State Source::addTile(Map &map, const Tile::ID& id) {
|
||||
|
||||
if (!new_tile.data) {
|
||||
// If we don't find working tile data, we're just going to load it.
|
||||
|
||||
std::string formed_url;
|
||||
const std::string formed_url = util::replaceTokens(url, [&](const std::string &token) -> std::string {
|
||||
if (token == "z") return std::to_string(normalized_id.z);
|
||||
if (token == "x") return std::to_string(normalized_id.x);
|
||||
if (token == "y") return std::to_string(normalized_id.y);
|
||||
if (token == "ratio") return (map.getState().getPixelRatio() > 1.0 ? "@2x" : "");
|
||||
return "";
|
||||
});
|
||||
|
||||
if (type == SourceType::Vector) {
|
||||
formed_url = util::sprintf<256>(url, normalized_id.z, normalized_id.x, normalized_id.y);
|
||||
new_tile.data = std::make_shared<VectorTileData>(normalized_id, map, formed_url);
|
||||
} else if (type == SourceType::Raster) {
|
||||
formed_url = util::sprintf<256>(url, normalized_id.z, normalized_id.x, normalized_id.y, (map.getState().getPixelRatio() > 1.0 ? "@2x" : ""));
|
||||
new_tile.data = std::make_shared<RasterTileData>(normalized_id, map, formed_url);
|
||||
} else {
|
||||
throw std::runtime_error("source type not implemented");
|
||||
|
||||
@@ -122,7 +122,7 @@ std::unique_ptr<Bucket> TileParser::createBucket(std::shared_ptr<StyleBucket> bu
|
||||
} else if (bucket_desc->render.is<StyleBucketRaster>()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
fprintf(stderr, "[WARNING] unknown bucket render type for layer '%s'\n", bucket_desc->source_layer.c_str());
|
||||
fprintf(stderr, "[WARNING] unknown bucket render type for layer '%s' (source layer '%s')\n", bucket_desc->name.c_str(), bucket_desc->source_layer.c_str());
|
||||
}
|
||||
} else {
|
||||
// The layer specified in the bucket does not exist. Do nothing.
|
||||
|
||||
@@ -92,7 +92,7 @@ float TransformState::getPixelRatio() const {
|
||||
#pragma mark - Zoom
|
||||
|
||||
float TransformState::getNormalizedZoom() const {
|
||||
return std::log(scale * util::tileSize / 256.0f) / M_LN2;
|
||||
return std::log(scale * util::tileSize / 512.0f) / M_LN2;
|
||||
}
|
||||
|
||||
int32_t TransformState::getIntegerZoom() const {
|
||||
|
||||
@@ -272,7 +272,7 @@ void FilteredVectorTileLayer::iterator::operator++() {
|
||||
} else if (feature_pbf.tag == 3) { // geometry type
|
||||
switch (FeatureType(feature_pbf.varint())) {
|
||||
case FeatureType::Point: extractor.setType(FilterExpression::GeometryType::Point); break;
|
||||
case FeatureType::LineString: extractor.setType(FilterExpression::GeometryType::Line); break;
|
||||
case FeatureType::LineString: extractor.setType(FilterExpression::GeometryType::LineString); break;
|
||||
case FeatureType::Polygon: extractor.setType(FilterExpression::GeometryType::Polygon); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
60
src/platform/event.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#include <llmr/platform/event.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
EventSeverity parseEventSeverity(const char *name) {
|
||||
if (strcmp(name, "DEBUG") == 0) return EventSeverity::Debug;
|
||||
if (strcmp(name, "INFO") == 0) return EventSeverity::Info;
|
||||
if (strcmp(name, "TEST") == 0) return EventSeverity::Test;
|
||||
if (strcmp(name, "WARNING") == 0) return EventSeverity::Warning;
|
||||
if (strcmp(name, "ERROR") == 0) return EventSeverity::Error;
|
||||
return EventSeverity(-1);
|
||||
}
|
||||
|
||||
const char *stringifyEventSeverity(EventSeverity eventSeverity) {
|
||||
switch (eventSeverity) {
|
||||
case EventSeverity::Debug: return "DEBUG";
|
||||
case EventSeverity::Info: return "INFO";
|
||||
case EventSeverity::Test: return "TEST";
|
||||
case EventSeverity::Warning: return "WARNING";
|
||||
case EventSeverity::Error: return "ERROR";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, EventSeverity eventSeverity) {
|
||||
return os << stringifyEventSeverity(eventSeverity);
|
||||
}
|
||||
|
||||
Event parseEvent(const char *name) {
|
||||
if (strcmp(name, "General") == 0) return Event::General;
|
||||
if (strcmp(name, "Setup") == 0) return Event::Setup;
|
||||
if (strcmp(name, "Shader") == 0) return Event::Shader;
|
||||
if (strcmp(name, "ParseStyle") == 0) return Event::ParseStyle;
|
||||
if (strcmp(name, "ParseTile") == 0) return Event::ParseTile;
|
||||
if (strcmp(name, "Render") == 0) return Event::Render;
|
||||
if (strcmp(name, "HttpRequest") == 0) return Event::HttpRequest;
|
||||
return Event(-1);
|
||||
}
|
||||
|
||||
const char *stringifyEvent(Event event) {
|
||||
switch (event) {
|
||||
case Event::General: return "General";
|
||||
case Event::Setup: return "Setup";
|
||||
case Event::Shader: return "Shader";
|
||||
case Event::ParseStyle: return "ParseStyle";
|
||||
case Event::ParseTile: return "ParseTile";
|
||||
case Event::Render: return "Render";
|
||||
case Event::HttpRequest: return "HttpRequest";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, Event event) {
|
||||
return os << stringifyEvent(event);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
7
src/platform/log.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <llmr/platform/log.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
std::unique_ptr<LogBackend> Log::Backend;
|
||||
|
||||
}
|
||||
@@ -150,7 +150,6 @@ void Painter::renderFill(FillBucket& bucket, std::shared_ptr<StyleLayer> layer_d
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
const FillProperties &properties = layer_desc->getProperties<FillProperties>();
|
||||
if (!properties.enabled) return;
|
||||
|
||||
if (layer_desc->rasterize && layer_desc->rasterize->isEnabled(id.z)) {
|
||||
if (pass == Translucent) {
|
||||
|
||||
@@ -14,7 +14,6 @@ void Painter::renderIcon(IconBucket& bucket, std::shared_ptr<StyleLayer> layer_d
|
||||
if (pass == Opaque) return;
|
||||
|
||||
const IconProperties &properties = layer_desc->getProperties<IconProperties>();
|
||||
if (!properties.enabled) return;
|
||||
|
||||
// TODO: when translating icon, are we doing this in the bucket already?
|
||||
// const mat4 &vtxMatrix = translatedMatrix(properties.translate, id, properties.translateAnchor);
|
||||
|
||||
@@ -11,7 +11,6 @@ void Painter::renderLine(LineBucket& bucket, std::shared_ptr<StyleLayer> layer_d
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
const LineProperties &properties = layer_desc->getProperties<LineProperties>();
|
||||
if (!properties.enabled) return;
|
||||
|
||||
float width = properties.width;
|
||||
float offset = properties.offset / 2;
|
||||
|
||||
@@ -9,7 +9,6 @@ void Painter::renderRaster(RasterBucket& bucket, std::shared_ptr<StyleLayer> lay
|
||||
if (pass == Translucent) return;
|
||||
|
||||
const RasterProperties &properties = layer_desc->getProperties<RasterProperties>();
|
||||
if (!properties.enabled) return;
|
||||
|
||||
depthMask(false);
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ void Painter::renderText(TextBucket& bucket, std::shared_ptr<StyleLayer> layer_d
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
const TextProperties &properties = layer_desc->getProperties<TextProperties>();
|
||||
if (!properties.enabled) return;
|
||||
|
||||
mat4 exMatrix;
|
||||
matrix::copy(exMatrix, projMatrix);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#include <llmr/shader/shader.hpp>
|
||||
#include <llmr/platform/gl.hpp>
|
||||
#if defined(DEBUG)
|
||||
#include <llmr/util/timer.hpp>
|
||||
#endif
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <llmr/platform/log.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace llmr;
|
||||
@@ -12,23 +10,17 @@ using namespace llmr;
|
||||
Shader::Shader(const GLchar *vertSource, const GLchar *fragSource)
|
||||
: valid(false),
|
||||
program(0) {
|
||||
#if defined(DEBUG)
|
||||
util::timer timer("shader compilation");
|
||||
#endif
|
||||
util::timer timer("shader compilation", Event::Shader);
|
||||
|
||||
GLuint vertShader;
|
||||
if (!compileShader(&vertShader, GL_VERTEX_SHADER, vertSource)) {
|
||||
#if defined(DEBUG)
|
||||
fprintf(stderr, "Vertex shader failed to compile: %s\n", vertSource);
|
||||
#endif
|
||||
Log::Error(Event::Shader, "Vertex shader failed to compile: %s", vertSource);
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint fragShader;
|
||||
if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, fragSource)) {
|
||||
#if defined(DEBUG)
|
||||
fprintf(stderr, "Fragment shader failed to compile: %s\n", fragSource);
|
||||
#endif
|
||||
Log::Error(Event::Shader, "Fragment shader failed to compile: %s", fragSource);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,20 +36,17 @@ Shader::Shader(const GLchar *vertSource, const GLchar *fragSource)
|
||||
GLint status;
|
||||
glLinkProgram(program);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(program, logLength, &logLength, log);
|
||||
fprintf(stderr, "Program link log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
if (status == 0) {
|
||||
fprintf(stderr, "Program failed to link\n");
|
||||
GLint logLength;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(program, logLength, &logLength, log);
|
||||
Log::Error(Event::Shader, "Program failed to link: %s", log);
|
||||
free(log);
|
||||
}
|
||||
|
||||
glDeleteShader(vertShader);
|
||||
vertShader = 0;
|
||||
glDeleteShader(fragShader);
|
||||
@@ -73,22 +62,17 @@ Shader::Shader(const GLchar *vertSource, const GLchar *fragSource)
|
||||
GLint status;
|
||||
glValidateProgram(program);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(program, logLength, &logLength, log);
|
||||
fprintf(stderr, "Program validate log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
|
||||
if (status == 0) {
|
||||
#if defined(DEBUG)
|
||||
fprintf(stderr, "Program failed to validate\n");
|
||||
#endif
|
||||
GLint logLength;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(program, logLength, &logLength, log);
|
||||
Log::Error(Event::Shader, "Program failed to validate: %s", log);
|
||||
free(log);
|
||||
}
|
||||
|
||||
glDeleteShader(vertShader);
|
||||
vertShader = 0;
|
||||
glDeleteShader(fragShader);
|
||||
@@ -119,19 +103,17 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
|
||||
|
||||
glCompileShader(*shader);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetShaderInfoLog(*shader, logLength, &logLength, log);
|
||||
fprintf(stderr, "Shader compile log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
|
||||
if (status == 0) {
|
||||
GLint logLength;
|
||||
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetShaderInfoLog(*shader, logLength, &logLength, log);
|
||||
Log::Error(Event::Shader, "Shader failed to compile: %s", log);
|
||||
free(log);
|
||||
}
|
||||
|
||||
glDeleteShader(*shader);
|
||||
*shader = 0;
|
||||
return false;
|
||||
|
||||
@@ -175,10 +175,10 @@ std::ostream& operator <<(std::ostream &s, FilterExpression::Operator op) {
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, FilterExpression::GeometryType type) {
|
||||
switch (type) {
|
||||
case FilterExpression::GeometryType::Point: s << "point"; break;
|
||||
case FilterExpression::GeometryType::Line: s << "line"; break;
|
||||
case FilterExpression::GeometryType::Polygon: s << "polygon"; break;
|
||||
case FilterExpression::GeometryType::Any: s << "any"; break;
|
||||
case FilterExpression::GeometryType::Point: s << "Point"; break;
|
||||
case FilterExpression::GeometryType::LineString: s << "LineString"; break;
|
||||
case FilterExpression::GeometryType::Polygon: s << "Polygon"; break;
|
||||
case FilterExpression::GeometryType::Any: s << "<Any>"; break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -265,9 +265,9 @@ void FilterExpression::setGeometryType(GeometryType g) {
|
||||
}
|
||||
|
||||
FilterExpression::GeometryType parseGeometryType(const std::string &geometry) {
|
||||
if (geometry == "point") return FilterExpression::GeometryType::Point;
|
||||
if (geometry == "line") return FilterExpression::GeometryType::Line;
|
||||
if (geometry == "polygon") return FilterExpression::GeometryType::Polygon;
|
||||
if (geometry == "Point") return FilterExpression::GeometryType::Point;
|
||||
if (geometry == "LineString") return FilterExpression::GeometryType::LineString;
|
||||
if (geometry == "Polygon") return FilterExpression::GeometryType::Polygon;
|
||||
return FilterExpression::GeometryType::Any;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,16 +34,16 @@ bool ExponentialFunction<bool>::evaluate(float z) const {
|
||||
|
||||
template <>
|
||||
float ExponentialFunction<float>::evaluate(float z) const {
|
||||
return std::fmin(std::fmax(min, value + std::pow(1.75, (z - z_base)) * slope), max);
|
||||
return std::fmin(std::fmax(min, value + std::pow(exp_base, (z - z_base)) * slope), max);
|
||||
}
|
||||
|
||||
template <>
|
||||
Color ExponentialFunction<Color>::evaluate(float z) const {
|
||||
return {{
|
||||
std::fmin(std::fmax(min[0], value[0] + float(std::pow(1.75, (z - z_base))) * slope), max[0]),
|
||||
std::fmin(std::fmax(min[1], value[1] + float(std::pow(1.75, (z - z_base))) * slope), max[1]),
|
||||
std::fmin(std::fmax(min[2], value[2] + float(std::pow(1.75, (z - z_base))) * slope), max[2]),
|
||||
std::fmin(std::fmax(min[3], value[3] + float(std::pow(1.75, (z - z_base))) * slope), max[3])
|
||||
std::fmin(std::fmax(min[0], value[0] + float(std::pow(exp_base, (z - z_base))) * slope), max[0]),
|
||||
std::fmin(std::fmax(min[1], value[1] + float(std::pow(exp_base, (z - z_base))) * slope), max[1]),
|
||||
std::fmin(std::fmax(min[2], value[2] + float(std::pow(exp_base, (z - z_base))) * slope), max[2]),
|
||||
std::fmin(std::fmax(min[3], value[3] + float(std::pow(exp_base, (z - z_base))) * slope), max[3])
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace llmr {
|
||||
|
||||
const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::FillEnabled, true },
|
||||
{ PropertyKey::FillAntialias, true },
|
||||
{ PropertyKey::FillOpacity, 1.0f },
|
||||
{ PropertyKey::FillColor, Color({{ 0, 0, 0, 1 }}) },
|
||||
@@ -11,7 +10,6 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::FillTranslateY, 0.0f },
|
||||
{ PropertyKey::FillTranslateAnchor, TranslateAnchorType::Map },
|
||||
|
||||
{ PropertyKey::LineEnabled, true },
|
||||
{ PropertyKey::LineOpacity, 1.0f },
|
||||
{ PropertyKey::LineColor, Color({{ 0, 0, 0, 1 }}) },
|
||||
{ PropertyKey::LineTranslateX, 0.0f },
|
||||
@@ -23,12 +21,10 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::LineDashLand, 1.0f },
|
||||
{ PropertyKey::LineDashGap, -1.0f },
|
||||
|
||||
{ PropertyKey::IconEnabled, true },
|
||||
{ PropertyKey::IconOpacity, 1.0f },
|
||||
{ PropertyKey::IconRotate, 0.0f },
|
||||
{ PropertyKey::IconRotateAnchor, RotateAnchorType::Viewport },
|
||||
|
||||
{ PropertyKey::TextEnabled, true },
|
||||
{ PropertyKey::TextOpacity, 1.0f },
|
||||
{ PropertyKey::TextSize, 16.0f },
|
||||
{ PropertyKey::TextColor, Color({{ 0, 0, 0, 1 }}) },
|
||||
@@ -36,10 +32,8 @@ const std::map<PropertyKey, PropertyValue> PropertyFallbackValue::properties = {
|
||||
{ PropertyKey::TextHaloWidth, 0.25f },
|
||||
{ PropertyKey::TextHaloBlur, 1.0f },
|
||||
|
||||
{ PropertyKey::CompositeEnabled, true },
|
||||
{ PropertyKey::CompositeOpacity, 1.0f },
|
||||
|
||||
{ PropertyKey::RasterEnabled, true },
|
||||
{ PropertyKey::RasterOpacity, 1.0f },
|
||||
{ PropertyKey::RasterSpin, 0.0f },
|
||||
{ PropertyKey::RasterBrightnessLow, 0.0f },
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <llmr/map/map.hpp>
|
||||
#include <llmr/style/style.hpp>
|
||||
#include <llmr/style/style_layer_group.hpp>
|
||||
#include <llmr/style/style_parser.hpp>
|
||||
@@ -12,7 +13,8 @@
|
||||
|
||||
namespace llmr {
|
||||
|
||||
Style::Style() {
|
||||
Style::Style(Map &map)
|
||||
: map(map) {
|
||||
}
|
||||
|
||||
void Style::updateSources() {
|
||||
@@ -107,7 +109,7 @@ void Style::loadJSON(const uint8_t *const data) {
|
||||
throw error::style_parse(doc.GetErrorOffset(), doc.GetParseError());
|
||||
}
|
||||
|
||||
StyleParser parser;
|
||||
StyleParser parser(map);
|
||||
parser.parse(const_cast<const rapidjson::Document &>(doc));
|
||||
|
||||
layers = parser.getLayers();
|
||||
|
||||
16
src/style/style_bucket.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <llmr/style/style_bucket.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
StyleBucket::StyleBucket(StyleLayerType type) {
|
||||
switch (type) {
|
||||
case StyleLayerType::Fill: render = StyleBucketFill{}; break;
|
||||
case StyleLayerType::Line: render = StyleBucketLine{}; break;
|
||||
case StyleLayerType::Icon: render = StyleBucketIcon{}; break;
|
||||
case StyleLayerType::Text: render = StyleBucketText{}; break;
|
||||
case StyleLayerType::Raster: render = StyleBucketRaster{}; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ StyleLayer::StyleLayer(const std::string &id, std::map<ClassID, ClassProperties>
|
||||
: id(id), styles(std::move(styles)), rasterize(std::move(rasterize)) {}
|
||||
|
||||
bool StyleLayer::isBackground() const {
|
||||
return id == "background";
|
||||
return type == StyleLayerType::Background && id == "background";
|
||||
}
|
||||
|
||||
void StyleLayer::setClasses(const std::vector<std::string> &class_names, const timestamp now,
|
||||
@@ -164,7 +164,6 @@ template <>
|
||||
void StyleLayer::applyStyleProperties<FillProperties>(const float z, const timestamp now) {
|
||||
properties.set<FillProperties>();
|
||||
FillProperties &fill = properties.get<FillProperties>();
|
||||
applyStyleProperty(PropertyKey::FillEnabled, fill.enabled, z, now);
|
||||
applyStyleProperty(PropertyKey::FillAntialias, fill.antialias, z, now);
|
||||
applyStyleProperty(PropertyKey::FillOpacity, fill.opacity, z, now);
|
||||
applyStyleProperty(PropertyKey::FillColor, fill.fill_color, z, now);
|
||||
@@ -179,7 +178,6 @@ template <>
|
||||
void StyleLayer::applyStyleProperties<LineProperties>(const float z, const timestamp now) {
|
||||
properties.set<LineProperties>();
|
||||
LineProperties &line = properties.get<LineProperties>();
|
||||
applyStyleProperty(PropertyKey::LineEnabled, line.enabled, z, now);
|
||||
applyStyleProperty(PropertyKey::LineOpacity, line.opacity, z, now);
|
||||
applyStyleProperty(PropertyKey::LineColor, line.color, z, now);
|
||||
applyStyleProperty(PropertyKey::LineTranslateX, line.translate[0], z, now);
|
||||
@@ -197,7 +195,6 @@ template <>
|
||||
void StyleLayer::applyStyleProperties<IconProperties>(const float z, const timestamp now) {
|
||||
properties.set<IconProperties>();
|
||||
IconProperties &icon = properties.get<IconProperties>();
|
||||
applyStyleProperty(PropertyKey::IconEnabled, icon.enabled, z, now);
|
||||
applyStyleProperty(PropertyKey::IconOpacity, icon.opacity, z, now);
|
||||
applyStyleProperty(PropertyKey::IconRotate, icon.rotate, z, now);
|
||||
applyStyleProperty(PropertyKey::IconRotateAnchor, icon.rotate_anchor, z, now);
|
||||
@@ -207,7 +204,6 @@ template <>
|
||||
void StyleLayer::applyStyleProperties<TextProperties>(const float z, const timestamp now) {
|
||||
properties.set<TextProperties>();
|
||||
TextProperties &text = properties.get<TextProperties>();
|
||||
applyStyleProperty(PropertyKey::TextEnabled, text.enabled, z, now);
|
||||
applyStyleProperty(PropertyKey::TextOpacity, text.opacity, z, now);
|
||||
applyStyleProperty(PropertyKey::TextSize, text.size, z, now);
|
||||
applyStyleProperty(PropertyKey::TextColor, text.color, z, now);
|
||||
@@ -220,7 +216,6 @@ template <>
|
||||
void StyleLayer::applyStyleProperties<CompositeProperties>(const float z, const timestamp now) {
|
||||
properties.set<CompositeProperties>();
|
||||
CompositeProperties &composite = properties.get<CompositeProperties>();
|
||||
applyStyleProperty(PropertyKey::CompositeEnabled, composite.enabled, z, now);
|
||||
applyStyleProperty(PropertyKey::CompositeOpacity, composite.opacity, z, now);
|
||||
}
|
||||
|
||||
@@ -228,7 +223,6 @@ template <>
|
||||
void StyleLayer::applyStyleProperties<RasterProperties>(const float z, const timestamp now) {
|
||||
properties.set<RasterProperties>();
|
||||
RasterProperties &raster = properties.get<RasterProperties>();
|
||||
applyStyleProperty(PropertyKey::RasterEnabled, raster.enabled, z, now);
|
||||
applyStyleProperty(PropertyKey::RasterOpacity, raster.opacity, z, now);
|
||||
applyStyleProperty(PropertyKey::RasterSpin, raster.spin, z, now);
|
||||
applyStyleProperty(PropertyKey::RasterBrightnessLow, raster.brightness[0], z, now);
|
||||
@@ -250,26 +244,17 @@ void StyleLayer::updateProperties(float z, const timestamp now) {
|
||||
layers->updateProperties(z, now);
|
||||
}
|
||||
|
||||
// Accomodate for different tile size.
|
||||
if (bucket && bucket->source) {
|
||||
z += std::log(bucket->source->tile_size / 256.0f) / M_LN2;
|
||||
}
|
||||
|
||||
cleanupAppliedStyleProperties(now);
|
||||
|
||||
if (layers) {
|
||||
applyStyleProperties<CompositeProperties>(z, now);
|
||||
} else if (bucket) {
|
||||
switch (bucket->type) {
|
||||
case BucketType::Fill: applyStyleProperties<FillProperties>(z, now); break;
|
||||
case BucketType::Line: applyStyleProperties<LineProperties>(z, now); break;
|
||||
case BucketType::Icon: applyStyleProperties<IconProperties>(z, now); break;
|
||||
case BucketType::Text: applyStyleProperties<TextProperties>(z, now); break;
|
||||
case BucketType::Raster: applyStyleProperties<RasterProperties>(z, now); break;
|
||||
default: properties.set<std::false_type>(); break;
|
||||
}
|
||||
} else {
|
||||
return applyStyleProperties<BackgroundProperties>(z, now);
|
||||
switch (type) {
|
||||
case StyleLayerType::Fill: applyStyleProperties<FillProperties>(z, now); break;
|
||||
case StyleLayerType::Line: applyStyleProperties<LineProperties>(z, now); break;
|
||||
case StyleLayerType::Icon: applyStyleProperties<IconProperties>(z, now); break;
|
||||
case StyleLayerType::Text: applyStyleProperties<TextProperties>(z, now); break;
|
||||
case StyleLayerType::Raster: applyStyleProperties<RasterProperties>(z, now); break;
|
||||
case StyleLayerType::Composite: applyStyleProperties<CompositeProperties>(z, now); break;
|
||||
case StyleLayerType::Background: applyStyleProperties<BackgroundProperties>(z, now); break;
|
||||
default: properties.set<std::false_type>(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <llmr/map/map.hpp>
|
||||
#include <llmr/style/style_parser.hpp>
|
||||
#include <llmr/style/style_layer_group.hpp>
|
||||
#include <llmr/util/constants.hpp>
|
||||
@@ -8,6 +9,10 @@ namespace llmr {
|
||||
|
||||
using JSVal = const rapidjson::Value&;
|
||||
|
||||
StyleParser::StyleParser(Map &map)
|
||||
: map(map) {
|
||||
}
|
||||
|
||||
void StyleParser::parse(JSVal document) {
|
||||
if (document.HasMember("constants")) {
|
||||
parseConstants(document["constants"]);
|
||||
@@ -165,11 +170,13 @@ void StyleParser::parseSources(JSVal value) {
|
||||
|
||||
parseRenderProperty(itr->value, type, "type", parseSourceType);
|
||||
parseRenderProperty(itr->value, url, "url");
|
||||
parseRenderProperty(itr->value, tile_size, "tileSize");
|
||||
if (type == SourceType::Raster) {
|
||||
parseRenderProperty(itr->value, tile_size, "tileSize");
|
||||
}
|
||||
parseRenderProperty(itr->value, min_zoom, "minZoom");
|
||||
parseRenderProperty(itr->value, max_zoom, "maxZoom");
|
||||
|
||||
sources.emplace(std::move(name), std::make_shared<Source>(type, url, tile_size, min_zoom, max_zoom));
|
||||
sources.emplace(std::move(name), std::make_shared<Source>(type, url, tile_size, min_zoom, max_zoom, map.getAccessToken()));
|
||||
}
|
||||
} else {
|
||||
throw Style::exception("sources must be an object");
|
||||
@@ -266,11 +273,12 @@ std::tuple<bool, Function<T>> StyleParser::parseFunction(JSVal value) {
|
||||
return std::tuple<bool, Function<T>> { false, ConstantFunction<T>(T()) };
|
||||
}
|
||||
const float z_base = parseFunctionArgument<float>(value["z"]);
|
||||
const float exp_base = value.HasMember("base") ? parseFunctionArgument<float>(value["base"]) : 1.75;
|
||||
const T val = parseFunctionArgument<T>(value["val"]);
|
||||
const float slope = value.HasMember("slope") ? parseFunctionArgument<float>(value["slope"]) : 1;
|
||||
const T min = value.HasMember("min") ? parseFunctionArgument<T>(value["min"]) : T();
|
||||
const T max = value.HasMember("max") ? parseFunctionArgument<T>(value["max"]) : T();
|
||||
return std::tuple<bool, Function<T>> { true, ExponentialFunction<T>(val, z_base, slope, min, max) };
|
||||
return std::tuple<bool, Function<T>> { true, ExponentialFunction<T>(val, z_base, exp_base, slope, min, max) };
|
||||
}
|
||||
else if (type == "stops") {
|
||||
if (!value.HasMember("stops")) {
|
||||
@@ -548,6 +556,15 @@ void StyleParser::parseLayer(std::pair<JSVal, std::shared_ptr<StyleLayer>> &pair
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.HasMember("type")) {
|
||||
JSVal type = value["type"];
|
||||
if (!type.IsString()) {
|
||||
fprintf(stderr, "[WARNING] layer type of '%s' must be a string\n", layer->id.c_str());
|
||||
} else {
|
||||
layer->type = parseStyleLayerType({ type.GetString(), type.GetStringLength() });
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we have not previously attempted to parse this layer.
|
||||
if (std::find(stack.begin(), stack.end(), layer.get()) != stack.end()) {
|
||||
fprintf(stderr, "[WARNING] layer reference of '%s' is circular\n", layer->id.c_str());
|
||||
@@ -583,8 +600,6 @@ void StyleParser::parseStyles(JSVal value, std::map<ClassID, ClassProperties> &s
|
||||
void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
|
||||
using Key = PropertyKey;
|
||||
|
||||
parseOptionalProperty<Function<bool>>("fill-enabled", Key::FillEnabled, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-fill-enabled", Key::FillEnabled, klass, value);
|
||||
parseOptionalProperty<Function<bool>>("fill-antialias", Key::FillAntialias, klass, value);
|
||||
parseOptionalProperty<Function<float>>("fill-opacity", Key::FillOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-fill-opacity", Key::FillOpacity, klass, value);
|
||||
@@ -597,8 +612,6 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<TranslateAnchorType>("fill-translate-anchor", Key::FillTranslateAnchor, klass, value);
|
||||
parseOptionalProperty<std::string>("fill-image", Key::FillImage, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<bool>>("line-enabled", Key::LineEnabled, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-line-enabled", Key::LineEnabled, klass, value);
|
||||
parseOptionalProperty<Function<float>>("line-opacity", Key::LineOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-line-opacity", Key::LineOpacity, klass, value);
|
||||
parseOptionalProperty<Function<Color>>("line-color", Key::LineColor, klass, value);
|
||||
@@ -616,15 +629,11 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<PropertyTransition>("transition-line-dasharray", Key::LineDashArray, klass, value);
|
||||
parseOptionalProperty<std::string>("line-image", Key::LineImage, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<bool>>("icon-enabled", Key::IconEnabled, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-icon-enabled", Key::IconEnabled, klass, value);
|
||||
parseOptionalProperty<Function<float>>("icon-opacity", Key::IconOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-icon-opacity", Key::IconOpacity, klass, value);
|
||||
parseOptionalProperty<Function<float>>("icon-rotate", Key::IconRotate, klass, value);
|
||||
parseOptionalProperty<RotateAnchorType>("icon-rotate-anchor", Key::IconRotateAnchor, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<bool>>("text-enabled", Key::TextEnabled, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-text-enabled", Key::TextEnabled, klass, value);
|
||||
parseOptionalProperty<Function<float>>("text-opacity", Key::TextOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-text-opacity", Key::TextOpacity, klass, value);
|
||||
parseOptionalProperty<Function<float>>("text-size", Key::TextSize, klass, value);
|
||||
@@ -638,13 +647,9 @@ void StyleParser::parseStyle(JSVal value, ClassProperties &klass) {
|
||||
parseOptionalProperty<Function<float>>("text-halo-blur", Key::TextHaloBlur, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-text-halo-blur", Key::TextHaloBlur, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<bool>>("composite-enabled", Key::CompositeEnabled, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-composite-enabled", Key::CompositeEnabled, klass, value);
|
||||
parseOptionalProperty<Function<float>>("composite-opacity", Key::CompositeOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-composite-opacity", Key::CompositeOpacity, klass, value);
|
||||
|
||||
parseOptionalProperty<Function<bool>>("raster-enabled", Key::RasterEnabled, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-raster-enabled", Key::RasterEnabled, klass, value);
|
||||
parseOptionalProperty<Function<float>>("raster-opacity", Key::RasterOpacity, klass, value);
|
||||
parseOptionalProperty<PropertyTransition>("transition-raster-opacity", Key::RasterOpacity, klass, value);
|
||||
parseOptionalProperty<Function<float>>("raster-spin", Key::RasterSpin, klass, value);
|
||||
@@ -694,20 +699,24 @@ void StyleParser::parseReference(JSVal value, std::shared_ptr<StyleLayer> &layer
|
||||
parseLayer(it->second);
|
||||
stack.pop_front();
|
||||
|
||||
|
||||
std::shared_ptr<StyleLayer> reference = it->second.second;
|
||||
|
||||
layer->type = reference->type;
|
||||
|
||||
if (reference->layers) {
|
||||
fprintf(stderr, "[WARNING] layer '%s' references composite layer\n", layer->id.c_str());
|
||||
// We cannot parse this layer further.
|
||||
return;
|
||||
} else {
|
||||
layer->bucket = reference->bucket;
|
||||
}
|
||||
|
||||
layer->bucket = reference->bucket;
|
||||
}
|
||||
|
||||
#pragma mark - Parse Bucket
|
||||
|
||||
void StyleParser::parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer) {
|
||||
layer->bucket = std::make_shared<StyleBucket>();
|
||||
layer->bucket = std::make_shared<StyleBucket>(layer->type);
|
||||
|
||||
// We name the buckets according to the layer that defined it.
|
||||
layer->bucket->name = layer->id;
|
||||
@@ -844,23 +853,14 @@ void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) {
|
||||
|
||||
StyleBucket &bucket = *layer->bucket;
|
||||
|
||||
if (value.HasMember("type")) {
|
||||
JSVal type = value["type"];
|
||||
if (type.IsString()) {
|
||||
bucket.type = parseBucketType({ type.GetString(), type.GetStringLength() });
|
||||
}
|
||||
}
|
||||
|
||||
switch (bucket.type) {
|
||||
case BucketType::Fill: {
|
||||
bucket.render = StyleBucketFill{};
|
||||
switch (layer->type) {
|
||||
case StyleLayerType::Fill: {
|
||||
StyleBucketFill &render = bucket.render.get<StyleBucketFill>();
|
||||
|
||||
parseRenderProperty(value, render.winding, "fill-winding", parseWindingType);
|
||||
} break;
|
||||
|
||||
case BucketType::Line: {
|
||||
bucket.render = StyleBucketLine{};
|
||||
case StyleLayerType::Line: {
|
||||
StyleBucketLine &render = bucket.render.get<StyleBucketLine>();
|
||||
|
||||
parseRenderProperty(value, render.cap, "line-cap", parseCapType);
|
||||
@@ -869,8 +869,7 @@ void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) {
|
||||
parseRenderProperty(value, render.round_limit, "line-round-limit");
|
||||
} break;
|
||||
|
||||
case BucketType::Icon: {
|
||||
bucket.render = StyleBucketIcon{};
|
||||
case StyleLayerType::Icon: {
|
||||
StyleBucketIcon &render = bucket.render.get<StyleBucketIcon>();
|
||||
|
||||
parseRenderProperty(value, render.size, "icon-size");
|
||||
@@ -884,8 +883,7 @@ void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) {
|
||||
parseRenderProperty(value, render.translate_anchor, "icon-translate-anchor", parseTranslateAnchorType);
|
||||
} break;
|
||||
|
||||
case BucketType::Text: {
|
||||
bucket.render = StyleBucketText{};
|
||||
case StyleLayerType::Text: {
|
||||
StyleBucketText &render = bucket.render.get<StyleBucketText>();
|
||||
|
||||
parseRenderProperty(value, render.field, "text-field");
|
||||
@@ -915,14 +913,8 @@ void StyleParser::parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer) {
|
||||
}
|
||||
parseRenderProperty(value, render.translate_anchor, "text-translate-anchor", parseTranslateAnchorType);
|
||||
} break;
|
||||
|
||||
case BucketType::Raster: {
|
||||
bucket.render = StyleBucketRaster{};
|
||||
} break;
|
||||
|
||||
default:
|
||||
layer->bucket.reset();
|
||||
fprintf(stderr, "[WARNING] bucket type of layer '%s' is invalid\n", layer->id.c_str());
|
||||
// There are no render properties for these layer types.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,28 +4,32 @@
|
||||
|
||||
namespace llmr {
|
||||
|
||||
BucketType parseBucketType(const std::string &type) {
|
||||
if (type == "fill") return BucketType::Fill;
|
||||
if (type == "line") return BucketType::Line;
|
||||
if (type == "icon") return BucketType::Icon;
|
||||
if (type == "text") return BucketType::Text;
|
||||
if (type == "raster") return BucketType::Raster;
|
||||
return BucketType::None;
|
||||
StyleLayerType parseStyleLayerType(const std::string &type) {
|
||||
if (type == "fill") return StyleLayerType::Fill;
|
||||
if (type == "line") return StyleLayerType::Line;
|
||||
if (type == "icon") return StyleLayerType::Icon;
|
||||
if (type == "text") return StyleLayerType::Text;
|
||||
if (type == "raster") return StyleLayerType::Raster;
|
||||
if (type == "composite") return StyleLayerType::Composite;
|
||||
if (type == "background") return StyleLayerType::Background;
|
||||
return StyleLayerType::Unknown;
|
||||
}
|
||||
|
||||
const char *stringifyBucketType(BucketType type) {
|
||||
const char *stringifyStyleLayerType(StyleLayerType type) {
|
||||
switch (type) {
|
||||
case BucketType::Fill: return "fill";
|
||||
case BucketType::Line: return "line";
|
||||
case BucketType::Icon: return "icon";
|
||||
case BucketType::Text: return "text";
|
||||
case BucketType::Raster: return "raster";
|
||||
default: return "none";
|
||||
case StyleLayerType::Fill: return "fill";
|
||||
case StyleLayerType::Line: return "line";
|
||||
case StyleLayerType::Icon: return "icon";
|
||||
case StyleLayerType::Text: return "text";
|
||||
case StyleLayerType::Raster: return "raster";
|
||||
case StyleLayerType::Composite: return "composite";
|
||||
case StyleLayerType::Background: return "background";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, BucketType type) {
|
||||
return os << stringifyBucketType(type);
|
||||
std::ostream& operator<<(std::ostream& os, StyleLayerType type) {
|
||||
return os << stringifyStyleLayerType(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -120,12 +120,11 @@ GlyphPBF::GlyphPBF(const std::string &glyphURL, const std::string &fontStack, Gl
|
||||
: future(promise.get_future().share())
|
||||
{
|
||||
// Load the glyph set URL
|
||||
|
||||
const std::map<std::string, std::string> tokens {{
|
||||
{ "fontstack", fontStack },
|
||||
{ "range", std::to_string(glyphRange.first) + "-" + std::to_string(glyphRange.second) }
|
||||
}};
|
||||
std::string url = util::replaceTokens(glyphURL, tokens);
|
||||
std::string url = util::replaceTokens(glyphURL, [&](const std::string &name) -> std::string {
|
||||
if (name == "fontstack") return fontStack;
|
||||
if (name == "range") return std::to_string(glyphRange.first) + "-" + std::to_string(glyphRange.second);
|
||||
return "";
|
||||
});
|
||||
|
||||
// TODO: Find more reliable URL normalization function
|
||||
std::replace(url.begin(), url.end(), ' ', '+');
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
#ifndef DISABLE_TIMER
|
||||
#include <llmr/util/timer.hpp>
|
||||
#include <llmr/util/time.hpp>
|
||||
#include <llmr/platform/log.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
|
||||
using namespace llmr::util;
|
||||
|
||||
std::atomic<int> indent;
|
||||
timer::timer(Event event)
|
||||
: event(event), start(now()) {}
|
||||
|
||||
timer::timer() : start(now()) {
|
||||
indent++;
|
||||
}
|
||||
timer::timer(EventSeverity severity, Event event)
|
||||
: severity(severity), event(event), start(now()) {}
|
||||
|
||||
timer::timer(const std::string &name) : name(name), start(now()) {
|
||||
indent++;
|
||||
}
|
||||
timer::timer(const std::string &name, Event event)
|
||||
: name(name), event(event), start(now()) {}
|
||||
|
||||
timer::timer(const std::string &name, EventSeverity severity, Event event)
|
||||
: name(name), severity(severity), event(event), start(now()) {}
|
||||
|
||||
void timer::report(const std::string &name) {
|
||||
timestamp duration = now() - start;
|
||||
std::cerr << std::string((indent - 1) * 4, ' ')
|
||||
<< name << ": "
|
||||
<< (double)(duration) / 1_millisecond
|
||||
<< "ms" << std::endl;
|
||||
|
||||
Log::Record(severity, event, name + ": " + std::to_string((double)(duration) / 1_millisecond) + "ms");
|
||||
start += duration;
|
||||
}
|
||||
|
||||
@@ -30,6 +31,5 @@ timer::~timer() {
|
||||
if (name.size()) {
|
||||
report(name);
|
||||
}
|
||||
indent--;
|
||||
}
|
||||
#endif
|
||||
|
||||
46
test/fixtures/fixture_log.cpp
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "fixture_log.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
FixtureLogBackend::~FixtureLogBackend() {
|
||||
std::cerr << unchecked();
|
||||
}
|
||||
|
||||
size_t FixtureLogBackend::count(const LogMessage &message) const {
|
||||
size_t count = 0;
|
||||
for (const LogMessage &msg : messages) {
|
||||
if (msg == message) {
|
||||
count++;
|
||||
msg.checked = true;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
std::vector<FixtureLogBackend::LogMessage> FixtureLogBackend::unchecked() const {
|
||||
std::vector<LogMessage> unchecked;
|
||||
for (const LogMessage &msg : messages) {
|
||||
if (!msg.checked) {
|
||||
unchecked.push_back(msg);
|
||||
}
|
||||
}
|
||||
return unchecked;
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const std::vector<FixtureLogBackend::LogMessage>& messages) {
|
||||
for (const FixtureLogBackend::LogMessage &message : messages) {
|
||||
os << "- " << message;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const FixtureLogBackend::LogMessage& message) {
|
||||
os << "[\"" << message.severity.get() << "\", \"" << message.event.get();
|
||||
if (message.code) os << "\", " << message.code.get();
|
||||
if (message.msg) os << ", \"" << message.msg.get();
|
||||
return os << "\"]" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
78
test/fixtures/fixture_log.hpp
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef LLMR_TEST_FIXTURE_LOG
|
||||
#define LLMR_TEST_FIXTURE_LOG
|
||||
|
||||
#include <llmr/platform/log.hpp>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class FixtureLogBackend : public LogBackend {
|
||||
public:
|
||||
struct LogMessage {
|
||||
inline LogMessage(EventSeverity severity, Event event, int64_t code, const std::string &msg)
|
||||
: severity(severity), event(event), code(code), msg(msg) {}
|
||||
inline LogMessage(EventSeverity severity, Event event, int64_t code)
|
||||
: severity(severity), event(event), code(code) {}
|
||||
inline LogMessage(EventSeverity severity, Event event, const std::string &msg)
|
||||
: severity(severity), event(event), msg(msg) {}
|
||||
inline LogMessage(EventSeverity severity, Event event)
|
||||
: severity(severity), event(event) {}
|
||||
|
||||
inline bool operator==(const LogMessage &rhs) const {
|
||||
return (!severity || !rhs.severity || severity.get() == rhs.severity.get()) &&
|
||||
(!event || !rhs.event || event.get() == rhs.event.get()) &&
|
||||
(!code || !rhs.code || code.get() == rhs.code.get()) &&
|
||||
(!msg || !rhs.msg || msg.get() == rhs.msg.get());
|
||||
}
|
||||
|
||||
const boost::optional<EventSeverity> severity;
|
||||
const boost::optional<Event> event;
|
||||
const boost::optional<int64_t> code;
|
||||
const boost::optional<std::string> msg;
|
||||
|
||||
mutable bool checked = false;
|
||||
};
|
||||
|
||||
~FixtureLogBackend();
|
||||
|
||||
void record(EventSeverity severity, Event event, const std::string &msg) {
|
||||
messages.emplace_back(severity, event, msg);
|
||||
}
|
||||
|
||||
void record(EventSeverity severity, Event event, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
const int len = vsnprintf(NULL, 0, format, args);
|
||||
va_end(args);
|
||||
std::unique_ptr<char[]> buffer(new char[len + 1]);
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer.get(), len + 1, format, args);
|
||||
va_end(args);
|
||||
messages.emplace_back(severity, event, std::string { buffer.get(), len });
|
||||
}
|
||||
|
||||
void record(EventSeverity severity, Event event, int64_t code) {
|
||||
messages.emplace_back(severity, event, code);
|
||||
}
|
||||
|
||||
void record(EventSeverity severity, Event event, int64_t code, const std::string &msg) {
|
||||
messages.emplace_back(severity, event, code, msg);
|
||||
}
|
||||
|
||||
size_t count(const LogMessage &message) const;
|
||||
std::vector<LogMessage> unchecked() const;
|
||||
|
||||
public:
|
||||
std::vector<LogMessage> messages;
|
||||
};
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const std::vector<FixtureLogBackend::LogMessage>& messages);
|
||||
::std::ostream& operator<<(::std::ostream& os, const FixtureLogBackend::LogMessage& message);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
6
test/fixtures/fixture_request.cpp
vendored
@@ -1,6 +1,7 @@
|
||||
#include <llmr/platform/platform.hpp>
|
||||
#include <llmr/platform/request.hpp>
|
||||
#include <llmr/util/uv.hpp>
|
||||
#include <llmr/platform/log.hpp>
|
||||
|
||||
const std::string base_directory = []{
|
||||
std::string fn = __FILE__;
|
||||
@@ -40,6 +41,7 @@ platform::request_http(const std::string &url,
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
Log::Warning(Event::HttpRequest, err, url + ": " + uv_strerror(err));
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
@@ -52,6 +54,7 @@ platform::request_http(const std::string &url,
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
Log::Warning(Event::HttpRequest, err, url + ": " + uv_strerror(err));
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
@@ -69,6 +72,7 @@ platform::request_http(const std::string &url,
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
Log::Warning(Event::HttpRequest, err, url + ": " + uv_strerror(err));
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
@@ -80,12 +84,14 @@ platform::request_http(const std::string &url,
|
||||
if (err < 0) {
|
||||
req->res->code = err;
|
||||
req->res->error_message = uv_strerror(err);
|
||||
Log::Warning(Event::HttpRequest, err, url + ": " + uv_strerror(err));
|
||||
req->complete();
|
||||
return req;
|
||||
}
|
||||
|
||||
req->res->body.swap(body);
|
||||
req->res->code = 200;
|
||||
Log::Info(Event::HttpRequest, 200, url);
|
||||
req->complete();
|
||||
|
||||
return req;
|
||||
|
||||
8
test/fixtures/styles/0.info.json
vendored
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"zoom": 0,
|
||||
"latitude": 0,
|
||||
"longitude": 0,
|
||||
"angle": 0,
|
||||
"width": 512,
|
||||
"height": 512
|
||||
}
|
||||
8
test/fixtures/styles/1.info.json
vendored
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"zoom": 0,
|
||||
"latitude": 0,
|
||||
"longitude": 0,
|
||||
"angle": 0,
|
||||
"width": 512,
|
||||
"height": 512
|
||||
}
|
||||
27
test/fixtures/styles/line-color.info.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"default": {
|
||||
"zoom": 14,
|
||||
"center": [52.499167, 13.418056],
|
||||
"height": 256,
|
||||
"log": [
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8803-5375.vector.pbf"],
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8802-5375.vector.pbf"],
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8803-5374.vector.pbf"],
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8802-5374.vector.pbf"],
|
||||
[4, "INFO", "HttpRequest"]
|
||||
]
|
||||
},
|
||||
"colored": {
|
||||
"zoom": 14,
|
||||
"center": [52.499167, 13.418056],
|
||||
"height": 256,
|
||||
"classes": ["colored"],
|
||||
"log": [
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8803-5375.vector.pbf"],
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8802-5375.vector.pbf"],
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8803-5374.vector.pbf"],
|
||||
[1, "INFO", "HttpRequest", 200, "tiles/14-8802-5374.vector.pbf"],
|
||||
[4, "INFO", "HttpRequest"]
|
||||
]
|
||||
}
|
||||
}
|
||||
33
test/fixtures/styles/line-color.style.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": {
|
||||
"mapbox": {
|
||||
"type": "vector",
|
||||
"url": "tiles/{z}-{x}-{y}.vector.pbf",
|
||||
"tileSize": 512,
|
||||
"maxZoom": 14
|
||||
}
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"id": "background",
|
||||
"type": "background",
|
||||
"style": {
|
||||
"background-color": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "road",
|
||||
"source": "mapbox",
|
||||
"source-layer": "road",
|
||||
"type": "line",
|
||||
"style": {
|
||||
"line-width": 2,
|
||||
"line-color": "#3590db"
|
||||
},
|
||||
"style.colored": {
|
||||
"line-color": "#222222"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
test/fixtures/styles/line-color/colored.expected.png
vendored
Normal file
|
After Width: | Height: | Size: 63 KiB |