diff options
-rw-r--r-- | bin/style.js | 2 | ||||
-rw-r--r-- | config/constants.cpp | 2 | ||||
-rw-r--r-- | include/llmr/map/source.hpp | 3 | ||||
-rw-r--r-- | include/llmr/style/style.hpp | 1 | ||||
-rw-r--r-- | include/llmr/style/style_parser.hpp | 8 | ||||
-rw-r--r-- | include/llmr/text/glyph_store.hpp | 7 | ||||
-rw-r--r-- | include/llmr/util/constants.hpp | 2 | ||||
-rw-r--r-- | src/map/map.cpp | 11 | ||||
-rw-r--r-- | src/map/source.cpp | 3 | ||||
-rw-r--r-- | src/map/tile_parser.cpp | 6 | ||||
-rw-r--r-- | src/style/style.cpp | 1 | ||||
-rw-r--r-- | src/style/style_parser.cpp | 14 | ||||
-rw-r--r-- | src/text/glyph_store.cpp | 16 |
13 files changed, 58 insertions, 18 deletions
diff --git a/bin/style.js b/bin/style.js index c5d98180f7..b3e692904b 100644 --- a/bin/style.js +++ b/bin/style.js @@ -3,6 +3,7 @@ module.exports = { "version": 3, "sprite": "http://mapbox-kkaefer.s3.amazonaws.com/static/outdoors-gl/sprite", + "glyphs": "http://mapbox.s3.amazonaws.com/gl-glyphs-256/{{fontstack}}/{{range}}.pbf", "constants": { "@land": "#eee", "@water": "#999", @@ -19,7 +20,6 @@ module.exports = { "mapbox.mapbox-streets-v5": { "type": "vector", "url": "mapbox://mapbox.mapbox-streets-v5", - "glyphs": "http://mapbox.s3.amazonaws.com/gl-glyphs-256/{fontstack}/{range}.pbf", "maxZoom": 14 } }, diff --git a/config/constants.cpp b/config/constants.cpp index 5be91a9fae..36f51559e2 100644 --- a/config/constants.cpp +++ b/config/constants.cpp @@ -1,7 +1,5 @@ #include <llmr/util/constants.hpp> -const char *llmr::kGlyphURL = "http://mapbox.s3.amazonaws.com/gl-glyphs-256/%s/%d-%d.pbf"; - const float llmr::util::tileSize = 512.0f; #if defined(DEBUG) diff --git a/include/llmr/map/source.hpp b/include/llmr/map/source.hpp index 0d6ef864f9..2937a8f690 100644 --- a/include/llmr/map/source.hpp +++ b/include/llmr/map/source.hpp @@ -22,7 +22,7 @@ class Texturepool; class Source : public std::enable_shared_from_this<Source>, private util::noncopyable { public: - Source(SourceType type = SourceType::Vector, const std::string &url = "", const std::string &glyphs = "", + Source(SourceType type = SourceType::Vector, const std::string &url = "", uint32_t tile_size = 512, uint32_t min_zoom = 0, uint32_t max_zoom = 22); bool update(Map &map); @@ -40,7 +40,6 @@ public: public: const SourceType type; const std::string url; - const std::string glyphs; const uint32_t tile_size; const int32_t min_zoom; const int32_t max_zoom; diff --git a/include/llmr/style/style.hpp b/include/llmr/style/style.hpp index fca18a7c9f..47539fb0b0 100644 --- a/include/llmr/style/style.hpp +++ b/include/llmr/style/style.hpp @@ -51,6 +51,7 @@ public: std::shared_ptr<StyleLayer> background; std::vector<std::string> appliedClasses; std::string sprite_url; + std::string glyph_url; private: void updateSources(); diff --git a/include/llmr/style/style_parser.hpp b/include/llmr/style/style_parser.hpp index c0570eae7e..777a8934da 100644 --- a/include/llmr/style/style_parser.hpp +++ b/include/llmr/style/style_parser.hpp @@ -34,6 +34,10 @@ public: return sprite; } + std::string getGlyphURL() const { + return glyph_url; + } + private: void parseConstants(JSVal value); JSVal replaceConstant(JSVal value); @@ -51,6 +55,7 @@ private: void parseBucket(JSVal value, std::shared_ptr<StyleLayer> &layer); void parseRender(JSVal value, std::shared_ptr<StyleLayer> &layer); void parseSprite(JSVal value); + void parseGlyphURL(JSVal value); // Parses optional properties into a render bucket. template<typename T> @@ -94,6 +99,9 @@ private: // Base URL of the sprite image. std::string sprite; + + // URL template for glyph PBFs. + std::string glyph_url; }; } diff --git a/include/llmr/text/glyph_store.hpp b/include/llmr/text/glyph_store.hpp index e44b94fe08..a1d1046b7f 100644 --- a/include/llmr/text/glyph_store.hpp +++ b/include/llmr/text/glyph_store.hpp @@ -51,7 +51,7 @@ private: class GlyphPBF { public: - GlyphPBF(const std::string &fontStack, GlyphRange glyphRange); + GlyphPBF(const std::string &glyphURL, const std::string &fontStack, GlyphRange glyphRange); void parse(FontStack &stack); @@ -67,6 +67,8 @@ private: // Manages Glyphrange PBF loading. class GlyphStore { public: + GlyphStore(const std::string &glyphURL); + // Block until all specified GlyphRanges of the specified font stack are loaded. void waitForGlyphRanges(const std::string &fontStack, const std::set<GlyphRange> &glyphRanges); @@ -78,6 +80,9 @@ private: FontStack &createFontStack(const std::string &fontStack); +public: + const std::string glyphURL; + private: std::unordered_map<std::string, std::map<GlyphRange, std::unique_ptr<GlyphPBF>>> ranges; std::unordered_map<std::string, std::unique_ptr<FontStack>> stacks; diff --git a/include/llmr/util/constants.hpp b/include/llmr/util/constants.hpp index 49f7a5f4b9..999ef05fcc 100644 --- a/include/llmr/util/constants.hpp +++ b/include/llmr/util/constants.hpp @@ -7,8 +7,6 @@ namespace llmr { -extern const char *kGlyphURL; - namespace util { extern const float tileSize; diff --git a/src/map/map.cpp b/src/map/map.cpp index 703cdf1400..50c172caaa 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -24,7 +24,6 @@ Map::Map(View& view) transform(), style(std::make_shared<Style>()), glyphAtlas(std::make_shared<GlyphAtlas>(1024, 1024)), - glyphStore(std::make_shared<GlyphStore>()), spriteAtlas(std::make_shared<SpriteAtlas>(512, 512)), texturepool(std::make_shared<Texturepool>()), painter(*this), @@ -439,6 +438,16 @@ void Map::prepare() { spriteAtlas->resize(state.getPixelRatio()); } + // Create a new glyph store object in case the glyph URL changed. + // TODO: Move this to a less frequently called place; we only need to do this when the + // stylesheet changes. + if (glyphStore && glyphStore->glyphURL != style->glyph_url) { + glyphStore.reset(); + } + if (!glyphStore && style->glyph_url.size()) { + glyphStore = std::make_shared<GlyphStore>(style->glyph_url); + } + if (pixelRatioChanged || dimensionsChanged) { painter.clearFramebuffers(); } diff --git a/src/map/source.cpp b/src/map/source.cpp index 6f7bb811fd..c3c5e89fd4 100644 --- a/src/map/source.cpp +++ b/src/map/source.cpp @@ -17,11 +17,10 @@ namespace llmr { -Source::Source(SourceType type, const std::string &url, const std::string &glyphs, +Source::Source(SourceType type, const std::string &url, uint32_t tile_size, uint32_t min_zoom, uint32_t max_zoom) : type(type), url(normalizeSourceURL(url)), - glyphs(glyphs), tile_size(tile_size), min_zoom(min_zoom), max_zoom(max_zoom) {} diff --git a/src/map/tile_parser.cpp b/src/map/tile_parser.cpp index b3a018f427..4cf7fb22fa 100644 --- a/src/map/tile_parser.cpp +++ b/src/map/tile_parser.cpp @@ -183,6 +183,12 @@ std::unique_ptr<Bucket> TileParser::createIconBucket(const VectorTileLayer& laye std::unique_ptr<Bucket> TileParser::createTextBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketText &text) { + // Make sure that we always have a valid glyph store. If this is not set, the stylesheet + // doesn't specify a glyph URL. + if (!glyphStore) { + return nullptr; + } + const StyleBucketText &properties = text; std::unique_ptr<TextBucket> bucket = std::make_unique<TextBucket>( diff --git a/src/style/style.cpp b/src/style/style.cpp index 8a23273f06..d6894f6e1c 100644 --- a/src/style/style.cpp +++ b/src/style/style.cpp @@ -103,6 +103,7 @@ void Style::loadJSON(const uint8_t *const data) { layers = parser.getLayers(); sprite_url = parser.getSprite(); + glyph_url = parser.getGlyphURL(); updateClasses(); } diff --git a/src/style/style_parser.cpp b/src/style/style_parser.cpp index a9d5c96985..069de2dbc5 100644 --- a/src/style/style_parser.cpp +++ b/src/style/style_parser.cpp @@ -25,6 +25,10 @@ void StyleParser::parse(JSVal document) { if (document.HasMember("sprite")) { parseSprite(document["sprite"]); } + + if (document.HasMember("glyphs")) { + parseGlyphURL(document["glyphs"]); + } } void StyleParser::parseConstants(JSVal value) { @@ -155,19 +159,17 @@ void StyleParser::parseSources(JSVal value) { std::string name { itr->name.GetString(), itr->name.GetStringLength() }; SourceType type = SourceType::Vector; std::string url; - std::string glyphs; uint16_t tile_size = 512; int32_t min_zoom = 0; int32_t max_zoom = 22; parseRenderProperty(itr->value, type, "type", parseSourceType); parseRenderProperty(itr->value, url, "url"); - parseRenderProperty(itr->value, glyphs, "glyphs"); parseRenderProperty(itr->value, tile_size, "tileSize"); parseRenderProperty(itr->value, min_zoom, "minZoom"); parseRenderProperty(itr->value, max_zoom, "maxZoom"); - sources.emplace(std::move(name), std::make_shared<Source>(type, url, glyphs, tile_size, min_zoom, max_zoom)); + sources.emplace(std::move(name), std::make_shared<Source>(type, url, tile_size, min_zoom, max_zoom)); } } else { throw Style::exception("sources must be an object"); @@ -921,5 +923,11 @@ void StyleParser::parseSprite(JSVal value) { } } +void StyleParser::parseGlyphURL(JSVal value) { + if (value.IsString()) { + glyph_url = { value.GetString(), value.GetStringLength() }; + } +} + } diff --git a/src/text/glyph_store.cpp b/src/text/glyph_store.cpp index 9d88a692b5..b79010670d 100644 --- a/src/text/glyph_store.cpp +++ b/src/text/glyph_store.cpp @@ -5,6 +5,7 @@ #include <llmr/util/utf.hpp> #include <llmr/util/pbf.hpp> #include <llmr/util/constants.hpp> +#include <llmr/util/token.hpp> #include <llmr/platform/platform.hpp> #include <uv.h> #include <algorithm> @@ -115,11 +116,16 @@ void FontStack::lineWrap(Shaping &shaping, const float &lineHeight, const float alignVertically(shaping, line + 1, lineHeight, verticalAlignment); } -GlyphPBF::GlyphPBF(const std::string &fontStack, GlyphRange glyphRange) +GlyphPBF::GlyphPBF(const std::string &glyphURL, const std::string &fontStack, GlyphRange glyphRange) : future(promise.get_future().share()) { // Load the glyph set URL - std::string url = util::sprintf<255>(kGlyphURL, fontStack.c_str(), glyphRange.first, glyphRange.second); + + const std::map<std::string, std::string> tokens {{ + { "fontstack", fontStack }, + { "range", std::to_string(glyphRange.first) + "-" + std::to_string(glyphRange.second) } + }}; + std::string url = util::replaceTokens(glyphURL, tokens); // TODO: Find more reliable URL normalization function std::replace(url.begin(), url.end(), ' ', '+'); @@ -202,6 +208,8 @@ void GlyphPBF::parse(FontStack &stack) { data.clear(); } +GlyphStore::GlyphStore(const std::string &glyphURL) + : glyphURL(glyphURL) {} void GlyphStore::waitForGlyphRanges(const std::string &fontStack, const std::set<GlyphRange> &glyphRanges) { // We are implementing a blocking wait with futures: Every GlyphSet has a future that we are @@ -232,11 +240,11 @@ void GlyphStore::waitForGlyphRanges(const std::string &fontStack, const std::set } } -std::shared_future<GlyphPBF &> GlyphStore::loadGlyphRange(const std::string &name, std::map<GlyphRange, std::unique_ptr<GlyphPBF>> &rangeSets, const GlyphRange range) { +std::shared_future<GlyphPBF &> GlyphStore::loadGlyphRange(const std::string &fontStack, std::map<GlyphRange, std::unique_ptr<GlyphPBF>> &rangeSets, const GlyphRange range) { auto range_it = rangeSets.find(range); if (range_it == rangeSets.end()) { // We don't have this glyph set yet for this font stack. - range_it = rangeSets.emplace(range, std::make_unique<GlyphPBF>(name, range)).first; + range_it = rangeSets.emplace(range, std::make_unique<GlyphPBF>(glyphURL, fontStack, range)).first; } return range_it->second->getFuture(); |