diff --git a/.gitignore b/.gitignore index 5295ff95f..c2ddb1a0c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ /ios/build /config.gypi /config.mk +/config/constants_local.cpp /build /bin/node_modules /include/llmr/shader/shaders.hpp diff --git a/bin/style.js b/bin/style.js index 4157e1e8f..ca42214ba 100644 --- a/bin/style.js +++ b/bin/style.js @@ -917,7 +917,7 @@ module.exports = { "poi": { "source": "outdoors", "layer": "poi_label", - "icon": "maki", + "icon": "{{maki}}", "field": "scalerank", "value": [1, 2], "size": 12, @@ -926,7 +926,7 @@ module.exports = { "poi_3": { "source": "outdoors", "layer": "poi_label", - "icon": "maki", + "icon": "{{maki}}", "field": "scalerank", "value": 3, "size": 12, @@ -935,7 +935,7 @@ module.exports = { "poi_4_4": { "source": "outdoors", "layer": "poi_label", - "icon": "maki", + "icon": "{{maki}}", "filter": [ "and", { "field": "scalerank", "value": 4 }, @@ -947,7 +947,7 @@ module.exports = { "poi_4_16": { "source": "outdoors", "layer": "poi_label", - "icon": "maki", + "icon": "{{maki}}", "filter": [ "and", { "field": "scalerank", "value": 4 }, @@ -960,7 +960,7 @@ module.exports = { "poi_4_all": { "source": "outdoors", "layer": "poi_label", - "icon": "maki", + "icon": "{{maki}}", "field": "scalerank", "value": 4, "size": 12, @@ -969,7 +969,7 @@ module.exports = { "poi_aerodrome": { "source": "outdoors", "layer": "poi_label", - "icon": "maki", + "icon": "{{maki}}", "field": "maki", "value": "airport", "size": 24, diff --git a/src/util/constants.cpp b/config/constants.cpp similarity index 76% rename from src/util/constants.cpp rename to config/constants.cpp index 46852e5e7..ab0c160a8 100644 --- a/src/util/constants.cpp +++ b/config/constants.cpp @@ -1,5 +1,9 @@ #include +const char *llmr::kSpriteURL = "http://mapbox-kkaefer.s3.amazonaws.com/static/outdoors-gl/sprite"; +const char *llmr::kVectorTileURL = "http://a.tiles.mapbox.com/v3/mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5/%d/%d/%d.vector.pbf"; +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) @@ -24,4 +28,4 @@ const bool llmr::debug::missingFontStackWarning = false; const bool llmr::debug::missingFontFaceWarning = false; const bool llmr::debug::glyphWarning = false; const bool llmr::debug::shapingWarning = false; -#endif \ No newline at end of file +#endif diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp index 31118a22f..220acd397 100644 --- a/include/llmr/platform/platform.hpp +++ b/include/llmr/platform/platform.hpp @@ -12,9 +12,6 @@ class loop; } namespace llmr { - -extern const char *kSpriteURL; - namespace platform { class Request; diff --git a/include/llmr/style/value.hpp b/include/llmr/style/value.hpp index c6d6f50b9..873438625 100644 --- a/include/llmr/style/value.hpp +++ b/include/llmr/style/value.hpp @@ -10,6 +10,12 @@ typedef util::variant Value; std::string toString(const Value &value); +inline std::string& operator+=(std::string& out, const Value& value) { + out += toString(value); + return out; +} + + Value parseValue(pbf data); namespace util { diff --git a/include/llmr/util/constants.hpp b/include/llmr/util/constants.hpp index f315e5171..e3a7b206e 100644 --- a/include/llmr/util/constants.hpp +++ b/include/llmr/util/constants.hpp @@ -6,6 +6,11 @@ #include "vec.hpp" namespace llmr { + +extern const char *kSpriteURL; +extern const char *kVectorTileURL; +extern const char *kGlyphURL; + namespace util { extern const float tileSize; diff --git a/include/llmr/util/token.hpp b/include/llmr/util/token.hpp new file mode 100644 index 000000000..db5b5fa0c --- /dev/null +++ b/include/llmr/util/token.hpp @@ -0,0 +1,49 @@ +#ifndef LLMR_UTIL_TOKEN +#define LLMR_UTIL_TOKEN + +#ifdef __linux__ +#include +namespace regex_impl = boost; +#else +#include +namespace regex_impl = std; +#endif + +namespace llmr { +namespace util { + +namespace detail { +const regex_impl::regex tokenRegex("\\{\\{(\\w+)\\}\\}"); +const regex_impl::sregex_token_iterator tokensEnd = regex_impl::sregex_token_iterator(); +} + +template +std::string replaceTokens(const std::string &source, const Tokens &tokens) { + std::string result; + result.reserve(source.size()); + + bool token = false; + for (auto token_it = regex_impl::sregex_token_iterator(source.begin(), source.end(), + detail::tokenRegex, {-1, 1}); + token_it != detail::tokensEnd; ++token_it, token = !token) { + if (!token_it->matched) { + continue; + } + + if (token) { + const auto it_prop = tokens.find(token_it->str()); + if (it_prop != tokens.end()) { + result += it_prop->second; + } + } else { + result += token_it->str(); + } + } + + return result; +} + +} // end namespace util +} // end namespace llmr + +#endif diff --git a/llmr.gyp b/llmr.gyp index d165a24d3..73aece077 100644 --- a/llmr.gyp +++ b/llmr.gyp @@ -65,6 +65,7 @@ ], 'sources': [ '(new Source(*this, painter, - "http://a.tiles.mapbox.com/v3/mapbox.mapbox-terrain-v1,mapbox.mapbox-streets-v5/%d/%d/%d.vector.pbf", + kVectorTileURL, Source::Type::vector, {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }}, 512, diff --git a/src/map/tile_parser.cpp b/src/map/tile_parser.cpp index 2af5278f5..21d2bf1bf 100644 --- a/src/map/tile_parser.cpp +++ b/src/map/tile_parser.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,11 @@ void TileParser::parseStyleLayers(const std::vector &layers) { return; } + if (layer_desc.bucket_name == "background") { + // background is a special, fake bucket + continue; + } + if (layer_desc.child_layer.size()) { // This is a layer group. // TODO: create framebuffer @@ -79,10 +85,7 @@ void TileParser::parseStyleLayers(const std::vector &layers) { auto bucket_it = tile.buckets.find(layer_desc.bucket_name); if (bucket_it == tile.buckets.end()) { auto bucket_it = style->buckets.find(layer_desc.bucket_name); - if (layer_desc.bucket_name == "background") { - // background is a special, fake bucket - continue; - } else if (bucket_it != style->buckets.end()) { + if (bucket_it != style->buckets.end()) { // Only create the new bucket if we have an actual specification // for it. std::unique_ptr bucket = createBucket(bucket_it->second); @@ -193,9 +196,6 @@ std::unique_ptr TileParser::createTextBucket(const VectorTileLayer &laye tile.textVertexBuffer, tile.triangleElementsBuffer, bucket_desc, placement); util::utf8_to_utf32 ucs4conv; - regex_impl::regex token_regex("\\{\\{(\\w+)\\}\\}"); - const auto tokens_end = regex_impl::sregex_token_iterator(); - std::vector> labels; @@ -209,34 +209,8 @@ std::unique_ptr TileParser::createTextBucket(const VectorTileLayer &laye return nullptr; VectorTileFeature feature{feature_pbf, layer}; - const std::string &field = bucket_desc.geometry.field; - std::string source_string; - source_string.reserve(field.size()); - - bool token = false; - for (auto token_it = regex_impl::sregex_token_iterator(field.begin(), field.end(), token_regex, {-1, 1}); token_it != tokens_end; ++token_it, token = !token) { - if (!token_it->matched) { - continue; - } - - if (token) { - auto it_prop = feature.properties.find(token_it->str()); - if (it_prop == feature.properties.end()) { - // feature does not have the correct property - if (debug::labelTextMissingWarning) { - fprintf(stderr, - "[WARNING] feature doesn't have property '%s' required for labelling\n", - token_it->str().c_str()); - } - continue; - } - source_string += toString(it_prop->second); - } else { - source_string += token_it->str(); - } - } - - const std::u32string string = ucs4conv.convert(source_string); + const std::u32string string = ucs4conv.convert( + util::replaceTokens(bucket_desc.geometry.field, feature.properties)); // Loop through all characters of this text and collect unique codepoints. for (uint32_t chr : string) { diff --git a/src/platform/platform.cpp b/src/platform/platform.cpp deleted file mode 100644 index 6aa5ef38f..000000000 --- a/src/platform/platform.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -const char *llmr::kSpriteURL = "http://mapbox-kkaefer.s3.amazonaws.com/static/outdoors-gl/sprite"; diff --git a/src/renderer/icon_bucket.cpp b/src/renderer/icon_bucket.cpp index 11999a608..fd43f6951 100644 --- a/src/renderer/icon_bucket.cpp +++ b/src/renderer/icon_bucket.cpp @@ -10,6 +10,7 @@ #include #include +#include #include @@ -28,16 +29,10 @@ void IconBucket::addFeature(const VectorTileFeature &feature, SpriteAtlas &sprit std::string field; if (geometry.field.size()) { - auto field_it = feature.properties.find(geometry.field); - if (field_it == feature.properties.end()) { - if (debug::tileParseWarnings) { - fprintf(stderr, "[WARNING] feature doesn't contain field '%s'\n", geometry.field.c_str()); - } - return; - } + field = util::replaceTokens(geometry.field, feature.properties); + } - field = toString(field_it->second); - } else { + if (!field.size()) { field = ""; } diff --git a/src/text/glyph_store.cpp b/src/text/glyph_store.cpp index 50084ba5f..9d88a692b 100644 --- a/src/text/glyph_store.cpp +++ b/src/text/glyph_store.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -118,7 +119,7 @@ GlyphPBF::GlyphPBF(const std::string &fontStack, GlyphRange glyphRange) : future(promise.get_future().share()) { // Load the glyph set URL - std::string url = util::sprintf<255>("http://mapbox.s3.amazonaws.com/gl-glyphs-256/%s/%d-%d.pbf", fontStack.c_str(), glyphRange.first, glyphRange.second); + std::string url = util::sprintf<255>(kGlyphURL, fontStack.c_str(), glyphRange.first, glyphRange.second); // TODO: Find more reliable URL normalization function std::replace(url.begin(), url.end(), ' ', '+');