load glyphset url from stylesheet
This commit is contained in:
@@ -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
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
namespace llmr {
|
||||
|
||||
extern const char *kGlyphURL;
|
||||
|
||||
namespace util {
|
||||
|
||||
extern const float tileSize;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -103,6 +103,7 @@ void Style::loadJSON(const uint8_t *const data) {
|
||||
|
||||
layers = parser.getLayers();
|
||||
sprite_url = parser.getSprite();
|
||||
glyph_url = parser.getGlyphURL();
|
||||
|
||||
updateClasses();
|
||||
}
|
||||
|
||||
@@ -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() };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user