From c2efeaf87601fb2773e9d961636d2091e6cf3fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Tue, 15 Jul 2014 17:01:00 -0700 Subject: [PATCH 01/13] do not reallocate the texture data on every update; use glTexSubImage2D instead --- src/geometry/sprite_atlas.cpp | 42 ++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index 8a055e5a6..733d587af 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -251,11 +251,13 @@ void SpriteAtlas::update(const Sprite &sprite) { } void SpriteAtlas::bind(bool linear) { + bool first = false; if (!texture) { glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + first = true; } else { glBindTexture(GL_TEXTURE_2D, texture); } @@ -270,17 +272,31 @@ void SpriteAtlas::bind(bool linear) { if (dirty) { std::lock_guard lock(mtx); allocate(); - glTexImage2D( - GL_TEXTURE_2D, // GLenum target - 0, // GLint level - GL_RGBA, // GLint internalformat - width * pixelRatio, // GLsizei width - height * pixelRatio, // GLsizei height - 0, // GLint border - GL_RGBA, // GLenum format - GL_UNSIGNED_BYTE, // GLenum type - data // const GLvoid * data - ); + + if (first) { + glTexImage2D( + GL_TEXTURE_2D, // GLenum target + 0, // GLint level + GL_RGBA, // GLint internalformat + width * pixelRatio, // GLsizei width + height * pixelRatio, // GLsizei height + 0, // GLint border + GL_RGBA, // GLenum format + GL_UNSIGNED_BYTE, // GLenum type + data // const GLvoid * data + ); + } else { + glTexSubImage2D(GL_TEXTURE_2D, // GLenum target + 0, // GLint level + 0, // GLint xoffset + 0, // GLint yoffset + width * pixelRatio, // GLsizei width + height * pixelRatio, // GLsizei height + GL_RGBA, // GLenum format + GL_UNSIGNED_BYTE, // GLenum type + data // const GLvoid *pixels + ); + } #if defined(DEBUG) // platform::show_color_debug_image("Sprite Atlas", data, width, height, width * pixelRatio, height * pixelRatio); @@ -291,6 +307,10 @@ void SpriteAtlas::bind(bool linear) { SpriteAtlas::~SpriteAtlas() { std::lock_guard lock(mtx); + + glDeleteTextures(1, &texture); + texture = 0; + if (data) { free(data); data = nullptr; From 066fa64dad2ad07da3500dc95604b7ae12544855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Tue, 15 Jul 2014 17:17:37 -0700 Subject: [PATCH 02/13] make icons work again --- src/geometry/sprite_atlas.cpp | 8 +++----- src/renderer/painter_icon.cpp | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index 733d587af..dbbbb419f 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -128,9 +128,7 @@ Rect SpriteAtlas::allocateImage(size_t width, size_t hei Rect SpriteAtlas::getIcon(const int size, const std::string &name) { std::lock_guard lock(mtx); - const std::string id = name + "-" + std::to_string(size); - - auto rect_it = images.find(id); + auto rect_it = images.find(name); if (rect_it != images.end()) { return rect_it->second; } @@ -143,7 +141,7 @@ Rect SpriteAtlas::getIcon(const int size, const std::str return rect; } - images.emplace(id, rect); + images.emplace(name, rect); allocate(); @@ -158,7 +156,7 @@ Rect SpriteAtlas::getIcon(const int size, const std::str 1.0f / size / pixelRatio ); - uninitialized.emplace(id); + uninitialized.emplace(name); dirty = true; diff --git a/src/renderer/painter_icon.cpp b/src/renderer/painter_icon.cpp index 499b124fb..29e8af396 100644 --- a/src/renderer/painter_icon.cpp +++ b/src/renderer/painter_icon.cpp @@ -23,7 +23,7 @@ void Painter::renderIcon(IconBucket& bucket, std::shared_ptr layer_d useProgram(iconShader->program); iconShader->setMatrix(matrix); // TODO: update -// iconShader->setColor(color); + iconShader->setColor({{ 1, 1, 1, 1 }}); iconShader->setImage(0); iconShader->setRatio(map.getState().getPixelRatio()); iconShader->setDimension({{ From 7810548409ee573b2d939dbed840414e09abc01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Tue, 15 Jul 2014 17:18:05 -0700 Subject: [PATCH 03/13] correctly cast buffer --- src/geometry/sprite_atlas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index dbbbb419f..2dfb792f7 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -297,7 +297,7 @@ void SpriteAtlas::bind(bool linear) { } #if defined(DEBUG) - // platform::show_color_debug_image("Sprite Atlas", data, width, height, width * pixelRatio, height * pixelRatio); + // platform::show_color_debug_image("Sprite Atlas", reinterpret_cast(data), width, height, width * pixelRatio, height * pixelRatio); #endif dirty = false; } From 682eaec87cff73e7a2c547fddea889d478e7d29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Tue, 15 Jul 2014 18:08:14 -0700 Subject: [PATCH 04/13] add icon render test --- include/llmr/map/sprite.hpp | 1 + include/llmr/platform/event.hpp | 2 ++ src/map/map.cpp | 1 + src/map/sprite.cpp | 11 +++--- src/style/filter_expression.cpp | 6 ++-- src/util/io.cpp | 4 +-- test/fixtures/fixture_log.cpp | 9 ++--- test/fixtures/styles/icons.info.json | 18 ++++++++++ test/fixtures/styles/icons.style.json | 33 ++++++++++++++++++ .../styles/icons/default.expected.png | Bin 0 -> 6538 bytes 10 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 test/fixtures/styles/icons.info.json create mode 100644 test/fixtures/styles/icons.style.json create mode 100644 test/fixtures/styles/icons/default.expected.png diff --git a/include/llmr/map/sprite.hpp b/include/llmr/map/sprite.hpp index 07f5903e5..079f0decc 100644 --- a/include/llmr/map/sprite.hpp +++ b/include/llmr/map/sprite.hpp @@ -52,6 +52,7 @@ private: private: Map ↦ + std::string url; std::string body; std::string image; std::atomic loaded; diff --git a/include/llmr/platform/event.hpp b/include/llmr/platform/event.hpp index 133cfc3c5..81b3e1d02 100644 --- a/include/llmr/platform/event.hpp +++ b/include/llmr/platform/event.hpp @@ -32,6 +32,7 @@ enum class Event : uint8_t { ParseTile, Render, HttpRequest, + Sprite, }; LLMR_DEFINE_ENUM_CLASS(EventClass, Event, { @@ -42,6 +43,7 @@ LLMR_DEFINE_ENUM_CLASS(EventClass, Event, { { Event::ParseTile, "ParseTile" }, { Event::Render, "Render" }, { Event::HttpRequest, "HttpRequest" }, + { Event::Sprite, "Sprite" }, { Event(-1), "Unknown" }, }); diff --git a/src/map/map.cpp b/src/map/map.cpp index 68db66370..4d374f1d5 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -97,6 +97,7 @@ void Map::run() { // If the map rendering wasn't started asynchronously, we perform one render // *after* all events have been processed. if (!async) { + prepare(); render(); } } diff --git a/src/map/sprite.cpp b/src/map/sprite.cpp index 4b23b120c..823d64665 100644 --- a/src/map/sprite.cpp +++ b/src/map/sprite.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,8 @@ Sprite::Sprite(Map &map, float pixelRatio) } void Sprite::load(const std::string& base_url) { + loaded = false; + url = base_url; std::shared_ptr sprite = shared_from_this(); std::string suffix = (pixelRatio > 1 ? "@2x" : ""); @@ -53,12 +56,12 @@ void Sprite::load(const std::string& base_url) { } void Sprite::complete(std::shared_ptr &sprite) { - if (sprite->raster && sprite->pos.size()) { + const bool raster = bool(sprite->raster); + const bool json = bool(sprite->pos.size()); + if (raster && json && !sprite->loaded) { sprite->loaded = true; sprite->map.update(); -#if defined(DEBUG) - fprintf(stderr, "sprite loaded\n"); -#endif + Log::Info(Event::Sprite, "loaded %s", sprite->url.c_str()); } } diff --git a/src/style/filter_expression.cpp b/src/style/filter_expression.cpp index 58483acca..cba7e21f1 100644 --- a/src/style/filter_expression.cpp +++ b/src/style/filter_expression.cpp @@ -61,11 +61,11 @@ bool FilterComparison::Instance::compare(const std::forward_list &propert switch (op) { case Operator::Equal: for (const Value &property_value : property_values) { - if (!includes(property_value, util::relaxed_equal)) { - return false; + if (includes(property_value, util::relaxed_equal)) { + return true; } } - return true; + return false; case Operator::NotEqual: for (const Value &property_value : property_values) { if (includes(property_value, util::relaxed_equal)) { diff --git a/src/util/io.cpp b/src/util/io.cpp index 1312b907b..2fd638cdf 100644 --- a/src/util/io.cpp +++ b/src/util/io.cpp @@ -15,7 +15,7 @@ void write_file(const std::string &filename, const std::string &data) { fwrite(data.data(), sizeof(std::string::value_type), data.size(), fd); fclose(fd); } else { - fprintf(stderr, "Failed to open file\n"); + throw std::runtime_error(std::string("Failed to open file ") + filename); } } @@ -26,7 +26,7 @@ std::string read_file(const std::string &filename) { data << file.rdbuf(); return data.str(); } else { - throw std::runtime_error("Cannot read file " + filename); + throw std::runtime_error(std::string("Cannot read file ") + filename); } } diff --git a/test/fixtures/fixture_log.cpp b/test/fixtures/fixture_log.cpp index 159f927e2..9253f5f98 100644 --- a/test/fixtures/fixture_log.cpp +++ b/test/fixtures/fixture_log.cpp @@ -24,6 +24,7 @@ std::vector FixtureLogBackend::unchecked() const for (const LogMessage &msg : messages) { if (!msg.checked) { unchecked.push_back(msg); + msg.checked = true; } } return unchecked; @@ -37,10 +38,10 @@ std::vector FixtureLogBackend::unchecked() const } ::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; + 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; } } \ No newline at end of file diff --git a/test/fixtures/styles/icons.info.json b/test/fixtures/styles/icons.info.json new file mode 100644 index 000000000..e116913aa --- /dev/null +++ b/test/fixtures/styles/icons.info.json @@ -0,0 +1,18 @@ +{ + "default": { + "zoom": 14, + "center": [52.499167, 13.418056], + "height": 256, + "log": [ + [1, "INFO", "HttpRequest", 200, "sprites/outdoors.json"], + [1, "INFO", "HttpRequest", 200, "sprites/outdoors.png"], + [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"], + [6, "INFO", "HttpRequest"], + + [1, "INFO", "Sprite", "loaded sprites/outdoors"] + ] + } +} diff --git a/test/fixtures/styles/icons.style.json b/test/fixtures/styles/icons.style.json new file mode 100644 index 000000000..46adfbd40 --- /dev/null +++ b/test/fixtures/styles/icons.style.json @@ -0,0 +1,33 @@ +{ + "version": 3, + "sources": { + "mapbox": { + "type": "vector", + "url": "tiles/{z}-{x}-{y}.vector.pbf", + "tileSize": 512, + "maxZoom": 14 + } + }, + "sprite": "sprites/outdoors", + "layers": [ + { + "id": "background", + "type": "background", + "style": { + "background-color": "green" + } + }, + { + "id": "poi", + "source": "mapbox", + "source-layer": "poi_label", + "type": "icon", + "filter": { "maki": "restaurant" }, + "render": { + "icon-image": "{maki}-12", + "icon-size": 12, + "icon-allow-overlap": true + } + } + ] +} diff --git a/test/fixtures/styles/icons/default.expected.png b/test/fixtures/styles/icons/default.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..17e3252c888b78f796adf891fe3d5cb7b8bf88c8 GIT binary patch literal 6538 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 literal 0 HcmV?d00001 From 1f06f518b2ad089abd27f9e2c2fa28486fd6e4de Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Tue, 15 Jul 2014 18:48:01 -0700 Subject: [PATCH 05/13] allow for delayed map notifications during animations --- common/glfw_view.cpp | 4 +++- common/headless_view.cpp | 3 ++- include/llmr/platform/platform.hpp | 4 +++- ios/mapbox-gl-cocoa | 2 +- src/map/transform.cpp | 9 ++++++--- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/common/glfw_view.cpp b/common/glfw_view.cpp index d4f896914..0d26928e0 100644 --- a/common/glfw_view.cpp +++ b/common/glfw_view.cpp @@ -1,5 +1,7 @@ #include "glfw_view.hpp" +#include + GLFWView::GLFWView(bool fullscreen) : fullscreen(fullscreen) { #ifdef NVIDIA glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)glfwGetProcAddress("glDiscardFramebufferEXT"); @@ -281,7 +283,7 @@ void show_color_debug_image(std::string name, const char *data, size_t logical_w } #endif -void notify_map_change(MapChange change) { +void notify_map_change(MapChange change, timestamp delay) { // no-op } diff --git a/common/headless_view.cpp b/common/headless_view.cpp index a44c6e6ed..2ca804664 100644 --- a/common/headless_view.cpp +++ b/common/headless_view.cpp @@ -1,4 +1,5 @@ #include "headless_view.hpp" +#include #include #include @@ -6,7 +7,7 @@ namespace llmr { namespace platform { -void notify_map_change(MapChange change) { +void notify_map_change(MapChange change, timestamp delay) { // no-op } diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp index 138843fee..540f22619 100644 --- a/include/llmr/platform/platform.hpp +++ b/include/llmr/platform/platform.hpp @@ -1,6 +1,8 @@ #ifndef LLMR_PLATFORM_PLATFORM #define LLMR_PLATFORM_PLATFORM +#include + #include #include #include @@ -49,7 +51,7 @@ std::shared_ptr request_http(const std::string &url, void cancel_request_http(const std::shared_ptr &req); // Notifies a watcher of map changes. -void notify_map_change(MapChange key); +void notify_map_change(MapChange key, timestamp delay = 0); // Shows an alpha image with the specified dimensions in a named window. void show_debug_image(std::string name, const char *data, size_t width, size_t height); diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa index 9d403d2ce..fcb1de181 160000 --- a/ios/mapbox-gl-cocoa +++ b/ios/mapbox-gl-cocoa @@ -1 +1 @@ -Subproject commit 9d403d2cefcd63797a3da2c67d4b653e287aeec5 +Subproject commit fcb1de1812fcf460712c210bdbfe9372ce341e34 diff --git a/src/map/transform.cpp b/src/map/transform.cpp index eb9aef69e..46ddc237c 100644 --- a/src/map/transform.cpp +++ b/src/map/transform.cpp @@ -86,7 +86,8 @@ void Transform::_moveBy(const double dx, const double dy, const timestamp durati platform::notify_map_change(duration ? platform::MapChangeRegionDidChangeAnimated : - platform::MapChangeRegionDidChange); + platform::MapChangeRegionDidChange, + duration); } void Transform::setLonLat(const double lon, const double lat, const timestamp duration) { @@ -310,7 +311,8 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl platform::notify_map_change(duration ? platform::MapChangeRegionDidChangeAnimated : - platform::MapChangeRegionDidChange); + platform::MapChangeRegionDidChange, + duration); } #pragma mark - Constraints @@ -410,7 +412,8 @@ void Transform::_setAngle(double new_angle, const timestamp duration) { platform::notify_map_change(duration ? platform::MapChangeRegionDidChangeAnimated : - platform::MapChangeRegionDidChange); + platform::MapChangeRegionDidChange, + duration); } double Transform::getAngle() const { From 17b1c6fd414c997720765e96008cddfa3ba1c607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 16 Jul 2014 14:38:46 -0700 Subject: [PATCH 06/13] update value semanatics to be closer to js and add filter expression tests --- include/llmr/style/filter_expression.hpp | 6 +- .../llmr/style/filter_expression_private.hpp | 87 ++++++++ include/llmr/style/value.hpp | 130 ++---------- include/llmr/style/value_comparison.hpp | 100 +++++++++ src/style/filter_expression.cpp | 87 +------- test/expressions.cpp | 130 ++++++++++++ test/test.gyp | 17 ++ test/variant.cpp | 199 +++++++++++++----- 8 files changed, 500 insertions(+), 256 deletions(-) create mode 100644 include/llmr/style/filter_expression_private.hpp create mode 100644 include/llmr/style/value_comparison.hpp create mode 100644 test/expressions.cpp diff --git a/include/llmr/style/filter_expression.hpp b/include/llmr/style/filter_expression.hpp index 5c7a400d8..61e0fae3c 100644 --- a/include/llmr/style/filter_expression.hpp +++ b/include/llmr/style/filter_expression.hpp @@ -11,8 +11,6 @@ namespace llmr { -class VectorTileTagExtractor; - class FilterComparison { public: enum class Operator : uint8_t { @@ -50,7 +48,7 @@ public: FilterComparison(const std::string &field) : field(field) {}; const std::string &getField() const; - inline bool compare(const VectorTileTagExtractor &extractor) const; + template inline bool compare(const Extractor &extractor) const; template inline void add(Args&& ...args) { @@ -95,7 +93,7 @@ public: bool empty() const; - bool compare(const VectorTileTagExtractor &extractor) const; + template bool compare(const Extractor &extractor) const; void add(const FilterComparison &comparison); void add(const FilterExpression &expression); void setGeometryType(GeometryType g); diff --git a/include/llmr/style/filter_expression_private.hpp b/include/llmr/style/filter_expression_private.hpp new file mode 100644 index 000000000..9a1f9fed3 --- /dev/null +++ b/include/llmr/style/filter_expression_private.hpp @@ -0,0 +1,87 @@ +#ifndef LLMR_STYLE_FILTER_EXPRESSION_PRIVATE +#define LLMR_STYLE_FILTER_EXPRESSION_PRIVATE + +#include "filter_expression.hpp" + +namespace llmr { + +template +inline bool FilterComparison::compare(const Extractor &extractor) const { + const std::forward_list values = extractor.getValues(field); + + // All instances are ANDed together. + for (const Instance &instance : instances) { + if (!instance.compare(values)) { + return false; + } + } + return true; +} + +template +bool FilterExpression::compare(const Extractor &extractor) const { + if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) { + return false; + } + + switch (op) { + case Operator::And: + for (const FilterComparison &comparison : comparisons) { + if (!comparison.compare(extractor)) { + return false; + } + } + for (const FilterExpression &expression: expressions) { + if (!expression.compare(extractor)) { + return false; + } + } + return true; + case Operator::Or: + for (const FilterComparison &comparison : comparisons) { + if (comparison.compare(extractor)) { + return true; + } + } + for (const FilterExpression &expression: expressions) { + if (expression.compare(extractor)) { + return true; + } + } + return false; + case Operator::Xor: { + int count = 0; + for (const FilterComparison &comparison : comparisons) { + count += comparison.compare(extractor); + if (count > 1) { + return false; + } + } + for (const FilterExpression &expression: expressions) { + count += expression.compare(extractor); + if (count > 1) { + return false; + } + } + return count == 1; + } + case Operator::Nor: + for (const FilterComparison &comparison : comparisons) { + if (comparison.compare(extractor)) { + return false; + } + } + for (const FilterExpression &expression: expressions) { + if (expression.compare(extractor)) { + return false; + } + } + return true; + default: + return true; + } +} + +} + +#endif diff --git a/include/llmr/style/value.hpp b/include/llmr/style/value.hpp index fac316d3d..ed14c233e 100644 --- a/include/llmr/style/value.hpp +++ b/include/llmr/style/value.hpp @@ -4,6 +4,9 @@ #include #include +#include +#include + namespace llmr { typedef util::variant Value; @@ -13,128 +16,21 @@ std::string toString(const Value &value); Value parseValue(pbf data); namespace util { - -namespace detail { - -inline int string_to_bool(std::string str) { - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - if (str == "0" || str == "0.0" || str == "false" || str == "null" || !str.length()) return 0; - else if (str == "true") return 1; - else return -1; +inline bool parseNumericString(const std::string &str, double &result) { + char *end = nullptr; + const char *begin = str.c_str(); + result = std::strtod(begin, &end); + while (*end != '\0' && isspace(*end)) end++; // eat whitespace after the end + return errno == 0 && end - begin == long(str.size()); } - -template -struct string_to_number {}; - -template <> struct string_to_number { - bool operator()(const std::string &str) const { - // Converts 0 => false, 1 => true and -1 => true. - return string_to_bool(str); - } -}; - -template <> struct string_to_number { - double operator()(std::string const &str) const { - int val = string_to_bool(str); - return val < 0 ? std::stod(str) : val; - } -}; - -template <> struct string_to_number { - int64_t operator()(std::string const &str) const { - int val = string_to_bool(str); - return val < 0 ? std::stoll(str) : val; - } -}; - -template <> struct string_to_number { - uint64_t operator()(std::string const &str) const { - int val = string_to_bool(str); - return val < 0 ? std::stoull(str) : val; - } -}; - -template -struct relaxed_operator_visitor { - typedef bool result_type; - - bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); } - - template ::value>::type> - bool operator()(bool lhs, T rhs) const { return Operator()(lhs, bool(rhs)); } - - template ::value>::type> - bool operator()(T lhs, bool rhs) const { return Operator()(bool(lhs), rhs); } - - bool operator()(int64_t lhs, uint64_t rhs) const { return lhs < 0 ? false : Operator()(uint64_t(lhs), rhs); } - bool operator()(uint64_t lhs, int64_t rhs) const { return rhs < 0 ? false : Operator()(lhs, uint64_t(rhs)); } - - template ::value>::type> - bool operator()(const std::string &lhs, T rhs) const try { return Operator()(string_to_number()(lhs), rhs); } - catch(...) { return false; } - - template ::value>::type> - bool operator()(T lhs, const std::string &rhs) const try { return Operator()(lhs, string_to_number()(rhs)); } - catch(...) { return false; } - - template - bool operator()(T0 lhs, T1 rhs) const { return Operator()(lhs, rhs); } -}; - -struct relaxed_equal_operator { - template - bool operator()(T0 lhs, T1 rhs) const { return lhs == rhs; } -}; - -struct relaxed_greater_operator { - template - bool operator()(T0 lhs, T1 rhs) const { return lhs > rhs; } -}; - -struct relaxed_greater_equal_operator { - template - bool operator()(T0 lhs, T1 rhs) const { return lhs >= rhs; } -}; - -struct relaxed_less_operator { - template - bool operator()(T0 lhs, T1 rhs) const { return lhs < rhs; } -}; - -struct relaxed_less_equal_operator { - template - bool operator()(T0 lhs, T1 rhs) const { return lhs <= rhs; } -}; - - -} // end namespace detail - -inline bool relaxed_equal(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); } -inline bool relaxed_greater(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); -} - -inline bool relaxed_greater_equal(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); -} - -inline bool relaxed_less(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); -} - -inline bool relaxed_less_equal(Value const &lhs, Value const &rhs) { - return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); -} - -} - - template T toNumber(const Value &value) { - if (value.is()) return util::detail::string_to_number()(value.get()); + if (value.is()) { + double val; + return util::parseNumericString(value.get(), val) ? val : 0; + } else if (value.is()) return value.get(); else if (value.is()) return value.get(); else if (value.is()) return value.get(); diff --git a/include/llmr/style/value_comparison.hpp b/include/llmr/style/value_comparison.hpp new file mode 100644 index 000000000..d69142bc5 --- /dev/null +++ b/include/llmr/style/value_comparison.hpp @@ -0,0 +1,100 @@ +#ifndef LLMR_STYLE_VALUE_COMPARISON +#define LLMR_STYLE_VALUE_COMPARISON + +#include "value.hpp" +#include +#include + +namespace llmr { + +namespace util { + +namespace detail { + +template +struct relaxed_operator_visitor { + typedef bool result_type; + + inline bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); } + + template ::value>::type> + inline bool operator()(bool lhs, T rhs) const { return Operator()(T(lhs), rhs); } + + template ::value>::type> + inline bool operator()(T lhs, bool rhs) const { return Operator()(lhs, T(rhs)); } + + inline bool operator()(int64_t lhs, uint64_t rhs) const { + return lhs < 0 ? false : Operator()(uint64_t(lhs), rhs); + } + inline bool operator()(uint64_t lhs, int64_t rhs) const { + return rhs < 0 ? false : Operator()(lhs, uint64_t(rhs)); + } + + template ::value>::type> + inline bool operator()(const std::string &lhs, T rhs) const { + double value; + return parseNumericString(lhs, value) ? Operator()(value, double(rhs)) : false; + } + + template ::value>::type> + inline bool operator()(T lhs, const std::string &rhs) const { + double value; + return parseNumericString(rhs, value) ? Operator()(double(lhs), value) : false; + } + + template + inline bool operator()(T0 lhs, T1 rhs) const { return Operator()(lhs, rhs); } +}; + +struct relaxed_equal_operator { + template + inline bool operator()(T0 lhs, T1 rhs) const { return lhs == rhs; } +}; + +struct relaxed_greater_operator { + template + inline bool operator()(T0 lhs, T1 rhs) const { return lhs > rhs; } +}; + +struct relaxed_greater_equal_operator { + template + inline bool operator()(T0 lhs, T1 rhs) const { return lhs >= rhs; } +}; + +struct relaxed_less_operator { + template + inline bool operator()(T0 lhs, T1 rhs) const { return lhs < rhs; } +}; + +struct relaxed_less_equal_operator { + template + inline bool operator()(T0 lhs, T1 rhs) const { return lhs <= rhs; } +}; + +} // end namespace detail + +inline bool relaxed_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); +} + +inline bool relaxed_greater(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); +} + +inline bool relaxed_greater_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); +} + +inline bool relaxed_less(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); +} + +inline bool relaxed_less_equal(Value const &lhs, Value const &rhs) { + return apply_visitor(detail::relaxed_operator_visitor(), lhs, rhs); +} + +} + +} + +#endif diff --git a/src/style/filter_expression.cpp b/src/style/filter_expression.cpp index cba7e21f1..38bb74272 100644 --- a/src/style/filter_expression.cpp +++ b/src/style/filter_expression.cpp @@ -1,6 +1,8 @@ -#include +#include #include +#include + namespace llmr { @@ -105,20 +107,6 @@ const std::string &FilterComparison::getField() const { return field; } -inline bool FilterComparison::compare(const VectorTileTagExtractor &extractor) const { - const std::forward_list values = extractor.getValues(field); - - // All instances are ANDed together. - for (const Instance &instance : instances) { - if (!instance.compare(values)) { - return false; - } - } - return true; -} - - - std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison) { s << "comparison" << std::endl; for (const FilterComparison::Instance &instance : comparison.instances) { @@ -183,71 +171,6 @@ std::ostream& operator <<(std::ostream &s, FilterExpression::GeometryType type) return s; } - - -bool FilterExpression::compare(const VectorTileTagExtractor &extractor) const { - if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) { - return false; - } - - switch (op) { - case Operator::And: - for (const FilterComparison &comparison : comparisons) { - if (!comparison.compare(extractor)) { - return false; - } - } - for (const FilterExpression &expression: expressions) { - if (!expression.compare(extractor)) { - return false; - } - } - return true; - case Operator::Or: - for (const FilterComparison &comparison : comparisons) { - if (comparison.compare(extractor)) { - return true; - } - } - for (const FilterExpression &expression: expressions) { - if (expression.compare(extractor)) { - return true; - } - } - return false; - case Operator::Xor: { - int count = 0; - for (const FilterComparison &comparison : comparisons) { - count += comparison.compare(extractor); - if (count > 1) { - return false; - } - } - for (const FilterExpression &expression: expressions) { - count += expression.compare(extractor); - if (count > 1) { - return false; - } - } - return count == 1; - } - case Operator::Nor: - for (const FilterComparison &comparison : comparisons) { - if (comparison.compare(extractor)) { - return false; - } - } - for (const FilterExpression &expression: expressions) { - if (expression.compare(extractor)) { - return false; - } - } - return true; - default: - return true; - } -} - bool FilterExpression::empty() const { return type == GeometryType::Any && comparisons.empty() && expressions.empty(); } @@ -281,4 +204,8 @@ std::ostream& operator <<(std::ostream &s, const FilterExpression &expression) { return s; } +// Explicit instantiation +template bool FilterComparison::compare(const VectorTileTagExtractor &extractor) const; +template bool FilterExpression::compare(const VectorTileTagExtractor &extractor) const; + } diff --git a/test/expressions.cpp b/test/expressions.cpp new file mode 100644 index 000000000..dc28f16ee --- /dev/null +++ b/test/expressions.cpp @@ -0,0 +1,130 @@ +#include +#include "gtest/gtest.h" + +#include +#include + +#include + + + +class MockExtractor { +public: + MockExtractor(const std::multimap &values) : values(values) {} + MockExtractor() {} + + inline std::forward_list getValues(const std::string &key) const { + std::forward_list result; + auto rit = result.before_begin(); + // Find all values with the requested key. + const auto ret = values.equal_range(key); + for (auto it = ret.first; it != ret.second; it++) { + // Append the newly found value to the forward list. + rit = result.emplace_after(rit, it->second); + } + return result; + } + +private: + const std::multimap values; +}; + + +TEST(FilterComparison, SingleStringValue) { + using namespace llmr; + + FilterComparison comparison("test"); + comparison.add(FilterComparison::Operator::Equal, std::forward_list { std::string("bar") }); + // comparison is { "test": { "==": "bar" } } + + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("booz") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", std::string("bar") }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }}))); + ASSERT_FALSE(comparison.compare(MockExtractor())); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("barst") }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); +} + + +TEST(FilterComparison, SingleDoubleValue) { + using namespace llmr; + + FilterComparison comparison("test"); + comparison.add(FilterComparison::Operator::Equal, std::forward_list { double(32.8) }); + // comparison is { "test": { "==": 32.8 } } + + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("32.8") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }, { "test", std::string("booz") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", double(32.8) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", double(32.8) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor())); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.9) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); +} + +TEST(FilterComparison, SingleUintValue) { + using namespace llmr; + + FilterComparison comparison("test"); + comparison.add(FilterComparison::Operator::Equal, std::forward_list { uint64_t(42) }); + // comparison is { "test": { "==": 42 } } + + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(42) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(42) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("42") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }, { "test", std::string("booz") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", uint64_t(42) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", uint64_t(42) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor())); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(43) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); +} + +TEST(FilterComparison, SingleIntValue) { + using namespace llmr; + + FilterComparison comparison("test"); + comparison.add(FilterComparison::Operator::Equal, std::forward_list { int64_t(-42) }); + // comparison is { "test": { "==": -42 } } + + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(-42) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("-42") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }, { "test", std::string("booz") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", int64_t(-42) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", int64_t(-42) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor())); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-43) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(-43) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(-42) }}))); +} + +TEST(FilterComparison, SingleBoolValue) { + using namespace llmr; + + FilterComparison comparison("test"); + comparison.add(FilterComparison::Operator::Equal, std::forward_list { bool(true) }); + // comparison is { "test": { "==": 32.8 } } + + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(1) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(1) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(1) }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("1") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }, { "test", std::string("booz") }}))); + ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", bool(true) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", bool(true) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor())); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }}))); + ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }}))); +} diff --git a/test/test.gyp b/test/test.gyp index 95f22c257..0f065a5be 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -122,6 +122,22 @@ "../llmr.gyp:llmr-x86" ] }, + { + "target_name": "expressions", + "product_name": "test_expressions", + "type": "executable", + "libraries": [ + "-lpthread", + ], + "sources": [ + "./main.cpp", + "./expressions.cpp", + ], + "dependencies": [ + "../deps/gtest/gtest.gyp:gtest", + "../llmr.gyp:llmr-x86" + ] + }, { "target_name": "tile", "product_name": "test_tile", @@ -188,6 +204,7 @@ "tile", "functions", "headless", + "expressions", ], } ] diff --git a/test/variant.cpp b/test/variant.cpp index 9b0de9f3a..fd2785369 100644 --- a/test/variant.cpp +++ b/test/variant.cpp @@ -2,6 +2,7 @@ #include "gtest/gtest.h" #include +#include #pragma GCC diagnostic push #ifndef __clang__ @@ -24,40 +25,117 @@ TEST(Variant, toString) { } +TEST(Variant, RelaxedEqualityStringToBool) { + // 1-ish values are true + EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string("1.0"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 1"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 0x1"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 0X1"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 1.0"), bool(true))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 1 "), bool(true))); + + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1"))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1.0"))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1"))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0x1"))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0X1"))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1.0"))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1 "))); + + // 0-ish values are false + EXPECT_TRUE(util::relaxed_equal(std::string("0"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("0.0"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 0"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 0x0"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 0X0"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 0.0"), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(" 0 "), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string(" "), bool(false))); + + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0.0"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0x0"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0X0"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0.0"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0 "))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(""))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" "))); + + + // other string values are neither true nor false + EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(true))); + + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" 1.0 g"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("foo"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inf "))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inFINITY "))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" nan "))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" NAN "))); + + + EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(false))); + + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" 1.0 g"))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("foo"))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inf "))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inFINITY "))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" nan "))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" NAN "))); +} + TEST(Variant, RelaxedEquality) { // Compare to bool - EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(386))); - EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(-7042))); - EXPECT_TRUE(util::relaxed_equal(bool(false), int64_t(0))); - EXPECT_TRUE(util::relaxed_equal(bool(true), uint64_t(386))); - EXPECT_TRUE(util::relaxed_equal(bool(false), uint64_t(0))); - EXPECT_TRUE(util::relaxed_equal(bool(true), double(386))); - EXPECT_TRUE(util::relaxed_equal(bool(false), double(0))); - EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("386"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(""))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("false"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("False"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("null"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("nuLL"))); - EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("NULL"))); - EXPECT_TRUE(util::relaxed_equal(bool(true), bool(true))); EXPECT_TRUE(util::relaxed_equal(bool(false), bool(false))); + EXPECT_TRUE(util::relaxed_equal(bool(false), int64_t(0))); + EXPECT_TRUE(util::relaxed_equal(bool(false), uint64_t(0))); + EXPECT_TRUE(util::relaxed_equal(bool(false), double(0))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0"))); + EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(""))); + + EXPECT_TRUE(util::relaxed_equal(bool(true), bool(true))); + EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(1))); + EXPECT_TRUE(util::relaxed_equal(bool(true), uint64_t(1))); + EXPECT_TRUE(util::relaxed_equal(bool(true), double(1))); + EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1"))); + - EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(0))); - EXPECT_FALSE(util::relaxed_equal(bool(true), uint64_t(0))); - EXPECT_FALSE(util::relaxed_equal(bool(true), double(0))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(""))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("false"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("FALSE"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("null"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("Null"))); - EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(-754))); - EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(3))); - EXPECT_FALSE(util::relaxed_equal(bool(false), double(3.145))); - EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("test"))); - EXPECT_FALSE(util::relaxed_equal(bool(true), bool(false))); EXPECT_FALSE(util::relaxed_equal(bool(false), bool(true))); + EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(386))); + EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(-7042))); + EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(386))); + EXPECT_FALSE(util::relaxed_equal(bool(false), double(3.145))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("386"))); + EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("test"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), bool(false))); + EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(386))); + EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(-7042))); + EXPECT_FALSE(util::relaxed_equal(bool(true), uint64_t(386))); + EXPECT_FALSE(util::relaxed_equal(bool(true), double(3.145))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("386"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("test"))); + EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(""))); // Compare to int64_t EXPECT_TRUE(util::relaxed_equal(int64_t(386), int64_t(386))); @@ -67,8 +145,6 @@ TEST(Variant, RelaxedEquality) { EXPECT_TRUE(util::relaxed_equal(int64_t(386), std::string("386"))); EXPECT_TRUE(util::relaxed_equal(int64_t(1), bool(true))); EXPECT_TRUE(util::relaxed_equal(int64_t(0), bool(false))); - EXPECT_TRUE(util::relaxed_equal(int64_t(1), std::string("true"))); - EXPECT_TRUE(util::relaxed_equal(int64_t(0), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(int64_t(386), int64_t(387))); EXPECT_FALSE(util::relaxed_equal(int64_t(-7042), int64_t(-7043))); @@ -77,6 +153,8 @@ TEST(Variant, RelaxedEquality) { EXPECT_FALSE(util::relaxed_equal(int64_t(386), std::string("387"))); EXPECT_FALSE(util::relaxed_equal(int64_t(1), bool(false))); EXPECT_FALSE(util::relaxed_equal(int64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_equal(int64_t(1), std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(int64_t(0), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(int64_t(1), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(int64_t(0), std::string("true"))); @@ -89,8 +167,6 @@ TEST(Variant, RelaxedEquality) { EXPECT_TRUE(util::relaxed_equal(uint64_t(386), std::string("386"))); EXPECT_TRUE(util::relaxed_equal(uint64_t(1), bool(true))); EXPECT_TRUE(util::relaxed_equal(uint64_t(0), bool(false))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(1), std::string("true"))); - EXPECT_TRUE(util::relaxed_equal(uint64_t(0), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(uint64_t(386), int64_t(387))); EXPECT_FALSE(util::relaxed_equal(uint64_t(386), uint64_t(387))); @@ -99,6 +175,8 @@ TEST(Variant, RelaxedEquality) { EXPECT_FALSE(util::relaxed_equal(uint64_t(386), std::string("387"))); EXPECT_FALSE(util::relaxed_equal(uint64_t(1), bool(false))); EXPECT_FALSE(util::relaxed_equal(uint64_t(0), bool(true))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(1), std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(uint64_t(0), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(uint64_t(1), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(uint64_t(0), std::string("true"))); @@ -112,12 +190,6 @@ TEST(Variant, RelaxedEquality) { EXPECT_TRUE(util::relaxed_equal(double(386), std::string("386"))); EXPECT_TRUE(util::relaxed_equal(double(1), bool(true))); EXPECT_TRUE(util::relaxed_equal(double(0), bool(false))); - EXPECT_TRUE(util::relaxed_equal(double(1), std::string("true"))); - EXPECT_TRUE(util::relaxed_equal(double(1), std::string("TRue"))); - EXPECT_TRUE(util::relaxed_equal(double(0), std::string("false"))); - EXPECT_TRUE(util::relaxed_equal(double(0), std::string("FALSe"))); - EXPECT_TRUE(util::relaxed_equal(double(0), std::string("null"))); - EXPECT_TRUE(util::relaxed_equal(double(0), std::string("Null"))); EXPECT_FALSE(util::relaxed_equal(double(3.159385), double(3.159383))); EXPECT_FALSE(util::relaxed_equal(double(386), int64_t(387))); @@ -127,6 +199,12 @@ TEST(Variant, RelaxedEquality) { EXPECT_FALSE(util::relaxed_equal(double(386), std::string("387"))); EXPECT_FALSE(util::relaxed_equal(double(1), bool(false))); EXPECT_FALSE(util::relaxed_equal(double(0), bool(true))); + EXPECT_FALSE(util::relaxed_equal(double(1), std::string("true"))); + EXPECT_FALSE(util::relaxed_equal(double(1), std::string("TRue"))); + EXPECT_FALSE(util::relaxed_equal(double(0), std::string("false"))); + EXPECT_FALSE(util::relaxed_equal(double(0), std::string("FALSe"))); + EXPECT_FALSE(util::relaxed_equal(double(0), std::string("null"))); + EXPECT_FALSE(util::relaxed_equal(double(0), std::string("Null"))); EXPECT_FALSE(util::relaxed_equal(double(1), std::string("false"))); EXPECT_FALSE(util::relaxed_equal(double(1), std::string("False"))); EXPECT_FALSE(util::relaxed_equal(double(1), std::string("null"))); @@ -141,20 +219,21 @@ TEST(Variant, RelaxedEquality) { EXPECT_TRUE(util::relaxed_equal(std::string("-386"), int64_t(-386))); EXPECT_TRUE(util::relaxed_equal(std::string("386"), uint64_t(386))); EXPECT_TRUE(util::relaxed_equal(std::string("386.36"), double(386.36))); - EXPECT_TRUE(util::relaxed_equal(std::string("true"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string("True"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string("some string"), bool(true))); - EXPECT_TRUE(util::relaxed_equal(std::string("false"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("fAlse"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("null"), bool(false))); - EXPECT_TRUE(util::relaxed_equal(std::string("NULl"), bool(false))); EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false))); + EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true))); EXPECT_FALSE(util::relaxed_equal(std::string("lord"), std::string("baron"))); EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(387))); EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-387))); EXPECT_FALSE(util::relaxed_equal(std::string("386"), uint64_t(387))); EXPECT_FALSE(util::relaxed_equal(std::string("386.36"), double(386.37))); + EXPECT_FALSE(util::relaxed_equal(std::string("some string"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("True"), bool(true))); + EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("fAlse"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("null"), bool(false))); + EXPECT_FALSE(util::relaxed_equal(std::string("NULl"), bool(false))); EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(false))); EXPECT_FALSE(util::relaxed_equal(std::string("TRUE"), bool(false))); EXPECT_FALSE(util::relaxed_equal(std::string("some string"), bool(false))); @@ -190,11 +269,23 @@ TEST(Variant, RelaxedGreater) { EXPECT_TRUE(util::relaxed_greater(double(387), double(386.7))); EXPECT_TRUE(util::relaxed_greater(bool(true), double(0))); + EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(true))); EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(false))); EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(false))); EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(false))); EXPECT_TRUE(util::relaxed_greater(double(387), bool(false))); - EXPECT_TRUE(util::relaxed_greater(bool(true), double(false))); + EXPECT_TRUE(util::relaxed_greater(double(387), bool(false))); + EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(true))); + EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(true))); + EXPECT_TRUE(util::relaxed_greater(double(387), bool(true))); + EXPECT_TRUE(util::relaxed_greater(double(387), bool(true))); + + EXPECT_TRUE(util::relaxed_greater(bool(true), double(0))); + EXPECT_TRUE(util::relaxed_greater(bool(true), double(0.5))); + EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false))); + EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0))); + EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0))); + EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false))); @@ -222,12 +313,8 @@ TEST(Variant, RelaxedGreater) { EXPECT_FALSE(util::relaxed_greater(int64_t(387), double(388.7))); EXPECT_FALSE(util::relaxed_greater(double(387), double(388.7))); EXPECT_FALSE(util::relaxed_greater(bool(true), double(388))); - - EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(true))); - EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(true))); - EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(true))); - EXPECT_FALSE(util::relaxed_greater(double(387), bool(true))); EXPECT_FALSE(util::relaxed_greater(bool(true), bool(true))); + EXPECT_FALSE(util::relaxed_greater(bool(false), bool(false))); } @@ -344,6 +431,11 @@ TEST(Variant, RelaxedLess) { EXPECT_TRUE(util::relaxed_less(double(0), bool(true))); EXPECT_TRUE(util::relaxed_less(bool(false), bool(true))); + EXPECT_TRUE(util::relaxed_less(bool(true), std::string("386"))); + EXPECT_TRUE(util::relaxed_less(bool(true), uint64_t(386))); + EXPECT_TRUE(util::relaxed_less(bool(true), int64_t(386))); + EXPECT_TRUE(util::relaxed_less(bool(true), double(386))); + @@ -351,31 +443,28 @@ TEST(Variant, RelaxedLess) { EXPECT_FALSE(util::relaxed_less(uint64_t(387), std::string("386"))); EXPECT_FALSE(util::relaxed_less(int64_t(387), std::string("386"))); EXPECT_FALSE(util::relaxed_less(double(387), std::string("386"))); - EXPECT_FALSE(util::relaxed_less(bool(true), std::string("386"))); EXPECT_FALSE(util::relaxed_less(std::string("387"), uint64_t(386))); EXPECT_FALSE(util::relaxed_less(uint64_t(387), uint64_t(386))); EXPECT_FALSE(util::relaxed_less(int64_t(387), uint64_t(386))); EXPECT_FALSE(util::relaxed_less(double(387), uint64_t(386))); - EXPECT_FALSE(util::relaxed_less(bool(true), uint64_t(386))); EXPECT_FALSE(util::relaxed_less(std::string("387"), int64_t(386))); EXPECT_FALSE(util::relaxed_less(uint64_t(387), int64_t(386))); EXPECT_FALSE(util::relaxed_less(int64_t(387), int64_t(386))); EXPECT_FALSE(util::relaxed_less(double(387), int64_t(386))); - EXPECT_FALSE(util::relaxed_less(bool(true), int64_t(386))); EXPECT_FALSE(util::relaxed_less(std::string("387"), double(386.7))); EXPECT_FALSE(util::relaxed_less(uint64_t(387), double(386.7))); EXPECT_FALSE(util::relaxed_less(int64_t(387), double(386.7))); EXPECT_FALSE(util::relaxed_less(double(387), double(386.7))); - EXPECT_FALSE(util::relaxed_less(bool(true), double(386))); EXPECT_FALSE(util::relaxed_less(std::string("387"), bool(true))); EXPECT_FALSE(util::relaxed_less(uint64_t(387), bool(true))); EXPECT_FALSE(util::relaxed_less(int64_t(387), bool(true))); EXPECT_FALSE(util::relaxed_less(double(387), bool(true))); EXPECT_FALSE(util::relaxed_less(bool(true), bool(true))); + EXPECT_FALSE(util::relaxed_less(bool(false), bool(false))); } From a902446e7f6d45c4b0a707f1adf4ea607b64f081 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Wed, 16 Jul 2014 18:18:04 -0700 Subject: [PATCH 07/13] refs #342 & #346: per-map change callbacks --- common/glfw_view.cpp | 10 +++--- common/glfw_view.hpp | 2 ++ common/headless_view.cpp | 16 +++------- common/headless_view.hpp | 2 ++ include/llmr/map/transform.hpp | 5 ++- include/llmr/map/view.hpp | 20 ++++++++++++ include/llmr/platform/platform.hpp | 18 ----------- ios/mapbox-gl-cocoa | 2 +- src/map/map.cpp | 2 +- src/map/transform.cpp | 50 ++++++++++++++++-------------- 10 files changed, 64 insertions(+), 63 deletions(-) diff --git a/common/glfw_view.cpp b/common/glfw_view.cpp index 0d26928e0..ae992d926 100644 --- a/common/glfw_view.cpp +++ b/common/glfw_view.cpp @@ -1,7 +1,5 @@ #include "glfw_view.hpp" -#include - GLFWView::GLFWView(bool fullscreen) : fullscreen(fullscreen) { #ifdef NVIDIA glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)glfwGetProcAddress("glDiscardFramebufferEXT"); @@ -196,6 +194,10 @@ void GLFWView::swap() { glfwPostEmptyEvent(); } +void GLFWView::notify_map_change(llmr::MapChange change, llmr::timestamp delay) { + // no-op +} + void GLFWView::fps() { static int frames = 0; static double time_elapsed = 0; @@ -283,9 +285,5 @@ void show_color_debug_image(std::string name, const char *data, size_t logical_w } #endif -void notify_map_change(MapChange change, timestamp delay) { - // no-op -} - } } diff --git a/common/glfw_view.hpp b/common/glfw_view.hpp index 62da124ca..05a406328 100644 --- a/common/glfw_view.hpp +++ b/common/glfw_view.hpp @@ -2,6 +2,7 @@ #define LLMR_COMMON_GLFW_VIEW #include +#include #ifdef NVIDIA #define GLFW_INCLUDE_ES2 @@ -18,6 +19,7 @@ public: void initialize(llmr::Map *map); void swap(); void make_active(); + void notify_map_change(llmr::MapChange change, llmr::timestamp delay = 0); static void key(GLFWwindow *window, int key, int scancode, int action, int mods); static void scroll(GLFWwindow *window, double xoffset, double yoffset); diff --git a/common/headless_view.cpp b/common/headless_view.cpp index 2ca804664..6c4054303 100644 --- a/common/headless_view.cpp +++ b/common/headless_view.cpp @@ -1,17 +1,5 @@ #include "headless_view.hpp" -#include #include -#include - -namespace llmr { - -namespace platform { - -void notify_map_change(MapChange change, timestamp delay) { - // no-op -} - -} HeadlessView::HeadlessView() { #if LLMR_USE_CGL @@ -161,6 +149,10 @@ HeadlessView::~HeadlessView() { #endif } +void HeadlessView::notify_map_change(llmr::MapChange change, llmr::timestamp delay) { + // no-op +} + void HeadlessView::make_active() { #if LLMR_USE_CGL CGLError error = CGLSetCurrentContext(gl_context); diff --git a/common/headless_view.hpp b/common/headless_view.hpp index b3e1c11b9..efbc08df1 100644 --- a/common/headless_view.hpp +++ b/common/headless_view.hpp @@ -10,6 +10,7 @@ #include #include +#include namespace llmr { @@ -20,6 +21,7 @@ public: void resize(int width, int height); + void notify_map_change(MapChange change, timestamp delay = 0); void make_active(); void swap(); unsigned int root_fbo(); diff --git a/include/llmr/map/transform.hpp b/include/llmr/map/transform.hpp index c4474ff02..16e5b21e8 100644 --- a/include/llmr/map/transform.hpp +++ b/include/llmr/map/transform.hpp @@ -5,6 +5,7 @@ #include #include +#include "view.hpp" #include "transform_state.hpp" #include @@ -15,7 +16,7 @@ struct box; class Transform : private util::noncopyable { public: - Transform(); + Transform(View &view); // Map view // Note: width * ratio does not necessarily equal fb_width @@ -74,6 +75,8 @@ private: void constrain(double& scale, double& y) const; private: + View &view; + mutable uv::rwlock mtx; // This reflects the current state of the transform, representing the actual position of the diff --git a/include/llmr/map/view.hpp b/include/llmr/map/view.hpp index d032f783c..d1fa58aa7 100644 --- a/include/llmr/map/view.hpp +++ b/include/llmr/map/view.hpp @@ -1,10 +1,25 @@ #ifndef LLMR_MAP_VIEW #define LLMR_MAP_VIEW +#include + namespace llmr { class Map; +enum MapChange : uint8_t { + MapChangeRegionWillChange = 0, + MapChangeRegionWillChangeAnimated = 1, + MapChangeRegionDidChange = 2, + MapChangeRegionDidChangeAnimated = 3, + MapChangeWillStartLoadingMap = 4, + MapChangeDidFinishLoadingMap = 5, + MapChangeDidFailLoadingMap = 6, + MapChangeWillStartRenderingMap = 7, + MapChangeDidFinishRenderingMap = 8, + MapChangeDidFinishRenderingMapFullyRendered = 9 +}; + class View { public: virtual void initialize(Map *map) { @@ -26,6 +41,11 @@ public: return 0; } + // Notifies a watcher of map x/y/scale/rotation changes. + // Must only be called from the same thread that caused the change. + // Must not be called from the render thread. + virtual void notify_map_change(MapChange change, timestamp delay = 0) = 0; + protected: llmr::Map *map = nullptr; }; diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp index 540f22619..30c6e048b 100644 --- a/include/llmr/platform/platform.hpp +++ b/include/llmr/platform/platform.hpp @@ -1,8 +1,6 @@ #ifndef LLMR_PLATFORM_PLATFORM #define LLMR_PLATFORM_PLATFORM -#include - #include #include #include @@ -26,19 +24,6 @@ struct Response { std::function callback; }; -enum MapChange : uint8_t { - MapChangeRegionWillChange = 0, - MapChangeRegionWillChangeAnimated = 1, - MapChangeRegionDidChange = 2, - MapChangeRegionDidChangeAnimated = 3, - MapChangeWillStartLoadingMap = 4, - MapChangeDidFinishLoadingMap = 5, - MapChangeDidFailLoadingMap = 6, - MapChangeWillStartRenderingMap = 7, - MapChangeDidFinishRenderingMap = 8, - MapChangeDidFinishRenderingMapFullyRendered = 9 -}; - // Makes an HTTP request of a URL, preferrably on a background thread, and calls a function with the // results in the original thread (which runs the libuv loop). // If the loop pointer is NULL, the callback function will be called on an arbitrary thread. @@ -50,9 +35,6 @@ std::shared_ptr request_http(const std::string &url, // Cancels an HTTP request. void cancel_request_http(const std::shared_ptr &req); -// Notifies a watcher of map changes. -void notify_map_change(MapChange key, timestamp delay = 0); - // Shows an alpha image with the specified dimensions in a named window. void show_debug_image(std::string name, const char *data, size_t width, size_t height); diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa index fcb1de181..84c3383dc 160000 --- a/ios/mapbox-gl-cocoa +++ b/ios/mapbox-gl-cocoa @@ -1 +1 @@ -Subproject commit fcb1de1812fcf460712c210bdbfe9372ce341e34 +Subproject commit 84c3383dc4394e544268547b3d6bf252fc6a2728 diff --git a/src/map/map.cpp b/src/map/map.cpp index 4d374f1d5..2086ad54b 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -22,7 +22,7 @@ using namespace llmr; Map::Map(View& view) : view(view), - transform(), + transform(view), style(std::make_shared