diff options
author | m-stephen <truestyle2005@163.com> | 2019-11-01 10:27:03 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-01 10:27:03 +0800 |
commit | 9427c04bc709c39f7e083b6d1597aaf33af8c302 (patch) | |
tree | 224fa2bffbc6a81b447c76b98e4c13a51baadc29 /platform/default | |
parent | fc2c02bbc6abaef52077fe5e9e78f772e6009967 (diff) | |
parent | 5b38cfee18800cbb3c6a3186882744592662c3d6 (diff) | |
download | qtlocation-mapboxgl-9427c04bc709c39f7e083b6d1597aaf33af8c302.tar.gz |
Merge branch 'master' into stephen-improve-accuracy-for-cameraupstream/stephen-improve-accuracy-for-camera
Diffstat (limited to 'platform/default')
17 files changed, 362 insertions, 152 deletions
diff --git a/platform/default/include/mbgl/gfx/headless_backend.hpp b/platform/default/include/mbgl/gfx/headless_backend.hpp index 325422323a..5167e6a465 100644 --- a/platform/default/include/mbgl/gfx/headless_backend.hpp +++ b/platform/default/include/mbgl/gfx/headless_backend.hpp @@ -15,11 +15,13 @@ namespace gfx { // of readStillImage. class HeadlessBackend : public gfx::Renderable { public: + enum class SwapBehaviour { NoFlush, Flush }; + // Factory. - static std::unique_ptr<HeadlessBackend> - Create(const Size size = { 256, 256 }, - const gfx::ContextMode contextMode = gfx::ContextMode::Unique) { - return Backend::Create<HeadlessBackend, Size, gfx::ContextMode>(size, contextMode); + static std::unique_ptr<HeadlessBackend> Create(const Size size = {256, 256}, + SwapBehaviour swapBehavior = SwapBehaviour::NoFlush, + const gfx::ContextMode contextMode = gfx::ContextMode::Unique) { + return Backend::Create<HeadlessBackend, Size, SwapBehaviour, gfx::ContextMode>(size, swapBehavior, contextMode); } virtual PremultipliedImage readStillImage() = 0; diff --git a/platform/default/include/mbgl/gfx/headless_frontend.hpp b/platform/default/include/mbgl/gfx/headless_frontend.hpp index 8f7a7bf202..8a98b4112d 100644 --- a/platform/default/include/mbgl/gfx/headless_frontend.hpp +++ b/platform/default/include/mbgl/gfx/headless_frontend.hpp @@ -1,11 +1,13 @@ #pragma once +#include <mbgl/gfx/headless_backend.hpp> +#include <mbgl/gfx/rendering_stats.hpp> #include <mbgl/map/camera.hpp> #include <mbgl/renderer/renderer_frontend.hpp> -#include <mbgl/gfx/headless_backend.hpp> #include <mbgl/util/async_task.hpp> #include <mbgl/util/optional.hpp> +#include <atomic> #include <memory> namespace mbgl { @@ -16,11 +18,18 @@ class TransformState; class HeadlessFrontend : public RendererFrontend { public: + struct RenderResult { + PremultipliedImage image; + gfx::RenderingStats stats; + }; + HeadlessFrontend(float pixelRatio_, + gfx::HeadlessBackend::SwapBehaviour swapBehviour = gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode mode = gfx::ContextMode::Unique, const optional<std::string> localFontFamily = {}); HeadlessFrontend(Size, float pixelRatio_, + gfx::HeadlessBackend::SwapBehaviour swapBehviour = gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode mode = gfx::ContextMode::Unique, const optional<std::string> localFontFamily = {}); ~HeadlessFrontend() override; @@ -29,6 +38,7 @@ public: void update(std::shared_ptr<UpdateParameters>) override; void setObserver(RendererObserver&) override; + double getFrameTime() const; Size getSize() const; void setSize(Size); @@ -44,7 +54,8 @@ public: LatLng latLngForPixel(const ScreenCoordinate&); PremultipliedImage readStillImage(); - PremultipliedImage render(Map&); + RenderResult render(Map&); + void renderOnce(Map&); optional<TransformState> getTransformState() const; @@ -52,6 +63,7 @@ private: Size size; float pixelRatio; + std::atomic<double> frameTime; std::unique_ptr<gfx::HeadlessBackend> backend; util::AsyncTask asyncInvalidate; diff --git a/platform/default/include/mbgl/gl/headless_backend.hpp b/platform/default/include/mbgl/gl/headless_backend.hpp index 8aefb5ff6c..b77f1b756f 100644 --- a/platform/default/include/mbgl/gl/headless_backend.hpp +++ b/platform/default/include/mbgl/gl/headless_backend.hpp @@ -10,13 +10,17 @@ namespace gl { class HeadlessBackend final : public gl::RendererBackend, public gfx::HeadlessBackend { public: - HeadlessBackend(Size = { 256, 256 }, gfx::ContextMode = gfx::ContextMode::Unique); + HeadlessBackend(Size = {256, 256}, + SwapBehaviour = SwapBehaviour::NoFlush, + gfx::ContextMode = gfx::ContextMode::Unique); ~HeadlessBackend() override; void updateAssumedState() override; gfx::Renderable& getDefaultRenderable() override; PremultipliedImage readStillImage() override; RendererBackend* getRendererBackend() override; + void swap(); + class Impl { public: virtual ~Impl() = default; @@ -37,6 +41,7 @@ private: private: std::unique_ptr<Impl> impl; bool active = false; + SwapBehaviour swapBehaviour = SwapBehaviour::NoFlush; }; } // namespace gl diff --git a/platform/default/include/mbgl/storage/offline_database.hpp b/platform/default/include/mbgl/storage/offline_database.hpp index 96b867eaa6..e599094a6d 100644 --- a/platform/default/include/mbgl/storage/offline_database.hpp +++ b/platform/default/include/mbgl/storage/offline_database.hpp @@ -108,6 +108,7 @@ private: void migrateToVersion6(); void cleanup(); bool disabled(); + void vacuum(); mapbox::sqlite::Statement& getStatement(const char *); diff --git a/platform/default/include/mbgl/storage/offline_schema.hpp b/platform/default/include/mbgl/storage/offline_schema.hpp index e177d0dbd3..77c66b7d15 100644 --- a/platform/default/include/mbgl/storage/offline_schema.hpp +++ b/platform/default/include/mbgl/storage/offline_schema.hpp @@ -1,7 +1,7 @@ #pragma once // THIS IS A GENERATED FILE; EDIT offline_schema.sql INSTEAD -// To regenerate, run `node platform/default/mbgl/storage/offline_schema.js` +// To regenerate, run `node platform/default/include/mbgl/storage/offline_schema.js` namespace mbgl { diff --git a/platform/default/include/mbgl/storage/offline_schema.js b/platform/default/include/mbgl/storage/offline_schema.js index fdb7dc6405..a58e216d4a 100644..100755 --- a/platform/default/include/mbgl/storage/offline_schema.js +++ b/platform/default/include/mbgl/storage/offline_schema.js @@ -1,13 +1,15 @@ +#!/usr/bin/env node + var fs = require('fs'); -fs.writeFileSync('platform/default/mbgl/storage/offline_schema.hpp', `#pragma once +fs.writeFileSync('platform/default/include/mbgl/storage/offline_schema.hpp', `#pragma once // THIS IS A GENERATED FILE; EDIT offline_schema.sql INSTEAD -// To regenerate, run \`node platform/default/mbgl/storage/offline_schema.js\` +// To regenerate, run \`node platform/default/include/mbgl/storage/offline_schema.js\` namespace mbgl { static constexpr const char* offlineDatabaseSchema = -${fs.readFileSync('platform/default/mbgl/storage/offline_schema.sql', 'utf8') +${fs.readFileSync('platform/default/include/mbgl/storage/offline_schema.sql', 'utf8') .replace(/ *--.*/g, '') .split('\n') .filter(a => a) diff --git a/platform/default/include/mbgl/storage/offline_schema.sql b/platform/default/include/mbgl/storage/offline_schema.sql index 722b0e0451..93f6f2a5ce 100644 --- a/platform/default/include/mbgl/storage/offline_schema.sql +++ b/platform/default/include/mbgl/storage/offline_schema.sql @@ -1,55 +1,159 @@ -CREATE TABLE resources ( -- Generic table for style, source, sprite, and glyph resources. - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - url TEXT NOT NULL, - kind INTEGER NOT NULL, - expires INTEGER, - modified INTEGER, - etag TEXT, - data BLOB, - compressed INTEGER NOT NULL DEFAULT 0, - accessed INTEGER NOT NULL, - must_revalidate INTEGER NOT NULL DEFAULT 0, +-- +-- Table containing the style, source, sprite, and glyph +-- resources. Essentially everything that is not a tile. +-- +CREATE TABLE resources ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, -- Primary key. + + url TEXT NOT NULL, -- The URL of the resource without the access token. If a Mapbox + -- resource, will be stored using the mapbox:// schema. Must be + -- unique and that is enforced by the database schema. + + kind INTEGER NOT NULL, -- Type of the resource, taken from Resource::Kind enumeration: + -- style = 1 + -- source = 2 + -- tile = 3 + -- glyphs = 4 + -- sprite image = 5 + -- sprite JSON = 6 + -- image = 7 + + expires INTEGER, -- Expiration time. The resource will be refreshed after this + -- expiration is reached. + + modified INTEGER, -- Last time the resource was modified. + + etag TEXT, -- Checksum used for cache optimization. If, when refreshing the + -- resource, it matches the etag on the server, the resource will + -- not get re-downloaded. See: + -- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag + + data BLOB, -- Contents of the resource. + + compressed INTEGER NOT NULL DEFAULT 0, -- If the resource is compressed with Deflate or not. Compression is + -- optional and should be used when the compression ratio is + -- significant. Using compression will make decoding time slower + -- because it will add an extra decompression step. + + accessed INTEGER NOT NULL, -- Last time the resource was used by GL Native. Useful for when + -- evicting the least used resources from the cache. + + must_revalidate INTEGER NOT NULL DEFAULT 0, -- When set to true, the resource will not be used unless it gets + -- first revalidated by the server. UNIQUE (url) ); +-- +-- Table containing all tiles, both vector and raster. +-- CREATE TABLE tiles ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - url_template TEXT NOT NULL, - pixel_ratio INTEGER NOT NULL, - z INTEGER NOT NULL, - x INTEGER NOT NULL, - y INTEGER NOT NULL, - expires INTEGER, - modified INTEGER, - etag TEXT, - data BLOB, - compressed INTEGER NOT NULL DEFAULT 0, - accessed INTEGER NOT NULL, - must_revalidate INTEGER NOT NULL DEFAULT 0, + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, -- Primary key. + + url_template TEXT NOT NULL, -- The URL of the resource without the access token and without + -- the tiles id substituted. Mapbox tiles will be stored using + -- the mapbox:// schema. Example: + -- mapbox://tiles/user.dataset/{z}/{x}/{y}.vector.pbf + + pixel_ratio INTEGER NOT NULL, -- The tile pixel ratio, typically 1 for vector tiles. + + z INTEGER NOT NULL, -- The zoom level of the tile. + + x INTEGER NOT NULL, -- The x position of the tile on the tile grid. + + y INTEGER NOT NULL, -- The y position of the tile on the tile grid. + + expires INTEGER, -- Expiration time. The tile will be refreshed after this + -- expiration is reached. Expired tiles can still be rendered, + -- unless must_revalidate is set to true. If an expired tile + -- gets rendered, it will be replaced by a newer version as soon + -- as the network request with a new tile arrives. + + modified INTEGER, -- Last time the tile was modified. + + etag TEXT, -- Checksum used for cache optimization. If, when refreshing the + -- tile, it matches the etag on the server, the tile will not + -- get re-downloaded. See: + -- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag + + data BLOB, -- Contents of the tile. + + compressed INTEGER NOT NULL DEFAULT 0, -- If the tile is compressed with Deflate or not. Compression is + -- optional and should be used when the compression ratio is + -- significant. Using compression will make decoding time slower + -- because it will add an extra decompression step. + + accessed INTEGER NOT NULL, -- Last time the tile was used by GL Native. Useful for when + -- evicting the least used tiles from the cache. + + must_revalidate INTEGER NOT NULL DEFAULT 0, -- When set to true, the tile will not be used unless it gets + -- first revalidated by the server. UNIQUE (url_template, pixel_ratio, z, x, y) ); +-- +-- Regions define the offline regions, which could be a GeoJSON geometry, +-- or a bounding box like this example: +-- +-- { +-- "bounds": [ +-- 37.2, +-- -122.8, +-- 38.1, +-- -121.7 +-- ], +-- "include_ideographs": false, +-- "max_zoom": 15.0, +-- "min_zoom": 0.0, +-- "pixel_ratio": 1.0, +-- "style_url": "mapbox://styles/mapbox/streets-v11" +-- } +-- +-- The semantic definition of the region is up to the user and +-- it could be a city, a country or an arbitrary bounding box. +-- +-- Regions can overlap, which will cause them to share resources +-- when it is the case. +-- +-- "include_ideographs" is set to true when CJK characters are +-- include on the offline package. By default, CJK is rendered +-- by GL Native client side using local fonts. Downloading CJK +-- will increase the size of the database considerably. +-- CREATE TABLE regions ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - definition TEXT NOT NULL, -- JSON formatted definition of region. Regions may be of variant types: - -- e.g. bbox and zoom range, route path, flyTo parameters, etc. Note that - -- the set of tiles required for a region may span multiple sources. - description BLOB -- User provided data in user-defined format + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, -- Primary key. + + definition TEXT NOT NULL, -- JSON formatted definition of a region, a bounding box + -- or a GeoJSON geometry. See https://geojson.org. + + description BLOB -- User provided data in user-defined format. ); +-- +-- Table mapping resources to regions. A resource +-- might be part of many regions. Resources without +-- regions are part of the ambient cache. +-- CREATE TABLE region_resources ( region_id INTEGER NOT NULL REFERENCES regions(id) ON DELETE CASCADE, resource_id INTEGER NOT NULL REFERENCES resources(id), UNIQUE (region_id, resource_id) ); +-- +-- Table mapping tiles to regions. A tile might +-- be part of many regions, meaning that regions might +-- overlap efficiently. Tiles without regions are part +-- of the ambient cache. +-- CREATE TABLE region_tiles ( region_id INTEGER NOT NULL REFERENCES regions(id) ON DELETE CASCADE, tile_id INTEGER NOT NULL REFERENCES tiles(id), UNIQUE (region_id, tile_id) ); --- Indexes for efficient eviction queries +-- +-- Indexes for efficient eviction queries. +-- CREATE INDEX resources_accessed ON resources (accessed); diff --git a/platform/default/src/mbgl/gfx/headless_frontend.cpp b/platform/default/src/mbgl/gfx/headless_frontend.cpp index 287567adbd..5235b2f408 100644 --- a/platform/default/src/mbgl/gfx/headless_frontend.cpp +++ b/platform/default/src/mbgl/gfx/headless_frontend.cpp @@ -1,43 +1,51 @@ -#include <mbgl/gfx/headless_frontend.hpp> #include <mbgl/gfx/backend_scope.hpp> +#include <mbgl/gfx/context.hpp> +#include <mbgl/gfx/headless_frontend.hpp> +#include <mbgl/map/map.hpp> +#include <mbgl/map/transform_state.hpp> #include <mbgl/renderer/renderer.hpp> #include <mbgl/renderer/renderer_state.hpp> #include <mbgl/renderer/update_parameters.hpp> -#include <mbgl/map/map.hpp> -#include <mbgl/map/transform_state.hpp> +#include <mbgl/util/monotonic_timer.hpp> #include <mbgl/util/run_loop.hpp> namespace mbgl { HeadlessFrontend::HeadlessFrontend(float pixelRatio_, + gfx::HeadlessBackend::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode, const optional<std::string> localFontFamily) - : HeadlessFrontend( - { 256, 256 }, pixelRatio_, contextMode, localFontFamily) { -} + : HeadlessFrontend({256, 256}, pixelRatio_, swapBehavior, contextMode, localFontFamily) {} HeadlessFrontend::HeadlessFrontend(Size size_, float pixelRatio_, + gfx::HeadlessBackend::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode, const optional<std::string> localFontFamily) : size(size_), pixelRatio(pixelRatio_), - backend(gfx::HeadlessBackend::Create({ static_cast<uint32_t>(size.width * pixelRatio), - static_cast<uint32_t>(size.height * pixelRatio) }, contextMode)), - asyncInvalidate([this] { - if (renderer && updateParameters) { - gfx::BackendScope guard { *getBackend() }; - - // onStyleImageMissing might be called during a render. The user implemented method - // could trigger a call to MGLRenderFrontend#update which overwrites `updateParameters`. - // Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is - // still using them. - auto updateParameters_ = updateParameters; - renderer->render(*updateParameters_); - } - }), - renderer(std::make_unique<Renderer>(*getBackend(), pixelRatio, localFontFamily)) { -} + frameTime(0), + backend(gfx::HeadlessBackend::Create( + {static_cast<uint32_t>(size.width * pixelRatio), static_cast<uint32_t>(size.height * pixelRatio)}, + swapBehavior, + contextMode)), + asyncInvalidate([this] { + if (renderer && updateParameters) { + auto startTime = mbgl::util::MonotonicTimer::now(); + gfx::BackendScope guard{*getBackend()}; + + // onStyleImageMissing might be called during a render. The user implemented method + // could trigger a call to MGLRenderFrontend#update which overwrites `updateParameters`. + // Copy the shared pointer here so that the parameters aren't destroyed while `render(...)` is + // still using them. + auto updateParameters_ = updateParameters; + renderer->render(*updateParameters_); + + auto endTime = mbgl::util::MonotonicTimer::now(); + frameTime = (endTime - startTime).count(); + } + }), + renderer(std::make_unique<Renderer>(*getBackend(), pixelRatio, localFontFamily)) {} HeadlessFrontend::~HeadlessFrontend() = default; @@ -56,6 +64,10 @@ void HeadlessFrontend::setObserver(RendererObserver& observer_) { renderer->setObserver(&observer_); } +double HeadlessFrontend::getFrameTime() const { + return frameTime; +} + Size HeadlessFrontend::getSize() const { return size; } @@ -128,29 +140,34 @@ PremultipliedImage HeadlessFrontend::readStillImage() { return backend->readStillImage(); } -PremultipliedImage HeadlessFrontend::render(Map& map) { - PremultipliedImage result; +HeadlessFrontend::RenderResult HeadlessFrontend::render(Map& map) { + HeadlessFrontend::RenderResult result; std::exception_ptr error; map.renderStill([&](std::exception_ptr e) { if (e) { error = e; } else { - result = backend->readStillImage(); + result.image = backend->readStillImage(); + result.stats = getBackend()->getContext().renderingStats(); } }); - while (!result.valid() && !error) { + while (!result.image.valid() && !error) { util::RunLoop::Get()->runOnce(); } if (error) { std::rethrow_exception(error); } - + return result; } +void HeadlessFrontend::renderOnce(Map&) { + util::RunLoop::Get()->runOnce(); +} + optional<TransformState> HeadlessFrontend::getTransformState() const { if (updateParameters) { return updateParameters->transformState; diff --git a/platform/default/src/mbgl/gl/headless_backend.cpp b/platform/default/src/mbgl/gl/headless_backend.cpp index 732e4babae..697c560f76 100644 --- a/platform/default/src/mbgl/gl/headless_backend.cpp +++ b/platform/default/src/mbgl/gl/headless_backend.cpp @@ -12,12 +12,12 @@ namespace gl { class HeadlessRenderableResource final : public gl::RenderableResource { public: - HeadlessRenderableResource(gl::Context& context_, Size size_) - : context(context_), + HeadlessRenderableResource(HeadlessBackend& backend_, gl::Context& context_, Size size_) + : backend(backend_), + context(context_), color(context.createRenderbuffer<gfx::RenderbufferPixelType::RGBA>(size_)), depthStencil(context.createRenderbuffer<gfx::RenderbufferPixelType::DepthStencil>(size_)), - framebuffer(context.createFramebuffer(color, depthStencil)) { - } + framebuffer(context.createFramebuffer(color, depthStencil)) {} void bind() override { context.bindFramebuffer = framebuffer.framebuffer; @@ -25,18 +25,22 @@ public: context.viewport = { 0, 0, framebuffer.size }; } + void swap() override { backend.swap(); } + + HeadlessBackend& backend; gl::Context& context; gfx::Renderbuffer<gfx::RenderbufferPixelType::RGBA> color; gfx::Renderbuffer<gfx::RenderbufferPixelType::DepthStencil> depthStencil; gl::Framebuffer framebuffer; }; -HeadlessBackend::HeadlessBackend(const Size size_, const gfx::ContextMode contextMode_) - : mbgl::gl::RendererBackend(contextMode_), mbgl::gfx::HeadlessBackend(size_) { -} +HeadlessBackend::HeadlessBackend(const Size size_, + gfx::HeadlessBackend::SwapBehaviour swapBehaviour_, + const gfx::ContextMode contextMode_) + : mbgl::gl::RendererBackend(contextMode_), mbgl::gfx::HeadlessBackend(size_), swapBehaviour(swapBehaviour_) {} HeadlessBackend::~HeadlessBackend() { - gfx::BackendScope guard { *this }; + gfx::BackendScope guard{*this}; resource.reset(); // Explicitly reset the context so that it is destructed and cleaned up before we destruct // the impl object. @@ -67,11 +71,15 @@ void HeadlessBackend::deactivate() { gfx::Renderable& HeadlessBackend::getDefaultRenderable() { if (!resource) { - resource = std::make_unique<HeadlessRenderableResource>(static_cast<gl::Context&>(getContext()), size); + resource = std::make_unique<HeadlessRenderableResource>(*this, static_cast<gl::Context&>(getContext()), size); } return *this; } +void HeadlessBackend::swap() { + if (swapBehaviour == SwapBehaviour::Flush) static_cast<gl::Context&>(getContext()).finish(); +} + void HeadlessBackend::updateAssumedState() { // no-op } @@ -89,9 +97,9 @@ RendererBackend* HeadlessBackend::getRendererBackend() { namespace gfx { template <> -std::unique_ptr<gfx::HeadlessBackend> -Backend::Create<gfx::Backend::Type::OpenGL>(const Size size, const gfx::ContextMode contextMode) { - return std::make_unique<gl::HeadlessBackend>(size, contextMode); +std::unique_ptr<gfx::HeadlessBackend> Backend::Create<gfx::Backend::Type::OpenGL>( + const Size size, gfx::HeadlessBackend::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode) { + return std::make_unique<gl::HeadlessBackend>(size, swapBehavior, contextMode); } } // namespace gfx diff --git a/platform/default/src/mbgl/text/collator.cpp b/platform/default/src/mbgl/i18n/collator.cpp index 400fa4d94d..f46accff8a 100644 --- a/platform/default/src/mbgl/text/collator.cpp +++ b/platform/default/src/mbgl/i18n/collator.cpp @@ -1,7 +1,9 @@ -#include <mbgl/style/expression/collator.hpp> -#include <mbgl/util/platform.hpp> #include <libnu/strcoll.h> -#include <mbgl/text/unaccent.hpp> +#include <libnu/unaccent.h> +#include <mbgl/i18n/collator.hpp> + +#include <cstring> +#include <sstream> /* The default implementation of Collator ignores locale. @@ -16,9 +18,35 @@ but would require bundling locale data. */ +namespace { +std::string unaccent(const std::string& str) { + std::stringstream output; + char const *itr = str.c_str(), *nitr; + char const* end = itr + str.length(); + char lo[5] = {0}; + + for (; itr < end; itr = nitr) { + uint32_t code_point = 0; + char const* buf = nullptr; + + nitr = _nu_tounaccent(itr, end, nu_utf8_read, &code_point, &buf, nullptr); + if (buf != nullptr) { + do { + buf = NU_CASEMAP_DECODING_FUNCTION(buf, &code_point); + if (code_point == 0) break; + output.write(lo, nu_utf8_write(code_point, lo) - lo); + } while (code_point != 0); + } else { + output.write(itr, nitr - itr); + } + } + + return output.str(); +} +} // namespace + namespace mbgl { -namespace style { -namespace expression { +namespace platform { class Collator::Impl { public: @@ -28,8 +56,7 @@ public: {} bool operator==(const Impl& other) const { - return caseSensitive == other.caseSensitive && - diacriticSensitive == other.diacriticSensitive; + return caseSensitive == other.caseSensitive && diacriticSensitive == other.diacriticSensitive; } int compare(const std::string& lhs, const std::string& rhs) const { @@ -40,40 +67,35 @@ public: return nu_strcasecoll(lhs.c_str(), rhs.c_str(), nu_utf8_read, nu_utf8_read); } else if (caseSensitive && !diacriticSensitive) { - return nu_strcoll(platform::unaccent(lhs).c_str(), platform::unaccent(rhs).c_str(), - nu_utf8_read, nu_utf8_read); + return nu_strcoll(unaccent(lhs).c_str(), unaccent(rhs).c_str(), nu_utf8_read, nu_utf8_read); } else { - return nu_strcasecoll(platform::unaccent(lhs).c_str(), platform::unaccent(rhs).c_str(), - nu_utf8_read, nu_utf8_read); + return nu_strcasecoll(unaccent(lhs).c_str(), unaccent(rhs).c_str(), nu_utf8_read, nu_utf8_read); } } std::string resolvedLocale() const { return ""; } + private: bool caseSensitive; bool diacriticSensitive; }; - -Collator::Collator(bool caseSensitive, bool diacriticSensitive, optional<std::string> locale_) - : impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, std::move(locale_))) -{} +int Collator::compare(const std::string& lhs, const std::string& rhs) const { + return impl->compare(lhs, rhs); +} bool Collator::operator==(const Collator& other) const { return *impl == *(other.impl); } -int Collator::compare(const std::string& lhs, const std::string& rhs) const { - return impl->compare(lhs, rhs); -} - std::string Collator::resolvedLocale() const { return impl->resolvedLocale(); } +Collator::Collator(bool caseSensitive, bool diacriticSensitive, optional<std::string> locale) + : impl(std::make_shared<Impl>(caseSensitive, diacriticSensitive, std::move(locale))) {} -} // namespace expression -} // namespace style +} // namespace platform } // namespace mbgl diff --git a/platform/default/src/mbgl/util/format_number.cpp b/platform/default/src/mbgl/i18n/format_number.cpp index d1b51e11a1..7b6f24221d 100644 --- a/platform/default/src/mbgl/util/format_number.cpp +++ b/platform/default/src/mbgl/i18n/format_number.cpp @@ -1,4 +1,4 @@ -#include <mbgl/util/platform.hpp> +#include <mbgl/i18n/number_format.hpp> #include <unicode/numberformatter.h> diff --git a/platform/default/src/mbgl/i18n/number_format.cpp b/platform/default/src/mbgl/i18n/number_format.cpp new file mode 100644 index 0000000000..7f2bc5a5ef --- /dev/null +++ b/platform/default/src/mbgl/i18n/number_format.cpp @@ -0,0 +1,41 @@ +#include <mbgl/i18n/number_format.hpp> + +#include <unicode/numberformatter.h> + +namespace mbgl { +namespace platform { + +std::string formatNumber(double number, + const std::string& localeId, + const std::string& currency, + uint8_t minFractionDigits, + uint8_t maxFractionDigits) { + UErrorCode status = U_ZERO_ERROR; + icu::UnicodeString ustr; + std::string formatted; + + icu::Locale locale = icu::Locale(localeId.c_str()); + // Print the value as currency + if (!currency.empty()) { + icu::UnicodeString ucurrency = icu::UnicodeString::fromUTF8(currency); + ustr = icu::number::NumberFormatter::with() + .unit(icu::CurrencyUnit(ucurrency.getBuffer(), status)) + .locale(locale) + .formatDouble(number, status) + .toString(); + } else { + ustr = icu::number::NumberFormatter::with() +#if U_ICU_VERSION_MAJOR_NUM >= 62 + .precision(icu::number::Precision::minMaxFraction(minFractionDigits, maxFractionDigits)) +#else + .rounding(icu::number::Rounder::minMaxFraction(minFractionDigits, maxFractionDigits)) +#endif + .locale(locale) + .formatDouble(number, status) + .toString(); + } + return ustr.toUTF8String(formatted); +} + +} // namespace platform +} // namespace mbgl diff --git a/platform/default/src/mbgl/map/map_snapshotter.cpp b/platform/default/src/mbgl/map/map_snapshotter.cpp index 5f4060e3f0..705a791af9 100644 --- a/platform/default/src/mbgl/map/map_snapshotter.cpp +++ b/platform/default/src/mbgl/map/map_snapshotter.cpp @@ -51,8 +51,8 @@ MapSnapshotter::Impl::Impl(const std::pair<bool, std::string> style, const optional<LatLngBounds> region, const optional<std::string> localFontFamily, const ResourceOptions& resourceOptions) - : frontend( - size, pixelRatio, gfx::ContextMode::Unique, localFontFamily), + : frontend( + size, pixelRatio, gfx::HeadlessBackend::SwapBehaviour::NoFlush, gfx::ContextMode::Unique, localFontFamily), map(frontend, MapObserver::nullObserver(), MapOptions().withMapMode(MapMode::Static).withSize(size).withPixelRatio(pixelRatio), diff --git a/platform/default/src/mbgl/render-test/main.cpp b/platform/default/src/mbgl/render-test/main.cpp new file mode 100644 index 0000000000..9b22b20e00 --- /dev/null +++ b/platform/default/src/mbgl/render-test/main.cpp @@ -0,0 +1,5 @@ +#include <mbgl/render_test.hpp> + +int main(int argc, char *argv[]) { + return mbgl::runRenderTests(argc, argv); +} diff --git a/platform/default/src/mbgl/storage/offline_database.cpp b/platform/default/src/mbgl/storage/offline_database.cpp index 133e1f7992..5aa5738f41 100644 --- a/platform/default/src/mbgl/storage/offline_database.cpp +++ b/platform/default/src/mbgl/storage/offline_database.cpp @@ -140,11 +140,12 @@ void OfflineDatabase::removeExisting() { void OfflineDatabase::removeOldCacheTable() { assert(db); db->exec("DROP TABLE IF EXISTS http_cache"); - db->exec("VACUUM"); + vacuum(); } void OfflineDatabase::createSchema() { assert(db); + vacuum(); db->exec("PRAGMA journal_mode = DELETE"); db->exec("PRAGMA synchronous = FULL"); mapbox::sqlite::Transaction transaction(*db); @@ -155,7 +156,7 @@ void OfflineDatabase::createSchema() { void OfflineDatabase::migrateToVersion3() { assert(db); - db->exec("VACUUM"); + vacuum(); db->exec("PRAGMA user_version = 3"); } @@ -181,6 +182,15 @@ void OfflineDatabase::migrateToVersion6() { transaction.commit(); } +void OfflineDatabase::vacuum() { + if (getPragma<int64_t>("PRAGMA auto_vacuum") != 2 /*INCREMENTAL*/) { + db->exec("PRAGMA auto_vacuum = INCREMENTAL"); + db->exec("VACUUM"); + } else { + db->exec("PRAGMA incremental_vacuum"); + } +} + mapbox::sqlite::Statement& OfflineDatabase::getStatement(const char* sql) { if (!db) { initialize(); @@ -683,7 +693,7 @@ std::exception_ptr OfflineDatabase::clearAmbientCache() try { resourceQuery.run(); - db->exec("VACUUM"); + vacuum(); return nullptr; } catch (const mapbox::sqlite::Exception& ex) { @@ -871,7 +881,7 @@ std::exception_ptr OfflineDatabase::deleteRegion(OfflineRegion&& region) try { evict(0); assert(db); - db->exec("VACUUM"); + vacuum(); // Ensure that the cached offlineTileCount value is recalculated. offlineMapboxTileCount = {}; @@ -1218,7 +1228,7 @@ std::exception_ptr OfflineDatabase::setMaximumAmbientCacheSize(uint64_t size) { if (databaseSize > maximumAmbientCacheSize) { evict(0); - db->exec("VACUUM"); + vacuum(); } return nullptr; diff --git a/platform/default/src/mbgl/text/unaccent.cpp b/platform/default/src/mbgl/text/unaccent.cpp deleted file mode 100644 index 37b9a0d9ca..0000000000 --- a/platform/default/src/mbgl/text/unaccent.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include <mbgl/util/platform.hpp> -#include <libnu/unaccent.h> -#include <mbgl/text/unaccent.hpp> - -#include <cstring> -#include <sstream> - -namespace mbgl { namespace platform { - -std::string unaccent(const std::string& str) -{ - std::stringstream output; - char const *itr = str.c_str(), *nitr; - char const *end = itr + str.length(); - char lo[5] = { 0 }; - - for (; itr < end; itr = nitr) - { - uint32_t code_point = 0; - char const* buf = nullptr; - - nitr = _nu_tounaccent(itr, end, nu_utf8_read, &code_point, &buf, nullptr); - if (buf != nullptr) - { - do - { - buf = NU_CASEMAP_DECODING_FUNCTION(buf, &code_point); - if (code_point == 0) break; - output.write(lo, nu_utf8_write(code_point, lo) - lo); - } - while (code_point != 0); - } - else - { - output.write(itr, nitr - itr); - } - } - - return output.str(); -} - -} // namespace platform -} // namespace mbgl diff --git a/platform/default/src/mbgl/util/monotonic_timer.cpp b/platform/default/src/mbgl/util/monotonic_timer.cpp new file mode 100644 index 0000000000..43c2ce6717 --- /dev/null +++ b/platform/default/src/mbgl/util/monotonic_timer.cpp @@ -0,0 +1,24 @@ +#include <assert.h> +#include <chrono> +#include <mbgl/util/monotonic_timer.hpp> + +namespace mbgl { +namespace util { + +// Prefer high resolution timer if it is monotonic +template <typename T, std::enable_if_t<std::chrono::high_resolution_clock::is_steady, T>* = nullptr> +static T sample() { + return std::chrono::duration_cast<T>(std::chrono::high_resolution_clock::now().time_since_epoch()); +} + +template <typename T, std::enable_if_t<!std::chrono::high_resolution_clock::is_steady, T>* = nullptr> +static T sample() { + return std::chrono::duration_cast<T>(std::chrono::steady_clock::now().time_since_epoch()); +} + +std::chrono::duration<double> MonotonicTimer::now() { + return sample<std::chrono::duration<double>>(); +} + +} // namespace util +} // namespace mbgl
\ No newline at end of file |