From 3d9a2932584b1230c8be47e6935f794cede8fe85 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 22 Aug 2014 15:31:57 -0700 Subject: [PATCH] Support for Mapbox fontstack API --- include/mbgl/util/mapbox.hpp | 17 ++++++++++++++ include/mbgl/util/url.hpp | 14 ++++++++++++ src/map/map.cpp | 3 ++- src/map/source.cpp | 18 ++------------- src/text/glyph_store.cpp | 6 ++--- src/util/mapbox.cpp | 44 ++++++++++++++++++++++++++++++++++++ src/util/url.cpp | 29 ++++++++++++++++++++++++ styles/bright/style.json | 2 +- styles/outdoors/style.json | 2 +- 9 files changed, 112 insertions(+), 23 deletions(-) create mode 100644 include/mbgl/util/mapbox.hpp create mode 100644 include/mbgl/util/url.hpp create mode 100644 src/util/mapbox.cpp create mode 100644 src/util/url.cpp diff --git a/include/mbgl/util/mapbox.hpp b/include/mbgl/util/mapbox.hpp new file mode 100644 index 000000000..0fbb9a91e --- /dev/null +++ b/include/mbgl/util/mapbox.hpp @@ -0,0 +1,17 @@ +#ifndef MBGL_UTIL_MAPBOX +#define MBGL_UTIL_MAPBOX + +#include + +namespace mbgl { +namespace util { +namespace mapbox { + +std::string normalizeSourceURL(const std::string& url, const std::string& accessToken); +std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken); + +} +} +} + +#endif diff --git a/include/mbgl/util/url.hpp b/include/mbgl/util/url.hpp new file mode 100644 index 000000000..14d9dd316 --- /dev/null +++ b/include/mbgl/util/url.hpp @@ -0,0 +1,14 @@ +#ifndef MBGL_UTIL_URL +#define MBGL_UTIL_URL + +#include + +namespace mbgl { +namespace util { + +std::string percentEncode(const std::string&); + +} +} + +#endif diff --git a/src/map/map.cpp b/src/map/map.cpp index 4fa483898..55566cb20 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -211,7 +212,7 @@ void Map::setStyleJSON(std::string newStyleJSON, const std::string &base) { sprite.reset(); style->loadJSON((const uint8_t *)styleJSON.c_str()); fileSource->setBase(base); - glyphStore->setURL(style->glyph_url); + glyphStore->setURL(util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken())); update(); } diff --git a/src/map/source.cpp b/src/map/source.cpp index db83cccc1..b83384f25 100644 --- a/src/map/source.cpp +++ b/src/map/source.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -23,21 +24,6 @@ Source::Source(SourceInfo& info) { } -std::string normalizeURL(const std::string& url, const std::string& access_token) { - const std::string t = "mapbox://"; - - if (url.compare(0, t.length(), t) != 0) - return url; - - if (access_token.empty()) - throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources"); - - return std::string("https://api.tiles.mapbox.com/v4/") - + url.substr(t.length()) - + ".json?access_token=" - + access_token; -} - // Note: This is a separate function that must be called exactly once after creation // The reason this isn't part of the constructor is that calling shared_from_this() in // the constructor fails. @@ -47,7 +33,7 @@ void Source::load(Map& map) { return; } - std::string url = normalizeURL(info.url, map.getAccessToken()); + std::string url = util::mapbox::normalizeSourceURL(info.url, map.getAccessToken()); std::shared_ptr source = shared_from_this(); map.getFileSource()->load(ResourceType::JSON, url, [source, &map](platform::Response *res) { diff --git a/src/text/glyph_store.cpp b/src/text/glyph_store.cpp index 09f2fbc7b..65941e91f 100644 --- a/src/text/glyph_store.cpp +++ b/src/text/glyph_store.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -141,14 +142,11 @@ GlyphPBF::GlyphPBF(const std::string &glyphURL, const std::string &fontStack, Gl { // Load the glyph set URL std::string url = util::replaceTokens(glyphURL, [&](const std::string &name) -> std::string { - if (name == "fontstack") return fontStack; + if (name == "fontstack") return util::percentEncode(fontStack); if (name == "range") return std::to_string(glyphRange.first) + "-" + std::to_string(glyphRange.second); return ""; }); - // TODO: Find more reliable URL normalization function - std::replace(url.begin(), url.end(), ' ', '+'); - #if defined(DEBUG) fprintf(stderr, "%s\n", url.c_str()); #endif diff --git a/src/util/mapbox.cpp b/src/util/mapbox.cpp new file mode 100644 index 000000000..277b647f3 --- /dev/null +++ b/src/util/mapbox.cpp @@ -0,0 +1,44 @@ +#include + +#include + +namespace mbgl { +namespace util { +namespace mapbox { + +const std::string mapbox = "mapbox://"; + +std::string normalizeURL(const std::string& url, const std::string& accessToken) { + if (accessToken.empty()) + throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources"); + + return std::string("https://api.tiles.mapbox.com/v4/") + + url.substr(mapbox.length()) + + "?access_token=" + + accessToken; +} + +std::string normalizeSourceURL(const std::string& url, const std::string& accessToken) { + if (url.compare(0, mapbox.length(), mapbox) != 0) + return url; + + std::string result = normalizeURL(url + ".json", accessToken); + + // TileJSON requests need a secure flag appended to their URLs so + // that the server knows to send SSL-ified resource references. + if (url.compare(0, 5, "https") == 0) + result += "&secure"; + + return result; +} + +std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken) { + if (url.compare(0, mapbox.length(), mapbox) != 0) + return url; + + return normalizeURL(url, accessToken); +} + +} +} +} diff --git a/src/util/url.cpp b/src/util/url.cpp new file mode 100644 index 000000000..b1a721d86 --- /dev/null +++ b/src/util/url.cpp @@ -0,0 +1,29 @@ +#include + +#include +#include +#include +#include + +namespace mbgl { +namespace util { + +std::string percentEncode(const std::string& input) { + std::ostringstream encoded; + + encoded.fill('0'); + encoded << std::hex; + + for (auto c : input) { + if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { + encoded << c; + } else { + encoded << '%' << std::setw(2) << int(c); + } + } + + return encoded.str(); +} + +} +} diff --git a/styles/bright/style.json b/styles/bright/style.json index d132efe98..917244648 100644 --- a/styles/bright/style.json +++ b/styles/bright/style.json @@ -1,7 +1,7 @@ { "version": 4, "sprite": "img/sprite", - "glyphs": "https://mapbox.s3.amazonaws.com/gl-glyphs-256/{fontstack}/{range}.pbf", + "glyphs": "mapbox://fontstack/{fontstack}/{range}.pbf", "constants": { "@name": "{name_en}", "@sans": "Open Sans Regular, Arial Unicode MS Regular", diff --git a/styles/outdoors/style.json b/styles/outdoors/style.json index 9abf91786..a9085c17d 100644 --- a/styles/outdoors/style.json +++ b/styles/outdoors/style.json @@ -1,7 +1,7 @@ { "version": 4, "sprite": "https://www.mapbox.com/mapbox-gl-styles/sprites/outdoors", - "glyphs": "https://mapbox.s3.amazonaws.com/gl-glyphs-256/{fontstack}/{range}.pbf", + "glyphs": "mapbox://fontstack/{fontstack}/{range}.pbf", "constants": { "@land": "rgb(244,239,225)", "@water": "#cdd",