Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[core] Rationalize Resource initialization #3740

Merged
merged 3 commits into from
Jan 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions include/mbgl/storage/resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,42 @@ class Resource {
SpriteJSON
};

Resource(Kind kind_, const std::string& url_)
struct TileData {
std::string urlTemplate;
uint8_t pixelRatio;
int32_t x;
int32_t y;
int8_t z;
};

Resource(Kind kind_, const std::string& url_, optional<TileData> tileData_ = {})
: kind(kind_),
url(url_) {
url(url_),
tileData(tileData_) {
}

static Resource style(const std::string& url);
static Resource source(const std::string& url);
static Resource tile(const std::string& urlTemplate,
float pixelRatio,
int32_t x,
int32_t y,
int8_t z);
static Resource glyphs(const std::string& urlTemplate,
const std::string& fontStack,
const std::pair<uint16_t, uint16_t>& glyphRange);
static Resource spriteImage(const std::string& base, float pixelRatio);
static Resource spriteJSON(const std::string& base, float pixelRatio);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why static functions rather than constructors that discriminate on Kind?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way enforces the appropriate arguments for each kind, and is more succinct.

const Resource style = Resource::style(url);

vs

const Resource style(Resource::Kind::Style, url);
const Resource tile(Resource::Kind::Tile, url); // wrong arguments

Better would be to make Resource a variant type, but that's a more invasive change than I want to make right now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Also allows us to write const auto style = Resource::style(url);


const Kind kind;
const std::string url;

optional<SystemTimePoint> priorModified;
optional<SystemTimePoint> priorExpires;
optional<std::string> priorEtag;
// Includes auxiliary data if this is a tile request.
optional<TileData> tileData;

optional<SystemTimePoint> priorModified = {};
optional<SystemTimePoint> priorExpires = {};
optional<std::string> priorEtag = {};
};

} // namespace mbgl
Expand Down
2 changes: 1 addition & 1 deletion src/mbgl/map/map_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void MapContext::setStyleURL(const std::string& url) {
}

