diff options
Diffstat (limited to 'src/mbgl/util')
25 files changed, 236 insertions, 363 deletions
diff --git a/src/mbgl/util/chrono.cpp b/src/mbgl/util/chrono.cpp index 5c8fd3c0ff..a880093b74 100644 --- a/src/mbgl/util/chrono.cpp +++ b/src/mbgl/util/chrono.cpp @@ -3,6 +3,13 @@ #include <parsedate/parsedate.h> #include <cstdio> +#include <ctime> + +#if defined(_WINDOWS) +#define _gmtime(t, i) gmtime_s(i, t) +#else +#define _gmtime(t, i) gmtime_r(t, i) +#endif namespace mbgl { namespace util { @@ -14,7 +21,7 @@ static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", std::string rfc1123(Timestamp timestamp) { std::time_t time = std::chrono::system_clock::to_time_t(timestamp); std::tm info; - gmtime_r(&time, &info); + _gmtime(&time, &info); char buffer[30]; snprintf(buffer, 30, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[info.tm_wday], info.tm_mday, months[info.tm_mon], 1900 + info.tm_year, info.tm_hour, info.tm_min, info.tm_sec); @@ -24,7 +31,7 @@ std::string rfc1123(Timestamp timestamp) { std::string iso8601(Timestamp timestamp) { std::time_t time = std::chrono::system_clock::to_time_t(timestamp); std::tm info; - gmtime_r(&time, &info); + _gmtime(&time, &info); char buffer[30]; std::strftime(buffer, sizeof(buffer), "%F %T", &info); return buffer; diff --git a/src/mbgl/util/constants.cpp b/src/mbgl/util/constants.cpp index 9faef140ef..56f78c9885 100644 --- a/src/mbgl/util/constants.cpp +++ b/src/mbgl/util/constants.cpp @@ -11,7 +11,6 @@ const bool tileParseWarnings = false; const bool styleParseWarnings = false; const bool spriteWarnings = false; const bool renderWarnings = false; -const bool renderTree = false; const bool labelTextMissingWarning = true; const bool missingFontStackWarning = true; const bool missingFontFaceWarning = true; @@ -22,7 +21,6 @@ const bool tileParseWarnings = false; const bool styleParseWarnings = false; const bool spriteWarnings = false; const bool renderWarnings = false; -const bool renderTree = false; const bool labelTextMissingWarning = false; const bool missingFontStackWarning = false; const bool missingFontFaceWarning = false; diff --git a/src/mbgl/util/dtoa.cpp b/src/mbgl/util/dtoa.cpp index dd4fba0f89..0e3aef6117 100644 --- a/src/mbgl/util/dtoa.cpp +++ b/src/mbgl/util/dtoa.cpp @@ -1,10 +1,18 @@ #include "dtoa.hpp" +// Clang/C2 on Windows 64-bits can't parse rapidjson's dtoa +// and it was causing the compiler to crash. +#if !defined(_WINDOWS) #include <rapidjson/internal/dtoa.h> +#endif + +#include <mbgl/util/string.hpp> namespace mbgl { namespace util { +#if !defined(_WINDOWS) + namespace { // From https://github.com/miloyip/rapidjson/blob/master/include/rapidjson/internal/dtoa.h @@ -101,5 +109,13 @@ std::string dtoa(double value) { return data; } +#else + +std::string dtoa(double value) { + return std::to_string(value); +} + +#endif + } // namespace util } // namespace mbgl diff --git a/src/mbgl/util/dtoa.hpp b/src/mbgl/util/dtoa.hpp index db7d309452..4cb81a94be 100644 --- a/src/mbgl/util/dtoa.hpp +++ b/src/mbgl/util/dtoa.hpp @@ -5,7 +5,6 @@ namespace mbgl { namespace util { -char* dtoa(double value, char* buffer); std::string dtoa(double value); } // end namespace util diff --git a/src/mbgl/util/geojson.cpp b/src/mbgl/util/geojson_impl.cpp index d1608e09fe..d1608e09fe 100644 --- a/src/mbgl/util/geojson.cpp +++ b/src/mbgl/util/geojson_impl.cpp diff --git a/src/mbgl/util/http_header.cpp b/src/mbgl/util/http_header.cpp index 40711232ff..ce31a06c5e 100644 --- a/src/mbgl/util/http_header.cpp +++ b/src/mbgl/util/http_header.cpp @@ -1,5 +1,7 @@ #include <mbgl/util/http_header.hpp> +#include <mbgl/util/string.hpp> + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wunused-parameter" diff --git a/src/mbgl/util/i18n.cpp b/src/mbgl/util/i18n.cpp index 6cfdc697e3..16f1d669f3 100644 --- a/src/mbgl/util/i18n.cpp +++ b/src/mbgl/util/i18n.cpp @@ -15,7 +15,7 @@ namespace { return codepoint >= first && codepoint <= last; \ } -// The following table comes from <http://www.unicode.org/Public/9.0.0/ucd/Blocks.txt>. +// The following table comes from <http://www.unicode.org/Public/10.0.0/ucd/Blocks.txt>. // Keep it synchronized with <http://www.unicode.org/Public/UCD/latest/ucd/Blocks.txt>. // DEFINE_IS_IN_UNICODE_BLOCK(BasicLatin, 0x0000, 0x007F) @@ -37,6 +37,7 @@ DEFINE_IS_IN_UNICODE_BLOCK(ArabicSupplement, 0x0750, 0x077F) // DEFINE_IS_IN_UNICODE_BLOCK(NKo, 0x07C0, 0x07FF) // DEFINE_IS_IN_UNICODE_BLOCK(Samaritan, 0x0800, 0x083F) // DEFINE_IS_IN_UNICODE_BLOCK(Mandaic, 0x0840, 0x085F) +// DEFINE_IS_IN_UNICODE_BLOCK(Syriac Supplement, 0x0860, 0x086F) DEFINE_IS_IN_UNICODE_BLOCK(ArabicExtendedA, 0x08A0, 0x08FF) // DEFINE_IS_IN_UNICODE_BLOCK(Devanagari, 0x0900, 0x097F) // DEFINE_IS_IN_UNICODE_BLOCK(Bengali, 0x0980, 0x09FF) @@ -239,9 +240,12 @@ DEFINE_IS_IN_UNICODE_BLOCK(HalfwidthandFullwidthForms, 0xFF00, 0xFFEF) // DEFINE_IS_IN_UNICODE_BLOCK(Takri, 0x11680, 0x116CF) // DEFINE_IS_IN_UNICODE_BLOCK(Ahom, 0x11700, 0x1173F) // DEFINE_IS_IN_UNICODE_BLOCK(WarangCiti, 0x118A0, 0x118FF) +// DEFINE_IS_IN_UNICODE_BLOCK(ZanabazarSquare, 0x11A00, 0x11A4F) +// DEFINE_IS_IN_UNICODE_BLOCK(Soyombo, 0x11A50, 0x11AAF) // DEFINE_IS_IN_UNICODE_BLOCK(PauCinHau, 0x11AC0, 0x11AFF) // DEFINE_IS_IN_UNICODE_BLOCK(Bhaiksuki, 0x11C00, 0x11C6F) // DEFINE_IS_IN_UNICODE_BLOCK(Marchen, 0x11C70, 0x11CBF) +// DEFINE_IS_IN_UNICODE_BLOCK(MasaramGondi, 0x11D00, 0x11D5F) // DEFINE_IS_IN_UNICODE_BLOCK(Cuneiform, 0x12000, 0x123FF) // DEFINE_IS_IN_UNICODE_BLOCK(CuneiformNumbersandPunctuation, 0x12400, 0x1247F) // DEFINE_IS_IN_UNICODE_BLOCK(EarlyDynasticCuneiform, 0x12480, 0x1254F) @@ -256,6 +260,8 @@ DEFINE_IS_IN_UNICODE_BLOCK(HalfwidthandFullwidthForms, 0xFF00, 0xFFEF) // DEFINE_IS_IN_UNICODE_BLOCK(Tangut, 0x17000, 0x187FF) // DEFINE_IS_IN_UNICODE_BLOCK(TangutComponents, 0x18800, 0x18AFF) // DEFINE_IS_IN_UNICODE_BLOCK(KanaSupplement, 0x1B000, 0x1B0FF) +// DEFINE_IS_IN_UNICODE_BLOCK(KanaExtendedA, 0x1B100, 0x1B12F) +// DEFINE_IS_IN_UNICODE_BLOCK(Nushu, 0x1B170, 0x1B2FF) // DEFINE_IS_IN_UNICODE_BLOCK(Duployan, 0x1BC00, 0x1BC9F) // DEFINE_IS_IN_UNICODE_BLOCK(ShorthandFormatControls, 0x1BCA0, 0x1BCAF) // DEFINE_IS_IN_UNICODE_BLOCK(ByzantineMusicalSymbols, 0x1D000, 0x1D0FF) @@ -286,6 +292,7 @@ DEFINE_IS_IN_UNICODE_BLOCK(HalfwidthandFullwidthForms, 0xFF00, 0xFFEF) // DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionC, 0x2A700, 0x2B73F) // DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionD, 0x2B740, 0x2B81F) // DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionE, 0x2B820, 0x2CEAF) +// DEFINE_IS_IN_UNICODE_BLOCK(CJKUnifiedIdeographsExtensionF, 0x2CEB0, 0x2EBEF) // DEFINE_IS_IN_UNICODE_BLOCK(CJKCompatibilityIdeographsSupplement, 0x2F800, 0x2FA1F) // DEFINE_IS_IN_UNICODE_BLOCK(Tags, 0xE0000, 0xE007F) // DEFINE_IS_IN_UNICODE_BLOCK(VariationSelectorsSupplement, 0xE0100, 0xE01EF) @@ -311,7 +318,7 @@ const std::map<char16_t, char16_t> verticalPunctuation = { { u'{', u'︷' }, { u'|', u'―' }, { u'}', u'︸' }, { u'⦅', u'︵' }, { u'⦆', u'︶' }, { u'。', u'︒' }, { u'「', u'﹁' }, { u'」', u'﹂' }, }; -} +} // namespace namespace mbgl { namespace util { @@ -375,11 +382,13 @@ bool allowsIdeographicBreaking(char16_t chr) { // return (isInTangut(chr) // || isInTangutComponents(chr) // || isInIdeographicSymbolsandPunctuation(chr) + // || isInNushu(chr) // || isInEnclosedIdeographicSupplement(chr) // || isInCJKUnifiedIdeographsExtensionB(chr) // || isInCJKUnifiedIdeographsExtensionC(chr) // || isInCJKUnifiedIdeographsExtensionD(chr) // || isInCJKUnifiedIdeographsExtensionE(chr) + // || isInCJKUnifiedIdeographsExtensionF(chr) // || isInCJKCompatibilityIdeographsSupplement(chr)); } @@ -393,7 +402,7 @@ bool allowsVerticalWritingMode(const std::u16string& string) { } // The following logic comes from -// <http://www.unicode.org/Public/vertical/revision-16/VerticalOrientation-16.txt>. +// <http://www.unicode.org/Public/vertical/revision-17/VerticalOrientation-17.txt>. // The data file denotes with “U” or “Tu” any codepoint that may be drawn // upright in vertical text but does not distinguish between upright and // “neutral” characters. @@ -457,6 +466,8 @@ bool hasUprightVerticalOrientation(char16_t chr) { // if (isInTangut(chr)) return true; // if (isInTangutComponents(chr)) return true; // if (isInKanaSupplement(chr)) return true; + // if (isInKanaExtendedA(chr)) return true; + // if (isInNushu(chr)) return true; // if (isInByzantineMusicalSymbols(chr)) return true; // if (isInMusicalSymbols(chr)) return true; // if (isInTaiXuanJingSymbols(chr)) return true; @@ -478,6 +489,7 @@ bool hasUprightVerticalOrientation(char16_t chr) { // if (isInCJKUnifiedIdeographsExtensionC(chr)) return true; // if (isInCJKUnifiedIdeographsExtensionD(chr)) return true; // if (isInCJKUnifiedIdeographsExtensionE(chr)) return true; + // if (isInCJKUnifiedIdeographsExtensionF(chr)) return true; // if (isInCJKCompatibilityIdeographsSupplement(chr)) return true; return false; diff --git a/src/mbgl/util/intersection_tests.cpp b/src/mbgl/util/intersection_tests.cpp index c580357298..e6ce245c0e 100644 --- a/src/mbgl/util/intersection_tests.cpp +++ b/src/mbgl/util/intersection_tests.cpp @@ -19,7 +19,7 @@ bool polygonContainsPoint(const GeometryCoordinates& ring, const GeometryCoordin // Code from http://stackoverflow.com/a/1501725/331379. float distToSegmentSquared(const GeometryCoordinate& p, const GeometryCoordinate& v, const GeometryCoordinate& w) { if (v == w) return util::distSqr<float>(p, v); - const float l2 = util::distSqr<float>(v, w); + const auto l2 = util::distSqr<float>(v, w); const float t = float((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; if (t < 0) return util::distSqr<float>(p, v); if (t > 1) return util::distSqr<float>(p, w); diff --git a/src/mbgl/util/io.cpp b/src/mbgl/util/io.cpp index 9adc3b8988..6a6ed7b250 100644 --- a/src/mbgl/util/io.cpp +++ b/src/mbgl/util/io.cpp @@ -6,8 +6,6 @@ #include <sstream> #include <fstream> -#include <unistd.h> - namespace mbgl { namespace util { @@ -43,8 +41,8 @@ optional<std::string> readFile(const std::string &filename) { } void deleteFile(const std::string& filename) { - const int ret = unlink(filename.c_str()); - if (ret == -1) { + const int ret = std::remove(filename.c_str()); + if (ret != 0) { throw IOException(errno, "failed to unlink file"); } } diff --git a/src/mbgl/util/logging.cpp b/src/mbgl/util/logging.cpp index 939f1def64..0552eb36cb 100644 --- a/src/mbgl/util/logging.cpp +++ b/src/mbgl/util/logging.cpp @@ -1,6 +1,6 @@ #include <mbgl/util/logging.hpp> #include <mbgl/util/enum.hpp> -#include <mbgl/util/thread.hpp> +#include <mbgl/util/platform.hpp> #include <cstdio> #include <cstdarg> diff --git a/src/mbgl/util/longest_common_subsequence.hpp b/src/mbgl/util/longest_common_subsequence.hpp new file mode 100644 index 0000000000..522b5a86b1 --- /dev/null +++ b/src/mbgl/util/longest_common_subsequence.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include <cstddef> +#include <functional> +#include <iterator> +#include <vector> + +namespace mbgl { + +/* + Computes the longest common subsequence (LCS) of sequences A and B, represented + by pairs of random access iterators. The result is output to the provided output + iterator. Equality of elements is determined by the provided comparator, defaulting + to ==. + + The algorithm used is the O(ND) time and space algorithm from: + + Myers, Eugene W. An O(ND) Difference Algorithm and Its Variations. Algorithmica + (1986) 1: 251. http://xmailserver.org/diff2.pdf + + For understanding this algorithm, http://simplygenius.net/Article/DiffTutorial1 is + also helpful. + + TODO: implement the O(N) space refinement presented in the paper. +*/ +template <class InIt, class OutIt, class Equal> +OutIt longest_common_subsequence(InIt a, InIt endA, + InIt b, InIt endB, + OutIt outIt, + Equal eq) { + const std::ptrdiff_t N = endA - a; + const std::ptrdiff_t M = endB - b; + const std::ptrdiff_t D = N + M; + + if (D == 0) { + return outIt; + } + + std::vector<std::vector<std::ptrdiff_t>> vs; + + // Self-executing lambda to allow `return` to break from inner loop, and avoid shadowing `v`. + [&] () { + std::vector<std::ptrdiff_t> v; + v.resize(2 * D + 1); + v[1] = 0; + + // Core of the algorithm: greedily find farthest-reaching D-paths for increasing + // values of D. Store the farthest-reaching endpoints found in each iteration for + // later reconstructing the LCS. + for (std::ptrdiff_t d = 0; d <= D; ++d) { + for (std::ptrdiff_t k = -d; k <= d; k += 2) { + std::ptrdiff_t x = (k == -d || (k != d && v.at(k - 1 + D) < v.at(k + 1 + D))) + ? v.at(k + 1 + D) // moving down + : v.at(k - 1 + D) + 1; // moving right + + std::ptrdiff_t y = x - k; + + while (x < N && y < M && eq(a[x], b[y])) { + x++; + y++; + } + + v[k + D] = x; + + if (x >= N && y >= M) { + vs.push_back(v); + return; + } + } + + vs.push_back(v); + } + }(); + + std::ptrdiff_t x = N; + std::ptrdiff_t y = M; + + using E = typename std::iterator_traits<InIt>::value_type; + std::vector<E> lcsReverse; + + // Reconstruct the LCS using the farthest-reaching endpoints stored above. + for (std::ptrdiff_t d = vs.size() - 1; x > 0 || y > 0; --d) { + const std::vector<std::ptrdiff_t>& v = vs.at(d); + const std::ptrdiff_t k = x - y; + const bool down = (k == -d || (k != d && v.at(k - 1 + D) < v.at(k + 1 + D))); + const std::ptrdiff_t kPrev = down ? k + 1 : k - 1; + + x = v.at(kPrev + D); + y = x - kPrev; + + for (std::ptrdiff_t c = v[k + D]; c != (down ? x : x + 1); --c) { + lcsReverse.push_back(a[c - 1]); + } + } + + return std::copy(lcsReverse.rbegin(), lcsReverse.rend(), outIt); +} + +template < typename InIt, typename OutIt > +OutIt longest_common_subsequence(InIt a, InIt endA, + InIt b, InIt endB, + OutIt outIt) { + return longest_common_subsequence(a, endA, b, endB, outIt, std::equal_to<>()); +} + +} // namespace mbgl diff --git a/src/mbgl/util/mat2.hpp b/src/mbgl/util/mat2.hpp index 6a25ef0f1e..c463202daa 100644 --- a/src/mbgl/util/mat2.hpp +++ b/src/mbgl/util/mat2.hpp @@ -26,7 +26,7 @@ namespace mbgl { -typedef std::array<double, 4> mat2; +using mat2 = std::array<double, 4>; namespace matrix { diff --git a/src/mbgl/util/mat4.cpp b/src/mbgl/util/mat4.cpp index d3d3617b7b..0ad0d371e5 100644 --- a/src/mbgl/util/mat4.cpp +++ b/src/mbgl/util/mat4.cpp @@ -336,10 +336,11 @@ void multiply(mat4& out, const mat4& a, const mat4& b) { } void transformMat4(vec4& out, const vec4& a, const mat4& m) { - out[0] = m[0] * a[0] + m[4] * a[1] + m[8] * a[2] + m[12] * a[3]; - out[1] = m[1] * a[0] + m[5] * a[1] + m[9] * a[2] + m[13] * a[3]; - out[2] = m[2] * a[0] + m[6] * a[1] + m[10] * a[2] + m[14] * a[3]; - out[3] = m[3] * a[0] + m[7] * a[1] + m[11] * a[2] + m[15] * a[3]; + double x = a[0], y = a[1], z = a[2], w = a[3]; + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; } } // namespace matrix diff --git a/src/mbgl/util/math.hpp b/src/mbgl/util/math.hpp index f969ecaedd..c18ce0c254 100644 --- a/src/mbgl/util/math.hpp +++ b/src/mbgl/util/math.hpp @@ -77,9 +77,9 @@ T mag(const S& a) { return std::sqrt(a.x * a.x + a.y * a.y); } -template <typename S> +template <typename T = double, typename S> S unit(const S& a) { - auto magnitude = mag(a); + auto magnitude = mag<T>(a); if (magnitude == 0) { return a; } @@ -106,5 +106,18 @@ T smoothstep(T edge0, T edge1, T x) { return t * t * (T(3) - T(2) * t); } +template <typename T> +inline T division(const T dividend, const T divisor, const T nan) { + if (divisor == 0) { + if (dividend == 0) { + return nan; + } else { + return ::copysign(std::numeric_limits<T>::infinity(), dividend); + } + } else { + return dividend / divisor; + } +} + } // namespace util } // namespace mbgl diff --git a/src/mbgl/util/offscreen_texture.cpp b/src/mbgl/util/offscreen_texture.cpp index fe24774b7c..339e74b250 100644 --- a/src/mbgl/util/offscreen_texture.cpp +++ b/src/mbgl/util/offscreen_texture.cpp @@ -11,20 +11,22 @@ OffscreenTexture& OffscreenTexture::operator=(OffscreenTexture&&) = default; class OffscreenTexture::Impl { public: - Impl(gl::Context& context_, const Size size_, OffscreenTextureAttachment type_) - : context(context_), size(std::move(size_)), type(type_) { + Impl(gl::Context& context_, const Size size_) + : context(context_), size(std::move(size_)) { + assert(!size.isEmpty()); + } + Impl(gl::Context& context_, + const Size size_, + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& depth_) + : context(context_), size(std::move(size_)), depth(&depth_) { assert(!size.isEmpty()); } void bind() { if (!framebuffer) { texture = context.createTexture(size, gl::TextureFormat::RGBA); - - if (type == OffscreenTextureAttachment::Depth) { - gl::Renderbuffer<gl::RenderbufferType::DepthComponent> depth = - context.createRenderbuffer<gl::RenderbufferType::DepthComponent>(size); - framebuffer = context.createFramebuffer(*texture, depth); - + if (depth) { + framebuffer = context.createFramebuffer(*texture, *depth); } else { framebuffer = context.createFramebuffer(*texture); } @@ -32,7 +34,8 @@ public: context.bindFramebuffer = framebuffer->framebuffer; } - context.activeTexture = 0; + context.activeTextureUnit = 0; + context.scissorTest = false; context.viewport = { 0, 0, size }; } @@ -52,15 +55,21 @@ public: private: gl::Context& context; const Size size; - OffscreenTextureAttachment type; optional<gl::Framebuffer> framebuffer; optional<gl::Texture> texture; + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>* depth = nullptr; }; OffscreenTexture::OffscreenTexture(gl::Context& context, + const Size size) + : impl(std::make_unique<Impl>(context, std::move(size))) { + assert(!size.isEmpty()); +} + +OffscreenTexture::OffscreenTexture(gl::Context& context, const Size size, - OffscreenTextureAttachment type) - : impl(std::make_unique<Impl>(context, std::move(size), type)) { + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>& renderbuffer) + : impl(std::make_unique<Impl>(context, std::move(size), renderbuffer)) { assert(!size.isEmpty()); } diff --git a/src/mbgl/util/offscreen_texture.hpp b/src/mbgl/util/offscreen_texture.hpp index ae96286340..7f7e0f0338 100644 --- a/src/mbgl/util/offscreen_texture.hpp +++ b/src/mbgl/util/offscreen_texture.hpp @@ -1,6 +1,5 @@ #pragma once -#include <mbgl/map/view.hpp> #include <mbgl/util/image.hpp> namespace mbgl { @@ -10,21 +9,18 @@ class Context; class Texture; } // namespace gl -enum class OffscreenTextureAttachment { - None, - Depth, -}; - -class OffscreenTexture : public View { +class OffscreenTexture { public: OffscreenTexture(gl::Context&, - Size size = { 256, 256 }, - OffscreenTextureAttachment type = OffscreenTextureAttachment::None); + Size size = { 256, 256 }); + OffscreenTexture(gl::Context&, + Size size, + gl::Renderbuffer<gl::RenderbufferType::DepthComponent>&); ~OffscreenTexture(); OffscreenTexture(OffscreenTexture&&); OffscreenTexture& operator=(OffscreenTexture&&); - void bind() override; + void bind(); PremultipliedImage readStillImage(); diff --git a/src/mbgl/util/premultiply.cpp b/src/mbgl/util/premultiply.cpp index 219273d7cc..d9fb2480de 100644 --- a/src/mbgl/util/premultiply.cpp +++ b/src/mbgl/util/premultiply.cpp @@ -9,6 +9,7 @@ PremultipliedImage premultiply(UnassociatedImage&& src) { PremultipliedImage dst; dst.size = src.size; + src.size = { 0, 0 }; dst.data = std::move(src.data); uint8_t* data = dst.data.get(); @@ -29,6 +30,7 @@ UnassociatedImage unpremultiply(PremultipliedImage&& src) { UnassociatedImage dst; dst.size = src.size; + src.size = { 0, 0 }; dst.data = std::move(src.data); uint8_t* data = dst.data.get(); diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp deleted file mode 100644 index 184c6a8a12..0000000000 --- a/src/mbgl/util/thread.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#pragma once - -#include <cassert> -#include <future> -#include <thread> -#include <atomic> -#include <utility> -#include <functional> - -#include <mbgl/util/run_loop.hpp> -#include <mbgl/util/thread_context.hpp> -#include <mbgl/util/platform.hpp> -#include <mbgl/util/util.hpp> - -namespace mbgl { -namespace util { - -// Manages a thread with Object. - -// Upon creation of this object, it launches a thread, creates an object of type Object in that -// thread, and then calls .start(); on that object. When the Thread<> object is destructed, the -// Object's .stop() function is called, and the destructor waits for thread termination. The -// Thread<> constructor blocks until the thread and the Object are fully created, so after the -// object creation, it's safe to obtain the Object stored in this thread. - -template <class Object> -class Thread { -public: - template <class... Args> - Thread(const ThreadContext&, Args&&... args); - ~Thread(); - - // Invoke object->fn(args...) asynchronously. - template <typename Fn, class... Args> - void invoke(Fn fn, Args&&... args) { - loop->invoke(bind(fn), std::forward<Args>(args)...); - } - - // Invoke object->fn(args...) asynchronously. The final argument to fn must be a callback. - // The provided callback is wrapped such that it is invoked, in the current thread (which - // must have a RunLoop), once for each time the invocation of fn invokes the wrapper, each - // time forwarding the passed arguments, until such time as the AsyncRequest is cancelled. - template <typename Fn, class... Args> - std::unique_ptr<AsyncRequest> - invokeWithCallback(Fn fn, Args&&... args) { - return loop->invokeWithCallback(bind(fn), std::forward<Args>(args)...); - } - - // Invoke object->fn(args...) asynchronously, but wait for the result. - template <typename Fn, class... Args> - auto invokeSync(Fn fn, Args&&... args) { - assert(!paused); - - using R = std::result_of_t<Fn(Object, Args&&...)>; - std::packaged_task<R ()> task(std::bind(fn, object, args...)); - std::future<R> future = task.get_future(); - loop->invoke(std::move(task)); - return future.get(); - } - - void pause() { - MBGL_VERIFY_THREAD(tid); - - assert(!paused); - - paused = std::make_unique<std::promise<void>>(); - resumed = std::make_unique<std::promise<void>>(); - - auto pausing = paused->get_future(); - - loop->invoke([this] { - auto resuming = resumed->get_future(); - paused->set_value(); - resuming.get(); - }); - - pausing.get(); - } - - void resume() { - MBGL_VERIFY_THREAD(tid); - - assert(paused); - - resumed->set_value(); - - resumed.reset(); - paused.reset(); - } - -private: - MBGL_STORE_THREAD(tid); - - Thread(const Thread&) = delete; - Thread(Thread&&) = delete; - Thread& operator=(const Thread&) = delete; - Thread& operator=(Thread&&) = delete; - - template <typename Fn> - auto bind(Fn fn) { - return [fn, this] (auto &&... args) { - return (object->*fn)(std::forward<decltype(args)>(args)...); - }; - } - - template <typename P, std::size_t... I> - void run(P&& params, std::index_sequence<I...>); - - std::promise<void> running; - std::promise<void> joinable; - - std::unique_ptr<std::promise<void>> paused; - std::unique_ptr<std::promise<void>> resumed; - - std::thread thread; - - Object* object = nullptr; - RunLoop* loop = nullptr; -}; - -template <class Object> -template <class... Args> -Thread<Object>::Thread(const ThreadContext& context, Args&&... args) { - // Note: We're using std::tuple<> to store the arguments because GCC 4.9 has a bug - // when expanding parameters packs captured in lambdas. - std::tuple<Args...> params = std::forward_as_tuple(::std::forward<Args>(args)...); - - thread = std::thread([&] { - platform::setCurrentThreadName(context.name); - - if (context.priority == ThreadPriority::Low) { - platform::makeThreadLowPriority(); - } - - run(std::move(params), std::index_sequence_for<Args...>{}); - }); - - running.get_future().get(); -} - -template <class Object> -template <typename P, std::size_t... I> -void Thread<Object>::run(P&& params, std::index_sequence<I...>) { - RunLoop loop_(RunLoop::Type::New); - loop = &loop_; - - Object object_(std::get<I>(std::forward<P>(params))...); - object = &object_; - - running.set_value(); - loop_.run(); - - loop = nullptr; - object = nullptr; - - joinable.get_future().get(); -} - -template <class Object> -Thread<Object>::~Thread() { - MBGL_VERIFY_THREAD(tid); - - if (paused) { - resume(); - } - - loop->stop(); - joinable.set_value(); - thread.join(); -} - -} // namespace util -} // namespace mbgl diff --git a/src/mbgl/util/thread_context.cpp b/src/mbgl/util/thread_context.cpp deleted file mode 100644 index fe64c2a686..0000000000 --- a/src/mbgl/util/thread_context.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include <mbgl/util/thread_context.hpp> -#include <utility> - -namespace mbgl { -namespace util { - -ThreadContext::ThreadContext(std::string name_, ThreadPriority priority_) - : name(std::move(name_)), - priority(priority_) { -} - -} // namespace util -} // namespace mbgl diff --git a/src/mbgl/util/thread_context.hpp b/src/mbgl/util/thread_context.hpp deleted file mode 100644 index a51dede404..0000000000 --- a/src/mbgl/util/thread_context.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <string> - -namespace mbgl { -namespace util { - -enum class ThreadPriority : bool { - Regular, - Low, -}; - -struct ThreadContext { -public: - ThreadContext(std::string name, ThreadPriority priority = ThreadPriority::Regular); - - std::string name; - ThreadPriority priority; -}; - -} // namespace util -} // namespace mbgl diff --git a/src/mbgl/util/thread_local.hpp b/src/mbgl/util/thread_local.hpp index 9fddbd5bbc..b0e26356b4 100644 --- a/src/mbgl/util/thread_local.hpp +++ b/src/mbgl/util/thread_local.hpp @@ -1,12 +1,8 @@ #pragma once -#include <mbgl/util/logging.hpp> #include <mbgl/util/noncopyable.hpp> -#include <cassert> -#include <stdexcept> - -#include <pthread.h> +#include <memory> namespace mbgl { namespace util { @@ -14,40 +10,20 @@ namespace util { template <class T> class ThreadLocal : public noncopyable { public: - ThreadLocal() { - int ret = pthread_key_create(&key, [](void *ptr) { - delete reinterpret_cast<T *>(ptr); - }); - - if (ret) { - throw std::runtime_error("Failed to init local storage key."); - } - } - - ~ThreadLocal() { - if (pthread_key_delete(key)) { - Log::Error(Event::General, "Failed to delete local storage key."); - assert(false); - } + ThreadLocal(T* val) { + ThreadLocal(); + set(val); } - T* get() { - T* ret = reinterpret_cast<T*>(pthread_getspecific(key)); - if (!ret) { - return nullptr; - } + ThreadLocal(); + ~ThreadLocal(); - return ret; - } - - void set(T* ptr) { - if (pthread_setspecific(key, ptr)) { - throw std::runtime_error("Failed to set local storage."); - } - } + T* get(); + void set(T* ptr); private: - pthread_key_t key; + class Impl; + std::unique_ptr<Impl> impl; }; } // namespace util diff --git a/src/mbgl/util/tile_cover.cpp b/src/mbgl/util/tile_cover.cpp index b53e91162c..a5a1b1d70c 100644 --- a/src/mbgl/util/tile_cover.cpp +++ b/src/mbgl/util/tile_cover.cpp @@ -169,5 +169,26 @@ std::vector<UnwrappedTileID> tileCover(const TransformState& state, int32_t z) { z); } +// Taken from https://github.com/mapbox/sphericalmercator#xyzbbox-zoom-tms_style-srs +// Computes the projected tiles for the lower left and upper right points of the bounds +// and uses that to compute the tile cover count +uint64_t tileCount(const LatLngBounds& bounds, uint8_t zoom, uint16_t tileSize_){ + + auto sw = Projection::project(bounds.southwest().wrapped(), zoom, tileSize_); + auto ne = Projection::project(bounds.northeast().wrapped(), zoom, tileSize_); + + auto x1 = floor(sw.x/ tileSize_); + auto x2 = floor((ne.x - 1) / tileSize_); + auto y1 = floor(sw.y/ tileSize_); + auto y2 = floor((ne.y - 1) / tileSize_); + + auto minX = std::fmax(std::min(x1, x2), 0); + auto maxX = std::max(x1, x2); + auto minY = (std::pow(2, zoom) - 1) - std::max(y1, y2); + auto maxY = (std::pow(2, zoom) - 1) - std::fmax(std::min(y1, y2), 0); + + return (maxX - minX + 1) * (maxY - minY + 1); +} + } // namespace util } // namespace mbgl diff --git a/src/mbgl/util/tile_cover.hpp b/src/mbgl/util/tile_cover.hpp index 2d32d8bf41..3c7a4ee44a 100644 --- a/src/mbgl/util/tile_cover.hpp +++ b/src/mbgl/util/tile_cover.hpp @@ -18,5 +18,8 @@ int32_t coveringZoomLevel(double z, SourceType type, uint16_t tileSize); std::vector<UnwrappedTileID> tileCover(const TransformState&, int32_t z); std::vector<UnwrappedTileID> tileCover(const LatLngBounds&, int32_t z); +// Compute only the count of tiles needed for tileCover +uint64_t tileCount(const LatLngBounds&, uint8_t z, uint16_t tileSize); + } // namespace util } // namespace mbgl diff --git a/src/mbgl/util/work_queue.cpp b/src/mbgl/util/work_queue.cpp deleted file mode 100644 index d0033e3ca2..0000000000 --- a/src/mbgl/util/work_queue.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include <mbgl/util/work_queue.hpp> -#include <mbgl/util/run_loop.hpp> - -#include <cassert> - -namespace mbgl { -namespace util { - -WorkQueue::WorkQueue() : runLoop(RunLoop::Get()) { -} - -WorkQueue::~WorkQueue() { - assert(runLoop == RunLoop::Get()); - - // Cancel all pending AsyncRequests. - while (!queue.empty()) { - queue.pop(); - } -} - -void WorkQueue::push(std::function<void()>&& fn) { - std::lock_guard<std::mutex> lock(queueMutex); - - auto workRequest = runLoop->invokeCancellable(std::bind(&WorkQueue::pop, this, std::move(fn))); - queue.push(std::move(workRequest)); -} - -void WorkQueue::pop(const std::function<void()>& fn) { - assert(runLoop == RunLoop::Get()); - - fn(); - - std::lock_guard<std::mutex> lock(queueMutex); - queue.pop(); -} - -} // namespace util -} // namespace mbgl diff --git a/src/mbgl/util/work_queue.hpp b/src/mbgl/util/work_queue.hpp deleted file mode 100644 index 3f6328fb57..0000000000 --- a/src/mbgl/util/work_queue.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include <mbgl/util/noncopyable.hpp> -#include <mbgl/util/async_request.hpp> - -#include <functional> -#include <memory> -#include <mutex> -#include <queue> - -namespace mbgl { -namespace util { - -class RunLoop; - -// The WorkQueue will manage a queue of closures -// and it will make sure they get executed on the -// thread that created the WorkQueue. All pending -// works are canceled when the queue gets destructed. -class WorkQueue : private util::noncopyable { -public: - WorkQueue(); - ~WorkQueue(); - - // Push a closure to the queue. It is advised to - // only push tasks calling functions on the object - // that owns the queue to avoid use after free errors. - void push(std::function<void()>&&); - -private: - void pop(const std::function<void()>&); - - std::queue<std::unique_ptr<AsyncRequest>> queue; - std::mutex queueMutex; - - RunLoop* runLoop; -}; - -} // namespace util -} // namespace mbgl |