From ee9b172152c7e462f2c204ea7b85c3cc4bd04582 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 19 May 2015 00:38:10 +0300 Subject: Notify failures when loading glyphs --- include/mbgl/util/exception.hpp | 5 ++++ src/mbgl/map/resource_loader.cpp | 4 +++ src/mbgl/map/resource_loader.hpp | 1 + src/mbgl/text/glyph_store.cpp | 55 ++++++++++++++++++++++++++++------------ src/mbgl/text/glyph_store.hpp | 10 +++++++- 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/include/mbgl/util/exception.hpp b/include/mbgl/util/exception.hpp index 7ef8ea9762..da61aa482a 100644 --- a/include/mbgl/util/exception.hpp +++ b/include/mbgl/util/exception.hpp @@ -11,6 +11,11 @@ struct Exception : std::runtime_error { inline Exception(const std::string &msg) : std::runtime_error(msg) {} }; +struct GlyphRangeLoadingException : Exception { + inline GlyphRangeLoadingException(const char *msg) : Exception(msg) {} + inline GlyphRangeLoadingException(const std::string &msg) : Exception(msg) {} +}; + struct MisuseException : Exception { inline MisuseException(const char *msg) : Exception(msg) {} inline MisuseException(const std::string &msg) : Exception(msg) {} diff --git a/src/mbgl/map/resource_loader.cpp b/src/mbgl/map/resource_loader.cpp index ddef11293a..5aa714595d 100644 --- a/src/mbgl/map/resource_loader.cpp +++ b/src/mbgl/map/resource_loader.cpp @@ -104,6 +104,10 @@ void ResourceLoader::onGlyphRangeLoaded() { emitTileDataChanged(); } +void ResourceLoader::onGlyphRangeLoadingFailed(std::exception_ptr error) { + emitResourceLoadingFailed(error); +} + void ResourceLoader::onSourceLoaded() { emitTileDataChanged(); } diff --git a/src/mbgl/map/resource_loader.hpp b/src/mbgl/map/resource_loader.hpp index 9d94cb6495..33949aa487 100644 --- a/src/mbgl/map/resource_loader.hpp +++ b/src/mbgl/map/resource_loader.hpp @@ -63,6 +63,7 @@ public: // GlyphStore::Observer implementation. void onGlyphRangeLoaded() override; + void onGlyphRangeLoadingFailed(std::exception_ptr error) override; // Source::Observer implementation. void onSourceLoaded() override; diff --git a/src/mbgl/text/glyph_store.cpp b/src/mbgl/text/glyph_store.cpp index 4ee853b1ef..72c7b16a84 100644 --- a/src/mbgl/text/glyph_store.cpp +++ b/src/mbgl/text/glyph_store.cpp @@ -1,20 +1,23 @@ #include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include #include -#include +#include +#include #include -#include -#include -#include #include + #include +#include namespace mbgl { @@ -139,7 +142,8 @@ GlyphPBF::GlyphPBF(const std::string& glyphURL, const std::string& fontStack, GlyphRange glyphRange, Environment& env_, - const GlyphLoadedCallback& callback) + const GlyphLoadedCallback& successCallback, + const GlyphLoadingFailedCallback& failureCallback) : parsed(false), env(env_) { // Load the glyph set URL std::string url = util::replaceTokens(glyphURL, [&](const std::string &name) -> std::string { @@ -149,20 +153,20 @@ GlyphPBF::GlyphPBF(const std::string& glyphURL, }); // The prepare call jumps back to the main thread. - req = env.request({ Resource::Kind::Glyphs, url }, [&, url, callback](const Response &res) { + req = env.request({ Resource::Kind::Glyphs, url }, [&, url, successCallback, failureCallback](const Response &res) { req = nullptr; if (res.status != Response::Successful) { - // Something went wrong with loading the glyph pbf. - const std::string msg = std::string { "[ERROR] failed to load glyphs: " } + url + " message: " + res.message; - Log::Error(Event::HttpRequest, msg); + std::stringstream message; + message << "Failed to load [" << url << "]: " << res.message; + failureCallback(message.str()); } else { // Transfer the data to the GlyphSet and signal its availability. // Once it is available, the caller will need to call parse() to actually // parse the data we received. We are not doing this here since this callback is being // called from another (unknown) thread. data = res.data; - callback(this); + successCallback(this); } }); } @@ -234,8 +238,10 @@ bool GlyphPBF::isParsed() const { GlyphStore::GlyphStore(uv_loop_t* loop, Environment& env_) : env(env_), asyncEmitGlyphRangeLoaded(util::make_unique(loop, [this] { emitGlyphRangeLoaded(); })), + asyncEmitGlyphRangeLoadedingFailed(util::make_unique(loop, [this] { emitGlyphRangeLoadingFailed(); })), observer(nullptr) { asyncEmitGlyphRangeLoaded->unref(); + asyncEmitGlyphRangeLoadedingFailed->unref(); } GlyphStore::~GlyphStore() { @@ -254,19 +260,26 @@ bool GlyphStore::requestGlyphRangesIfNeeded(const std::string& fontStackName, return requestIsNeeded; } - auto callback = [this, fontStackName](GlyphPBF* glyph) { + auto successCallback = [this, fontStackName](GlyphPBF* glyph) { auto fontStack = createFontStack(fontStackName); glyph->parse(**fontStack); asyncEmitGlyphRangeLoaded->send(); }; + auto failureCallback = [this](const std::string& message) { + std::lock_guard lock(errorMessageMutex); + errorMessage = message; + asyncEmitGlyphRangeLoadedingFailed->send(); + }; + std::lock_guard lock(rangesMutex); auto& rangeSets = ranges[fontStackName]; for (const auto& range : glyphRanges) { const auto& rangeSets_it = rangeSets.find(range); if (rangeSets_it == rangeSets.end()) { - auto glyph = util::make_unique(glyphURL, fontStackName, range, env, callback); + auto glyph = util::make_unique(glyphURL, fontStackName, range, env, + successCallback, failureCallback); rangeSets.emplace(range, std::move(glyph)); requestIsNeeded = true; continue; @@ -312,4 +325,14 @@ void GlyphStore::emitGlyphRangeLoaded() { } } +void GlyphStore::emitGlyphRangeLoadingFailed() { + if (!observer) { + return; + } + + std::lock_guard lock(errorMessageMutex); + auto error = std::make_exception_ptr(util::GlyphRangeLoadingException(errorMessage)); + observer->onGlyphRangeLoadingFailed(error); +} + } diff --git a/src/mbgl/text/glyph_store.hpp b/src/mbgl/text/glyph_store.hpp index e13ed1f1d7..77452a3057 100644 --- a/src/mbgl/text/glyph_store.hpp +++ b/src/mbgl/text/glyph_store.hpp @@ -59,12 +59,14 @@ private: class GlyphPBF { public: using GlyphLoadedCallback = std::function; + using GlyphLoadingFailedCallback = std::function; GlyphPBF(const std::string &glyphURL, const std::string &fontStack, GlyphRange glyphRange, Environment &env, - const GlyphLoadedCallback& callback); + const GlyphLoadedCallback& successCallback, + const GlyphLoadingFailedCallback& failureCallback); ~GlyphPBF(); void parse(FontStack &stack); @@ -91,6 +93,7 @@ public: virtual ~Observer() = default; virtual void onGlyphRangeLoaded() = 0; + virtual void onGlyphRangeLoadingFailed(std::exception_ptr error) = 0; }; GlyphStore(uv_loop_t* loop, Environment &); @@ -110,6 +113,7 @@ public: private: void emitGlyphRangeLoaded(); + void emitGlyphRangeLoadingFailed(); util::exclusive createFontStack(const std::string &fontStack); @@ -122,7 +126,11 @@ private: std::unordered_map> stacks; std::mutex stacksMutex; + std::string errorMessage; + std::mutex errorMessageMutex; + std::unique_ptr asyncEmitGlyphRangeLoaded; + std::unique_ptr asyncEmitGlyphRangeLoadedingFailed; Observer* observer; }; -- cgit v1.2.1