From e4858b6a0270f6deb22ad2f97be658e9c510673c Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 8 Jan 2015 23:23:35 -0500 Subject: [PATCH 01/11] merge adjacent roads with same text for labelling js: https://github.com/mapbox/mapbox-gl-js/pull/683 --- src/mbgl/renderer/symbol_bucket.cpp | 62 +++++++++------- src/mbgl/renderer/symbol_bucket.hpp | 1 - src/mbgl/util/merge_lines.hpp | 110 ++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 src/mbgl/util/merge_lines.hpp diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index 0eadacec5..b0cfbf974 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -16,6 +16,7 @@ #include #include #include +#include namespace mbgl { @@ -145,7 +146,37 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress const FontStack &fontStack = glyphStore.getFontStack(properties.text.font); - for (const SymbolFeature &feature : features) { + std::vector>> geometries; + + for (unsigned int k = 0; k < features.size(); k++) { + const SymbolFeature &feature = features[k]; + + geometries.emplace_back(); + std::vector> &multiline = geometries.back(); + + // Decode all lines. + Geometry::command cmd; + bool first = true; + pbf geom(feature.geometry); + Geometry geometry(geom); + int32_t x, y; + while ((cmd = geometry.next(x, y)) != Geometry::end) { + if (first || cmd == Geometry::move_to) { + multiline.emplace_back(); + first = false; + } + multiline.back().emplace_back(x, y); + } + } + + if (properties.placement == PlacementType::Line) { + util::mergeLines(features, geometries); + } + + for (unsigned int k = 0; k < geometries.size(); k++) { + if (!geometries[k].size()) continue; + const SymbolFeature &feature = features[k]; + Shaping shaping; Rect image; GlyphPositions face; @@ -181,32 +212,13 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress // if either shaping or icon position is present, add the feature if (shaping.size() || image) { - addFeature(feature.geometry, shaping, face, image); - } - } -} - -void SymbolBucket::addFeature(const pbf &geom_pbf, const Shaping &shaping, - const GlyphPositions &face, const Rect &image) { - // Decode all lines. - std::vector line; - Geometry::command cmd; - - Coordinate coord; - pbf geom(geom_pbf); - Geometry geometry(geom); - int32_t x, y; - while ((cmd = geometry.next(x, y)) != Geometry::end) { - if (cmd == Geometry::move_to) { - if (!line.empty()) { - addFeature(line, shaping, face, image); - line.clear(); + std::vector> &multiline = geometries[k]; + for (const std::vector &line : multiline) { + if (line.size()) { + addFeature(line, shaping, face, image); + } } } - line.emplace_back(x, y); - } - if (line.size()) { - addFeature(line, shaping, face, image); } } diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index dd596b1a0..f90ff8999 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -77,7 +77,6 @@ private: std::vector processFeatures(const VectorTileLayer &layer, const FilterExpression &filter, GlyphStore &glyphStore, const Sprite &sprite); - void addFeature(const pbf &geom_pbf, const Shaping &shaping, const GlyphPositions &face, const Rect &image); void addFeature(const std::vector &line, const Shaping &shaping, const GlyphPositions &face, const Rect &image); diff --git a/src/mbgl/util/merge_lines.hpp b/src/mbgl/util/merge_lines.hpp new file mode 100644 index 000000000..433e0b276 --- /dev/null +++ b/src/mbgl/util/merge_lines.hpp @@ -0,0 +1,110 @@ +#ifndef MBGL_UTIL_MERGELINES +#define MBGL_UTIL_MERGELINES + +#include +#include +#include +#include +#include + + +#include +namespace mbgl { +namespace util { + +unsigned int mergeFromRight( + std::vector>> &geometries, + std::map &rightIndex, + std::map::iterator left, + std::string &rightKey, + std::vector> &geom) { + + unsigned int index = left->second; + rightIndex.erase(left); + rightIndex[rightKey] = index; + geometries[index][0].pop_back(); + geometries[index][0].insert(geometries[index][0].end(), geom[0].begin(), geom[0].end()); + geom[0].clear(); + return index; +} + +unsigned int mergeFromLeft( + std::vector>> &geometries, + std::map &leftIndex, + std::string &leftKey, + std::map::iterator right, + std::vector> &geom) { + + unsigned int index = right->second; + leftIndex.erase(right); + leftIndex[leftKey] = index; + geom[0].pop_back(); + geom[0].insert(geom[0].end(), geometries[index][0].begin(), geometries[index][0].end()); + geometries[index][0].clear(); + std::swap(geometries[index][0], geom[0]); + return index; +} + +std::string getKey(const std::u32string &text, const std::vector> &geom, bool onRight) { + const Coordinate &coord = onRight ? geom[0].back() : geom[0].front(); + std::ostringstream key; + for (const char32_t &c : text) { + key << (char)c; + } + key << ":" << coord.x << ":" << coord.y; + return key.str(); +} + + +void mergeLines(const std::vector &features, std::vector>> &geometries) { + + std::map leftIndex; + std::map rightIndex; + + if (features.size()) getKey(features[0].label, geometries[0], false); + + for (unsigned int k = 0; k < features.size(); k++) { + const SymbolFeature &feature = features[k]; + std::vector> &geometry = geometries[k]; + + if (!feature.label.length()) { + continue; + } + + std::string leftKey = getKey(feature.label, geometry, false); + std::string rightKey = getKey(feature.label, geometry, true); + + auto left = rightIndex.find(leftKey); + auto right = leftIndex.find(rightKey); + + if ((left != rightIndex.end()) && (right != leftIndex.end()) && (left->second != right->second)) { + // found lines with the same text adjacent to both ends of the current line, merge all three + unsigned int j = mergeFromLeft(geometries, leftIndex, leftKey, right, geometry); + unsigned int i = mergeFromRight(geometries, rightIndex, left, rightKey, geometries[j]); + + leftIndex.erase(leftIndex.find(leftKey)); + rightIndex.erase(rightIndex.find(rightKey)); + rightIndex[getKey(feature.label, geometries[i], true)] = i; + + } else if (left != rightIndex.end()) { + // found mergeable line adjacent to the start of the current line, merge + mergeFromRight(geometries, rightIndex, left, rightKey, geometry); + + } else if (right != leftIndex.end()) { + // found mergeable line adjacent to the end of the current line, merge + mergeFromLeft(geometries, leftIndex, leftKey, right, geometry); + + } else { + // no adjacent lines, add as a new item + leftIndex[leftKey] = k; + rightIndex[rightKey] = k; + } + + } + +} + +} // end namespace util +} // end namespace mbgl + +#endif From 5670fb397ffe7ce596d94a91ee5aaf5e2b348e9a Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 8 Jan 2015 23:50:12 -0500 Subject: [PATCH 02/11] get rid of separate vector for symbol geometries --- src/mbgl/renderer/symbol_bucket.cpp | 57 ++++++++++++----------------- src/mbgl/renderer/symbol_bucket.hpp | 2 +- src/mbgl/util/merge_lines.hpp | 33 ++++++++--------- 3 files changed, 40 insertions(+), 52 deletions(-) diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp index b0cfbf974..c6a7c8c4e 100644 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ b/src/mbgl/renderer/symbol_bucket.cpp @@ -86,11 +86,31 @@ std::vector SymbolBucket::processFeatures(const VectorTileLayer & } if (ft.label.length() || ft.sprite.length()) { - ft.geometry = feature.geometry; + + auto &multiline = ft.geometry; + + // Decode line + Geometry::command cmd; + pbf geom(feature.geometry); + Geometry geometry(geom); + bool first = true; + int32_t x, y; + while ((cmd = geometry.next(x, y)) != Geometry::end) { + if (first || cmd == Geometry::move_to) { + multiline.emplace_back(); + first = false; + } + multiline.back().emplace_back(x, y); + } + features.push_back(std::move(ft)); } } + if (properties.placement == PlacementType::Line) { + util::mergeLines(features); + } + glyphStore.waitForGlyphRanges(properties.text.font, ranges); sprite.waitUntilLoaded(); @@ -146,36 +166,8 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress const FontStack &fontStack = glyphStore.getFontStack(properties.text.font); - std::vector>> geometries; - - for (unsigned int k = 0; k < features.size(); k++) { - const SymbolFeature &feature = features[k]; - - geometries.emplace_back(); - std::vector> &multiline = geometries.back(); - - // Decode all lines. - Geometry::command cmd; - bool first = true; - pbf geom(feature.geometry); - Geometry geometry(geom); - int32_t x, y; - while ((cmd = geometry.next(x, y)) != Geometry::end) { - if (first || cmd == Geometry::move_to) { - multiline.emplace_back(); - first = false; - } - multiline.back().emplace_back(x, y); - } - } - - if (properties.placement == PlacementType::Line) { - util::mergeLines(features, geometries); - } - - for (unsigned int k = 0; k < geometries.size(); k++) { - if (!geometries[k].size()) continue; - const SymbolFeature &feature = features[k]; + for (const SymbolFeature &feature : features) { + if (!feature.geometry.size()) continue; Shaping shaping; Rect image; @@ -212,8 +204,7 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress // if either shaping or icon position is present, add the feature if (shaping.size() || image) { - std::vector> &multiline = geometries[k]; - for (const std::vector &line : multiline) { + for (const std::vector &line : feature.geometry) { if (line.size()) { addFeature(line, shaping, face, image); } diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp index f90ff8999..bc148579f 100644 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ b/src/mbgl/renderer/symbol_bucket.hpp @@ -30,7 +30,7 @@ class FontStack; class SymbolFeature { public: - pbf geometry; + std::vector> geometry; std::u32string label; std::string sprite; }; diff --git a/src/mbgl/util/merge_lines.hpp b/src/mbgl/util/merge_lines.hpp index 433e0b276..6e4c56125 100644 --- a/src/mbgl/util/merge_lines.hpp +++ b/src/mbgl/util/merge_lines.hpp @@ -8,12 +8,11 @@ #include -#include namespace mbgl { namespace util { unsigned int mergeFromRight( - std::vector>> &geometries, + std::vector &features, std::map &rightIndex, std::map::iterator left, std::string &rightKey, @@ -22,14 +21,14 @@ unsigned int mergeFromRight( unsigned int index = left->second; rightIndex.erase(left); rightIndex[rightKey] = index; - geometries[index][0].pop_back(); - geometries[index][0].insert(geometries[index][0].end(), geom[0].begin(), geom[0].end()); + features[index].geometry[0].pop_back(); + features[index].geometry[0].insert(features[index].geometry[0].end(), geom[0].begin(), geom[0].end()); geom[0].clear(); return index; } unsigned int mergeFromLeft( - std::vector>> &geometries, + std::vector &features, std::map &leftIndex, std::string &leftKey, std::map::iterator right, @@ -39,9 +38,9 @@ unsigned int mergeFromLeft( leftIndex.erase(right); leftIndex[leftKey] = index; geom[0].pop_back(); - geom[0].insert(geom[0].end(), geometries[index][0].begin(), geometries[index][0].end()); - geometries[index][0].clear(); - std::swap(geometries[index][0], geom[0]); + geom[0].insert(geom[0].end(), features[index].geometry[0].begin(), features[index].geometry[0].end()); + features[index].geometry[0].clear(); + std::swap(features[index].geometry[0], geom[0]); return index; } @@ -56,16 +55,14 @@ std::string getKey(const std::u32string &text, const std::vector &features, std::vector>> &geometries) { +void mergeLines(std::vector &features) { std::map leftIndex; std::map rightIndex; - - if (features.size()) getKey(features[0].label, geometries[0], false); for (unsigned int k = 0; k < features.size(); k++) { - const SymbolFeature &feature = features[k]; - std::vector> &geometry = geometries[k]; + SymbolFeature &feature = features[k]; + std::vector> &geometry = feature.geometry; if (!feature.label.length()) { continue; @@ -79,20 +76,20 @@ void mergeLines(const std::vector &features, std::vectorsecond != right->second)) { // found lines with the same text adjacent to both ends of the current line, merge all three - unsigned int j = mergeFromLeft(geometries, leftIndex, leftKey, right, geometry); - unsigned int i = mergeFromRight(geometries, rightIndex, left, rightKey, geometries[j]); + unsigned int j = mergeFromLeft(features, leftIndex, leftKey, right, geometry); + unsigned int i = mergeFromRight(features, rightIndex, left, rightKey, features[j].geometry); leftIndex.erase(leftIndex.find(leftKey)); rightIndex.erase(rightIndex.find(rightKey)); - rightIndex[getKey(feature.label, geometries[i], true)] = i; + rightIndex[getKey(feature.label, features[i].geometry, true)] = i; } else if (left != rightIndex.end()) { // found mergeable line adjacent to the start of the current line, merge - mergeFromRight(geometries, rightIndex, left, rightKey, geometry); + mergeFromRight(features, rightIndex, left, rightKey, geometry); } else if (right != leftIndex.end()) { // found mergeable line adjacent to the end of the current line, merge - mergeFromLeft(geometries, leftIndex, leftKey, right, geometry); + mergeFromLeft(features, leftIndex, leftKey, right, geometry); } else { // no adjacent lines, add as a new item From 4533dcaf34096fd9f3756f283468301bbb077104 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 13 Jan 2015 12:49:41 -0500 Subject: [PATCH 03/11] fix hard tabs in Makefile so clear_xcode_cache task actually runs, remove cache.db in Application Support if it exists --- Makefile | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index d429903db..933fb1340 100644 --- a/Makefile +++ b/Makefile @@ -115,16 +115,21 @@ render: build/render/Makefile ##### Xcode projects ########################################################### +.PHONY: clear_xcode_cache clear_xcode_cache: - @CUSTOM_DD=`defaults read com.apple.dt.Xcode IDECustomDerivedDataLocation 2>/dev/null`; \ - if [[ $$CUSTOM_DD ]]; then \ - echo clearing files in $$CUSTOM_DD older than one day; \ - find $$CUSTOM_DD/mapboxgl-app-* -mtime +1 | xargs rm -rf; \ - fi; \ - if [[ -d ~/Library/Developer/Xcode/DerivedData/ ]] && [[ ! $$CUSTOM_DD ]]; then \ - echo 'clearing files in ~/Library/Developer/Xcode/DerivedData/mapboxgl-app-* older than one day'; \ - find ~/Library/Developer/Xcode/DerivedData/mapboxgl-app-* -mtime +1 | xargs rm -rf; \ - fi + @CUSTOM_DD=`defaults read com.apple.dt.Xcode IDECustomDerivedDataLocation 2>/dev/null`; \ + if [[ $$CUSTOM_DD ]]; then \ + echo clearing files in $$CUSTOM_DD older than one day; \ + find $$CUSTOM_DD/mapboxgl-app-* -mtime +1 | xargs rm -rf; \ + fi; \ + if [[ -d ~/Library/Developer/Xcode/DerivedData/ ]] && [[ ! $$CUSTOM_DD ]]; then \ + echo 'clearing files in ~/Library/Developer/Xcode/DerivedData/mapboxgl-app-* older than one day'; \ + find ~/Library/Developer/Xcode/DerivedData/mapboxgl-app-* -mtime +1 | xargs rm -rf; \ + fi; \ + if [[ -e ~/Library/Application\ Support/Mapbox\ GL/cache.db ]]; then \ + echo 'removing ~/Library/Application\ Support/Mapbox\ GL/cache.db'; \ + rm ~/Library/Application\ Support/Mapbox\ GL/cache.db; \ + fi xproj: build/macosx/mapboxgl-app.xcodeproj open ./build/macosx/mapboxgl-app.xcodeproj From fa0d20194e5ccddd4ea1902a9d97592b06367fc3 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 13 Jan 2015 14:15:48 -0500 Subject: [PATCH 04/11] break out version.hpp copy task into a separate gyp target to eliminate a possible race condition in parallel builds --- gyp/install.gypi | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/gyp/install.gypi b/gyp/install.gypi index 5338bfed1..cf08ea1ea 100644 --- a/gyp/install.gypi +++ b/gyp/install.gypi @@ -17,7 +17,6 @@ { 'files': [ '<(PRODUCT_DIR)/libmbgl-headless.a' ], 'destination': '<(install_prefix)/lib' }, { 'files': [ '<(PRODUCT_DIR)/libmbgl-<(platform).a' ], 'destination': '<(install_prefix)/lib' }, { 'files': [ '../include/mbgl' ], 'destination': '<(install_prefix)/include' }, - { 'files': [ '<(SHARED_INTERMEDIATE_DIR)/include/mbgl/util/version.hpp' ], 'destination': '<(install_prefix)/include/mbgl/util' }, ], 'variables': { 'conditions': [ @@ -55,6 +54,16 @@ } ] }, + { 'target_name': 'copy_version', + 'type': 'none', + 'hard_dependency': 1, + 'dependencies': [ + 'install', + ], + 'copies': [ + { 'files': [ '<(SHARED_INTERMEDIATE_DIR)/include/mbgl/util/version.hpp' ], 'destination': '<(install_prefix)/include/mbgl/util' }, + ], + } ] }], ], From 139c0c6da6d03730a9494050ea014f3d9400fb18 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Thu, 8 Jan 2015 12:05:03 -0500 Subject: [PATCH 05/11] build against mason sqlite 3.8.6 --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 8c74ec189..33410ca8a 100755 --- a/configure +++ b/configure @@ -26,7 +26,7 @@ case ${MASON_PLATFORM} in ;; *) GLFW_VERSION=e1ae9af5 - SQLITE_VERSION=system + SQLITE_VERSION=3.8.6 LIBPNG_VERSION=1.6.13 LIBJPEG_VERSION=v8d LIBCURL_VERSION=system From f1609ef329d13fb16f13e75a920099fca19d47ca Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Thu, 8 Jan 2015 13:58:16 -0500 Subject: [PATCH 06/11] include sqlite3_static_libs in linker flags --- gyp/mbgl-core.gypi | 1 + macosx/mapboxgl-app.gyp | 3 ++- test/test.gyp | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/gyp/mbgl-core.gypi b/gyp/mbgl-core.gypi index ea279f2da..aa30c5b4d 100644 --- a/gyp/mbgl-core.gypi +++ b/gyp/mbgl-core.gypi @@ -85,6 +85,7 @@ '<(standalone_lib)', '<@(uv_static_libs)', '<@(curl_static_libs)', + '<@(sqlite3_static_libs)', '<(core_lib)' ], } diff --git a/macosx/mapboxgl-app.gyp b/macosx/mapboxgl-app.gyp index 6696ebc57..192604d3c 100644 --- a/macosx/mapboxgl-app.gyp +++ b/macosx/mapboxgl-app.gyp @@ -39,6 +39,7 @@ 'ldflags': [ '<@(uv_ldflags)', '<@(uv_static_libs)', + '<@(sqlite3_static_libs)', '<@(sqlite3_ldflags)', '<@(glfw3_static_libs)', '<@(glfw3_ldflags)', @@ -61,4 +62,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/test/test.gyp b/test/test.gyp index e33cf3689..5cb84dbd4 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -7,6 +7,7 @@ 'variables' : { 'ldflags': [ '<@(uv_ldflags)', + '<@(sqlite3_static_libs)', '<@(sqlite3_ldflags)', '<@(curl_ldflags)', '<@(png_ldflags)', From 0d1764c43eabd1b6461ca0fde2df0617edb5fa54 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Thu, 8 Jan 2015 11:04:28 -0800 Subject: [PATCH 07/11] sqlite3_static_libs on linux --- linux/mapboxgl-app.gyp | 1 + 1 file changed, 1 insertion(+) diff --git a/linux/mapboxgl-app.gyp b/linux/mapboxgl-app.gyp index 4127b5c27..60eb16de3 100644 --- a/linux/mapboxgl-app.gyp +++ b/linux/mapboxgl-app.gyp @@ -29,6 +29,7 @@ 'variables': { 'ldflags': [ '<@(png_ldflags)', + '<@(sqlite3_static_libs)', '<@(sqlite3_ldflags)', '<@(glfw3_static_libs)', '<@(glfw3_ldflags)', From 1b2f38d33055ee40a92e6e71c29ef185286b8e30 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Fri, 9 Jan 2015 15:01:07 -0500 Subject: [PATCH 08/11] pass sqlite3_static_libs in install.gypi --- gyp/install.gypi | 1 + 1 file changed, 1 insertion(+) diff --git a/gyp/install.gypi b/gyp/install.gypi index cf08ea1ea..1c5066a9c 100644 --- a/gyp/install.gypi +++ b/gyp/install.gypi @@ -46,6 +46,7 @@ './utils/mbgl-config/build.sh', '<(install_prefix)', '<(platform)', + '<@(sqlite3_static_libs)', '<@(sqlite3_ldflags)', '<@(curl_ldflags)', '<@(png_ldflags)', From 8cca0a27bad356c9033ddfb2b3e44204207c98c8 Mon Sep 17 00:00:00 2001 From: Leith Bade Date: Mon, 12 Jan 2015 12:35:09 +1100 Subject: [PATCH 09/11] Check for IO errors when loading binary shader. Fixes #740 --- src/mbgl/map/map.cpp | 9 ++++- src/mbgl/shader/shader.cpp | 78 ++++++++++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index ea95c925c..f78b8385c 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -250,6 +250,8 @@ void Map::run() { mode = Mode::None; fileSource.clearLoop(); } + + terminate(); } void Map::rerender() { @@ -258,8 +260,9 @@ void Map::rerender() { } else if (mode == Mode::Continuous) { // We only send render events if we want to continuously update the map // (== async rendering). - assert(asyncRender); - asyncRender->send(); + if (asyncRender) { + asyncRender->send(); + } } } @@ -279,7 +282,9 @@ void Map::swapped() { void Map::terminate() { assert(painter); + view.activate(); painter->terminate(); + view.deactivate(); } #pragma mark - Setup diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp index 62edf1d38..32e10a640 100644 --- a/src/mbgl/shader/shader.cpp +++ b/src/mbgl/shader/shader.cpp @@ -26,26 +26,53 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo // Load binary shader if it exists bool skipCompile = false; if (!binaryFileName.empty() && (gl::ProgramBinary != nullptr)) { - std::ifstream binaryFile(binaryFileName, std::ios::in | std::ios::binary); + try { + std::ifstream binaryFile(binaryFileName, std::ios::in | std::ios::binary); + binaryFile.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); - GLsizei binaryLength; - GLenum binaryFormat; - binaryFile.read(reinterpret_cast(&binaryLength), sizeof(binaryLength)); - binaryFile.read(reinterpret_cast(&binaryFormat), sizeof(binaryFormat)); + GLsizei binaryLength; + GLenum binaryFormat; + binaryFile.read(reinterpret_cast(&binaryLength), sizeof(binaryLength)); + binaryFile.read(reinterpret_cast(&binaryFormat), sizeof(binaryFormat)); - std::unique_ptr binary = mbgl::util::make_unique(binaryLength); - binaryFile.read(binary.get(), binaryLength); + GLint numBinaryFormats; + MBGL_CHECK_ERROR(glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats)); - MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength)); + std::unique_ptr validBinaryFormats = mbgl::util::make_unique(numBinaryFormats); + MBGL_CHECK_ERROR(glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, reinterpret_cast(validBinaryFormats.get()))); - // Check if the binary was valid - GLint status; - MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status)); - if (status == GL_TRUE) { - skipCompile = true; + bool validBinaryFormat = false; + for (GLint i = 0; i < numBinaryFormats; i++) { + if (validBinaryFormats[i] == binaryFormat) { + validBinaryFormat = true; + } + } + if (!validBinaryFormat) { + throw std::runtime_error("Trying load program binary with an invalid binaryFormat!"); + } + + if (binaryLength == 0) { + throw std::runtime_error("Trying load program binary with a zero length binary!"); + } + + std::unique_ptr binary = mbgl::util::make_unique(binaryLength); + binaryFile.read(binary.get(), binaryLength); + + MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength)); + + // Check if the binary was valid + GLint status; + MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status)); + if (status == GL_TRUE) { + skipCompile = true; + } + + } catch(std::exception& e) { + Log::Error(Event::Shader, "Loading binary shader failed!"); + + // Delete the bad file + std::remove(binaryFileName.c_str()); } - - binaryFile.close(); } GLuint vertShader = 0; @@ -183,12 +210,21 @@ Shader::~Shader() { std::unique_ptr binary = mbgl::util::make_unique(binaryLength); MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get())); - // Write the binary to a file - std::ofstream binaryFile(binaryFileName, std::ios::out | std::ios::trunc | std::ios::binary); - binaryFile.write(reinterpret_cast(&binaryLength), sizeof(binaryLength)); - binaryFile.write(reinterpret_cast(&binaryFormat), sizeof(binaryFormat)); - binaryFile.write(binary.get(), binaryLength); - binaryFile.close(); + try { + // Write the binary to a file + std::ofstream binaryFile(binaryFileName, std::ios::out | std::ios::trunc | std::ios::binary); + binaryFile.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit); + + binaryFile.write(reinterpret_cast(&binaryLength), sizeof(binaryLength)); + binaryFile.write(reinterpret_cast(&binaryFormat), sizeof(binaryFormat)); + binaryFile.write(binary.get(), binaryLength); + + } catch(std::exception& e) { + Log::Error(Event::Shader, "Saving binary shader failed!"); + + // Delete the bad file + std::remove(binaryFileName.c_str()); + } } } From b54c0e24479c0b7b3d21cd30a24cc5b6fb2e2102 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 13 Jan 2015 22:26:37 -0500 Subject: [PATCH 10/11] simplify erase so you don't have to think about whether find might return an end() iterator (which is invalid for erase). --- src/mbgl/util/merge_lines.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mbgl/util/merge_lines.hpp b/src/mbgl/util/merge_lines.hpp index 6e4c56125..e0dd4c641 100644 --- a/src/mbgl/util/merge_lines.hpp +++ b/src/mbgl/util/merge_lines.hpp @@ -79,8 +79,8 @@ void mergeLines(std::vector &features) { unsigned int j = mergeFromLeft(features, leftIndex, leftKey, right, geometry); unsigned int i = mergeFromRight(features, rightIndex, left, rightKey, features[j].geometry); - leftIndex.erase(leftIndex.find(leftKey)); - rightIndex.erase(rightIndex.find(rightKey)); + leftIndex.erase(leftKey); + rightIndex.erase(rightKey); rightIndex[getKey(feature.label, features[i].geometry, true)] = i; } else if (left != rightIndex.end()) { From 4fbb7d614c93ac2d0146f2bf9c8e94fd2720b1ba Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 13 Jan 2015 22:29:28 -0500 Subject: [PATCH 11/11] port tests for mergeLines js: 867b7f4be01126663df609756049515a41e700d1 --- test/merge_lines.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++ test/test.gyp | 20 ++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 test/merge_lines.cpp diff --git a/test/merge_lines.cpp b/test/merge_lines.cpp new file mode 100644 index 000000000..3c887105f --- /dev/null +++ b/test/merge_lines.cpp @@ -0,0 +1,73 @@ +#include "gtest/gtest.h" + +#include + + +TEST(mergeLines, mergeLines) { + + std::u32string a = U"a"; + std::u32string b = U"b"; + + // merges lines with the same text + std::vector input1 = { + { {{{0, 0}, {1, 0}, {2, 0}}}, a, "" }, + { {{{4, 0}, {5, 0}, {6, 0}}}, b, "" }, + { {{{8, 0}, {9, 0}}}, a, "" }, + { {{{2, 0}, {3, 0}, {4, 0}}}, a, "" }, + { {{{6, 0}, {7, 0}, {8, 0}}}, a, "" }, + { {{{5, 0}, {6, 0}}}, a, "" } + }; + + std::vector expected1 = { + { {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}}}, a, "" }, + { {{{4, 0}, {5, 0}, {6, 0}}}, b, "" }, + { {{{5, 0}, {6, 0}, {7, 0}, {8, 0}, {9, 0}}}, a, "" }, + { {{}}, a, "" }, + { {{}}, a, "" }, + { {{}}, a, "" } + }; + + mbgl::util::mergeLines(input1); + + for (int i = 0; i < 6; i++) { + EXPECT_EQ(input1[i].geometry, expected1[i].geometry); + } + + // mergeLines handles merge from both ends + std::vector input2 = { + { {{{0, 0}, {1, 0}, {2, 0}}}, a, "" }, + { {{{4, 0}, {5, 0}, {6, 0}}}, a, "" }, + { {{{2, 0}, {3, 0}, {4, 0}}}, a, "" } + }; + + std::vector expected2 = { + { {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}}, a, "" }, + { {{}}, a, "" }, + { {{}}, a, "" } + }; + + mbgl::util::mergeLines(input2); + + for (int i = 0; i < 3; i++) { + EXPECT_EQ(input2[i].geometry, expected2[i].geometry); + } + + // mergeLines handles circular lines + std::vector input3 = { + { {{{0, 0}, {1, 0}, {2, 0}}}, a, "" }, + { {{{2, 0}, {3, 0}, {4, 0}}}, a, "" }, + { {{{4, 0}, {0, 0}}}, a, "" } + }; + + std::vector expected3 = { + { {{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {0, 0}}}, a, "" }, + { {{}}, a, "" }, + { {{}}, a, "" } + }; + + mbgl::util::mergeLines(input3); + + for (int i = 0; i < 3; i++) { + EXPECT_EQ(input3[i].geometry, expected3[i].geometry); + } +} diff --git a/test/test.gyp b/test/test.gyp index e33cf3689..dd24f9084 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -167,6 +167,25 @@ }] ] }, + { 'target_name': 'merge_lines', + 'product_name': 'test_merge_lines', + 'type': 'executable', + 'sources': [ + './main.cpp', + './merge_lines.cpp', + ], + 'dependencies': [ + '../deps/gtest/gtest.gyp:gtest', + '../mapboxgl.gyp:mbgl-standalone', + ], + 'include_dirs': [ '../src' ], + 'conditions': [ + ['OS == "mac"', { 'xcode_settings': { 'OTHER_LDFLAGS': [ '<@(ldflags)' ] } + }, { + 'libraries': [ '<@(ldflags)' ], + }] + ] + }, { 'target_name': 'headless', 'product_name': 'test_headless', 'type': 'executable', @@ -236,6 +255,7 @@ 'variant', 'tile', 'functions', + 'merge_lines', 'headless', 'style_parser', 'comparisons',