FileSource* fs = util::ThreadContext::getFileSource();
styleRequest = fs->request({ Resource::Kind::Style, styleURL }, [this, base](Response res) {
styleRequest = fs->request(Resource::style(styleURL), [this, base](Response res) {
if (res.error) {
if (res.error->reason == Response::Error::Reason::NotFound &&
util::mapbox::isMapboxURL(styleURL)) {
Expand Down
21 changes: 10 additions & 11 deletions src/mbgl/map/raster_tile_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,18 @@
using namespace mbgl;

RasterTileData::RasterTileData(const TileID& id_,
float pixelRatio,
const std::string& urlTemplate,
TexturePool &texturePool_,
Worker& worker_)
Worker& worker_,
const std::function<void(std::exception_ptr)>& callback)
: TileData(id_),
texturePool(texturePool_),
worker(worker_) {
}

RasterTileData::~RasterTileData() {
cancel();
}

void RasterTileData::request(const std::string& url,
const RasterTileData::Callback& callback) {
state = State::loading;

FileSource* fs = util::ThreadContext::getFileSource();
req = fs->request({ Resource::Kind::Tile, url }, [url, callback, this](Response res) {
const Resource resource = Resource::tile(urlTemplate, pixelRatio, id.x, id.y, id.sourceZ);
req = util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) {
if (res.error) {
std::exception_ptr error;
if (res.error->reason == Response::Error::Reason::NotFound) {
Expand Down Expand Up @@ -76,6 +71,10 @@ void RasterTileData::request(const std::string& url,
});
}

RasterTileData::~RasterTileData() {
cancel();
}

Bucket* RasterTileData::getBucket(StyleLayer const&) {
return bucket.get();
}
Expand Down
15 changes: 6 additions & 9 deletions src/mbgl/map/raster_tile_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,22 @@ class WorkRequest;

class RasterTileData : public TileData {
public:
RasterTileData(const TileID&, TexturePool&, Worker&);
RasterTileData(const TileID&,
float pixelRatio,
const std::string& urlTemplate,
TexturePool&,
Worker&,
const std::function<void(std::exception_ptr)>& callback);
~RasterTileData();

using Callback = std::function<void(std::exception_ptr)>;

void request(const std::string& url,
const Callback& callback);

void cancel() override;

Bucket* getBucket(StyleLayer const &layer_desc) override;

private:
TexturePool& texturePool;
Worker& worker;
std::unique_ptr<FileRequest> req;

std::unique_ptr<Bucket> bucket;

std::unique_ptr<WorkRequest> workRequest;
};

Expand Down
13 changes: 7 additions & 6 deletions src/mbgl/map/source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void Source::load() {

// URL may either be a TileJSON file, or a GeoJSON file.
FileSource* fs = util::ThreadContext::getFileSource();
req = fs->request({ Resource::Kind::Source, url }, [this](Response res) {
req = fs->request(Resource::source(url), [this](Response res) {
if (res.error) {
observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message)));
return;
Expand Down Expand Up @@ -267,16 +267,17 @@ TileData::State Source::addTile(const TileID& tileID, const StyleUpdateParameter

// If we don't find working tile data, we're just going to load it.
if (type == SourceType::Raster) {
auto tileData = std::make_shared<RasterTileData>(normalizedID,
newTile->data = std::make_shared<RasterTileData>(normalizedID,
parameters.pixelRatio,
info->tiles.at(0),
parameters.texturePool,
parameters.worker);
tileData->request(util::templateTileURL(info->tiles.at(0), normalizedID, parameters.pixelRatio), callback);
newTile->data = tileData;
parameters.worker,
callback);
} else {
std::unique_ptr<GeometryTileMonitor> monitor;

if (type == SourceType::Vector) {
monitor = std::make_unique<VectorTileMonitor>(normalizedID, info->tiles.at(0));
monitor = std::make_unique<VectorTileMonitor>(normalizedID, parameters.pixelRatio, info->tiles.at(0));
} else if (type == SourceType::Annotations) {
monitor = std::make_unique<AnnotationTileMonitor>(normalizedID, parameters.data);
} else if (type == SourceType::GeoJSON) {
Expand Down
10 changes: 6 additions & 4 deletions src/mbgl/map/vector_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,15 @@ util::ptr<const GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i)
return std::make_shared<VectorTileFeature>(features.at(i), *this);
}

VectorTileMonitor::VectorTileMonitor(const TileID& tileID_, const std::string& urlTemplate_)
: tileID(tileID_), urlTemplate(urlTemplate_) {
VectorTileMonitor::VectorTileMonitor(const TileID& tileID_, float pixelRatio_, const std::string& urlTemplate_)
: tileID(tileID_),
pixelRatio(pixelRatio_),
urlTemplate(urlTemplate_) {
}

std::unique_ptr<FileRequest> VectorTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback) {
const std::string url = util::templateTileURL(urlTemplate, tileID);
return util::ThreadContext::getFileSource()->request({ Resource::Kind::Tile, url }, [callback, this](Response res) {
const Resource resource = Resource::tile(urlTemplate, pixelRatio, tileID.x, tileID.y, tileID.sourceZ);
return util::ThreadContext::getFileSource()->request(resource, [callback, this](Response res) {
if (res.notModified) {
// We got the same data again. Abort early.
return;
Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/map/vector_tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ class TileID;

class VectorTileMonitor : public GeometryTileMonitor {
public:
VectorTileMonitor(const TileID&, const std::string& urlTemplate);
VectorTileMonitor(const TileID&, float pixelRatio, const std::string& urlTemplate);

std::unique_ptr<FileRequest> monitorTile(const GeometryTileMonitor::Callback&) override;

private:
TileID tileID;
float pixelRatio;
std::string urlTemplate;
};

Expand Down
36 changes: 15 additions & 21 deletions src/mbgl/sprite/sprite_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,10 @@ void SpriteStore::setURL(const std::string& url) {
return;
}

std::string spriteURL(url + (pixelRatio > 1 ? "@2x" : "") + ".png");
std::string jsonURL(url + (pixelRatio > 1 ? "@2x" : "") + ".json");

loader = std::make_unique<Loader>();

FileSource* fs = util::ThreadContext::getFileSource();
loader->jsonRequest = fs->request({ Resource::Kind::SpriteJSON, jsonURL },
[this, jsonURL](Response res) {
loader->jsonRequest = fs->request(Resource::spriteJSON(url, pixelRatio), [this](Response res) {
if (res.error) {
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
return;
Expand All @@ -57,24 +53,22 @@ void SpriteStore::setURL(const std::string& url) {
}
});

loader->spriteRequest =
fs->request({ Resource::Kind::SpriteImage, spriteURL },
[this, spriteURL](Response res) {
if (res.error) {
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
return;
}
loader->spriteRequest = fs->request(Resource::spriteImage(url, pixelRatio), [this](Response res) {
if (res.error) {
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
return;
}

if (res.notModified) {
// We got the same data back as last time. Abort early.
return;
}
if (res.notModified) {
// We got the same data back as last time. Abort early.
return;
}

if (!loader->image || *loader->image != *res.data) {
loader->image = res.data;
emitSpriteLoadedIfComplete();
}
});
if (!loader->image || *loader->image != *res.data) {
loader->image = res.data;
emitSpriteLoadedIfComplete();
}
});
}

void SpriteStore::emitSpriteLoadedIfComplete() {
Expand Down
82 changes: 82 additions & 0 deletions src/mbgl/storage/resource.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <mbgl/storage/resource.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/token.hpp>
#include <mbgl/util/url.hpp>

namespace mbgl {

Resource Resource::style(const std::string& url) {
return Resource {
Resource::Kind::Style,
url
};
}

Resource Resource::source(const std::string& url) {
return Resource {
Resource::Kind::Source,
url
};
}

Resource Resource::spriteImage(const std::string& base, float pixelRatio) {
return Resource {
Resource::Kind::SpriteImage,
base + (pixelRatio > 1 ? "@2x" : "") + ".png"
};
}

Resource Resource::spriteJSON(const std::string& base, float pixelRatio) {
return Resource {
Resource::Kind::SpriteJSON,
base + (pixelRatio > 1 ? "@2x" : "") + ".json"
};
}

Resource Resource::glyphs(const std::string& urlTemplate, const std::string& fontStack, const std::pair<uint16_t, uint16_t>& glyphRange) {
return Resource {
Resource::Kind::Glyphs,
util::replaceTokens(urlTemplate, [&](const std::string& token) {
if (token == "fontstack") {
return util::percentEncode(fontStack);
} else if (token == "range") {
return util::toString(glyphRange.first) + "-" + util::toString(glyphRange.second);
} else {
return std::string();
}
})
};
}

Resource Resource::tile(const std::string& urlTemplate, float pixelRatio, int32_t x, int32_t y, int8_t z) {
return Resource {
Resource::Kind::Tile,
util::replaceTokens(urlTemplate, [&](const std::string& token) {
if (token == "z") {
return util::toString(z);
} else if (token == "x") {
return util::toString(x);
} else if (token == "y") {
return util::toString(y);
} else if (token == "prefix") {
std::string prefix{ 2 };
prefix[0] = "0123456789abcdef"[x % 16];
prefix[1] = "0123456789abcdef"[y % 16];
return prefix;
} else if (token == "ratio") {
return std::string(pixelRatio > 1.0 ? "@2x" : "");
} else {
return std::string();
}
}),
Resource::TileData {
urlTemplate,
uint8_t(pixelRatio > 1.0 ? 2 : 1),
x,
y,
z
}
};
}

}
9 changes: 1 addition & 8 deletions src/mbgl/text/glyph_pbf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,8 @@ GlyphPBF::GlyphPBF(GlyphStore* store,
GlyphStore::Observer* observer_)
: parsed(false),
observer(observer_) {
// Load the glyph set URL
std::string url = util::replaceTokens(store->getURL(), [&](const std::string &name) -> std::string {
if (name == "fontstack") return util::percentEncode(fontStack);
if (name == "range") return util::toString(glyphRange.first) + "-" + util::toString(glyphRange.second);
return "";
});

FileSource* fs = util::ThreadContext::getFileSource();
req = fs->request({ Resource::Kind::Glyphs, url }, [this, store, fontStack, glyphRange](Response res) {
req = fs->request(Resource::glyphs(store->getURL(), fontStack, glyphRange), [this, store, fontStack, glyphRange](Response res) {
if (res.error) {
observer->onGlyphsError(fontStack, glyphRange, std::make_exception_ptr(std::runtime_error(res.error->message)));
return;
Expand Down
24 changes: 0 additions & 24 deletions src/mbgl/util/url.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#include <mbgl/util/url.hpp>
#include <mbgl/util/token.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/map/tile_id.hpp>

#include <cctype>
#include <iomanip>
Expand Down Expand Up @@ -50,26 +47,5 @@ std::string percentDecode(const std::string& input) {
return decoded;
}

std::string templateTileURL(const std::string& url, const TileID& id, float pixelRatio) {
return util::replaceTokens(url, [&](const std::string& token) -> std::string {
if (token == "z") {
return util::toString(id.sourceZ);
} else if (token == "x") {
return util::toString(id.x);
} else if (token == "y") {
return util::toString(id.y);
} else if (token == "prefix") {
std::string prefix{ 2 };
prefix[0] = "0123456789abcdef"[id.x % 16];
prefix[1] = "0123456789abcdef"[id.y % 16];
return prefix;
} else if (token == "ratio") {
return pixelRatio > 1.0 ? "@2x" : "";
} else {
return "";
}
});
}

} // namespace util
} // namespace mbgl
Loading