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

Commit

Permalink
[core] Source-driven attribution
Browse files Browse the repository at this point in the history
Implemented observer callbacks so the style knows when the source’s attribution changes and the map knows when the style’s attribution changes. Also implemented a getter for a tile source’s attribution.

Fixes #2723.
  • Loading branch information
1ec5 committed Sep 22, 2016
1 parent e8d4726 commit 5a26cd4
Show file tree
Hide file tree
Showing 12 changed files with 103 additions and 5 deletions.
1 change: 1 addition & 0 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class Map : private util::noncopyable {
style::Source* getSource(const std::string& sourceID);
void addSource(std::unique_ptr<style::Source>);
void removeSource(const std::string& sourceID);
std::vector<std::string> getAttributions() const;

// Layers
style::Layer* getLayer(const std::string& layerID);
Expand Down
3 changes: 2 additions & 1 deletion platform/qt/include/qmapboxgl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ class Q_DECL_EXPORT QMapboxGL : public QObject
MapChangeDidFinishRenderingFrameFullyRendered,
MapChangeWillStartRenderingMap,
MapChangeDidFinishRenderingMap,
MapChangeDidFinishRenderingMapFullyRendered
MapChangeDidFinishRenderingMapFullyRendered,
MapChangeSourceAttributionDidChange
};

QMapboxGL(QObject *parent = 0, const QMapboxGLSettings& = QMapboxGLSettings());
Expand Down
1 change: 1 addition & 0 deletions platform/qt/src/qmapboxgl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingFrameF
static_assert(mbgl::underlying_type(QMapboxGL::MapChangeWillStartRenderingMap) == mbgl::underlying_type(mbgl::MapChangeWillStartRenderingMap), "error");
static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMap), "error");
static_assert(mbgl::underlying_type(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMapFullyRendered), "error");
static_assert(mbgl::underlying_type(QMapboxGL::MapChangeSourceAttributionDidChange) == mbgl::underlying_type(mbgl::MapChangeSourceAttributionDidChange), "error");

namespace {

Expand Down
3 changes: 2 additions & 1 deletion src/mbgl/map/change.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ enum MapChange : uint8_t {
MapChangeWillStartRenderingMap = 11,
MapChangeDidFinishRenderingMap = 12,
MapChangeDidFinishRenderingMapFullyRendered = 13,
MapChangeDidFinishLoadingStyle = 14
MapChangeDidFinishLoadingStyle = 14,
MapChangeSourceAttributionDidChange = 15
};

} // namespace mbgl
9 changes: 9 additions & 0 deletions src/mbgl/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Map::Impl : public style::Observer {
public:
Impl(View&, FileSource&, MapMode, GLContextMode, ConstrainMode, ViewportMode);

void onSourceAttributionChanged(style::Source&, std::string) override;
void onUpdate(Update) override;
void onStyleLoaded() override;
void onStyleError() override;
Expand Down Expand Up @@ -785,6 +786,10 @@ void Map::removeSource(const std::string& sourceID) {
}
}

std::vector<std::string> Map::getAttributions() const {
return impl->style ? impl->style->getAttributions() : std::vector<std::string>();
}

style::Layer* Map::getLayer(const std::string& layerID) {
if (impl->style) {
impl->styleMutated = true;
Expand Down Expand Up @@ -958,6 +963,10 @@ void Map::onLowMemory() {
impl->view.invalidate();
}

void Map::Impl::onSourceAttributionChanged(style::Source&, std::string) {
view.notifyMapChange(MapChangeSourceAttributionDidChange);
}

void Map::Impl::onUpdate(Update flags) {
if (flags & Update::Dimensions) {
transform.resize(view.getSize());
Expand Down
1 change: 1 addition & 0 deletions src/mbgl/style/source_observer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class SourceObserver {
virtual ~SourceObserver() = default;

virtual void onSourceLoaded(Source&) {}
virtual void onSourceAttributionChanged(Source&, std::string) {}
virtual void onSourceError(Source&, std::exception_ptr) {}

virtual void onTileChanged(Source&, const OverscaledTileID&) {}
Expand Down
28 changes: 28 additions & 0 deletions src/mbgl/style/style.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
#include <mbgl/style/update_parameters.hpp>
#include <mbgl/style/cascade_parameters.hpp>
#include <mbgl/style/calculation_parameters.hpp>
#include <mbgl/style/tile_source_impl.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/renderer/render_item.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/tileset.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/math/minmax.hpp>

Expand Down Expand Up @@ -293,6 +295,28 @@ Source* Style::getSource(const std::string& id) const {
return it != sources.end() ? it->get() : nullptr;
}

std::vector<std::string> Style::getAttributions() const {
std::vector<std::string> result;
for (const auto& source : sources) {
switch (source->baseImpl->type) {
case SourceType::Vector:
case SourceType::Raster: {
style::TileSourceImpl* tileSource = static_cast<style::TileSourceImpl*>(source->baseImpl.get());
auto attribution = tileSource->getAttribution();
if (!attribution.empty()) {
result.push_back(attribution);
}
}

case SourceType::GeoJSON:
case SourceType::Video:
case SourceType::Annotations:
break;
}
}
return result;
}

bool Style::hasTransitions() const {
return hasPendingTransitions;
}
Expand Down Expand Up @@ -465,6 +489,10 @@ void Style::onSourceLoaded(Source& source) {
observer->onUpdate(Update::Repaint);
}

void Style::onSourceAttributionChanged(Source& source, std::string attribution) {
observer->onSourceAttributionChanged(source, attribution);
}

void Style::onSourceError(Source& source, std::exception_ptr error) {
lastError = error;
Log::Error(Event::Style, "Failed to load source %s: %s",
Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/style/style.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class Style : public GlyphAtlasObserver,
Source* getSource(const std::string& id) const;
void addSource(std::unique_ptr<Source>);
void removeSource(const std::string& sourceID);
std::vector<std::string> getAttributions() const;

std::vector<const Layer*> getLayers() const;
Layer* getLayer(const std::string& id) const;
Expand Down Expand Up @@ -132,6 +133,7 @@ class Style : public GlyphAtlasObserver,

// SourceObserver implementation.
void onSourceLoaded(Source&) override;
void onSourceAttributionChanged(Source&, std::string) override;
void onSourceError(Source&, std::exception_ptr) override;
void onTileChanged(Source&, const OverscaledTileID&) override;
void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) override;
Expand Down
12 changes: 10 additions & 2 deletions src/mbgl/style/tile_source_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void TileSourceImpl::loadDescription(FileSource& fileSource) {
}

// Check whether previous information specifies different tile
bool attributionChanged = false;
if (tileset.tiles != newTileset.tiles) {
// Tile URLs changed: force tiles to be reloaded.
invalidateTiles();
Expand All @@ -95,8 +96,8 @@ void TileSourceImpl::loadDescription(FileSource& fileSource) {
// This is done automatically when we trigger the onSourceLoaded observer below.

// Attribution changed: We need to notify the embedding application that this
// changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723
// This is not yet implemented.
// changed.
attributionChanged = true;

// Center/bounds changed: We're not using these values currently
}
Expand All @@ -105,6 +106,9 @@ void TileSourceImpl::loadDescription(FileSource& fileSource) {
loaded = true;

observer->onSourceLoaded(base);
if (attributionChanged) {
observer->onSourceAttributionChanged(base, newTileset.attribution);
}
}
});
}
Expand All @@ -114,5 +118,9 @@ Range<uint8_t> TileSourceImpl::getZoomRange() {
return tileset.zoomRange;
}

std::string TileSourceImpl::getAttribution() const {
return loaded ? tileset.attribution : "";
}

} // namespace style
} // namespace mbgl
2 changes: 2 additions & 0 deletions src/mbgl/style/tile_source_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class TileSourceImpl : public Source::Impl {
const variant<std::string, Tileset>& getURLOrTileset() const {
return urlOrTileset;
}

std::string getAttribution() const;

protected:
Range<uint8_t> getZoomRange() final;
Expand Down
7 changes: 6 additions & 1 deletion test/src/mbgl/test/stub_style_observer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ using namespace mbgl;
using namespace mbgl::style;

/**
* An implementation of style::Observer that forwards all methods to dynamically-settable lambas.
* An implementation of style::Observer that forwards all methods to dynamically-settable lambdas.
*/
class StubStyleObserver : public style::Observer {
public:
Expand All @@ -30,6 +30,10 @@ class StubStyleObserver : public style::Observer {
if (sourceLoaded) sourceLoaded(source);
}

void onSourceAttributionChanged(Source& source, std::string attribution) override {
if (sourceAttributionChanged) sourceAttributionChanged(source, attribution);
}

void onSourceError(Source& source, std::exception_ptr error) override {
if (sourceError) sourceError(source, error);
}
Expand All @@ -52,6 +56,7 @@ class StubStyleObserver : public style::Observer {
std::function<void ()> spriteLoaded;
std::function<void (std::exception_ptr)> spriteError;
std::function<void (Source&)> sourceLoaded;
std::function<void (Source&, std::string)> sourceAttributionChanged;
std::function<void (Source&, std::exception_ptr)> sourceError;
std::function<void (Source&, const OverscaledTileID&)> tileChanged;
std::function<void (Source&, const OverscaledTileID&, std::exception_ptr)> tileError;
Expand Down
39 changes: 39 additions & 0 deletions test/style/source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,42 @@ TEST(Source, VectorTileCancel) {

test.run();
}

TEST(Source, RasterTileAttribution) {
SourceTest test;

std::string mapboxOSM = ("<a href='https://www.mapbox.com/about/maps/' target='_blank'>&copy; Mapbox</a> "
"<a href='http://www.openstreetmap.org/about/' target='_blank'>©️ OpenStreetMap</a>");

test.fileSource.tileResponse = [&] (const Resource&) {
Response response;
response.noContent = true;
return response;
};

test.fileSource.sourceResponse = [&] (const Resource& resource) {
EXPECT_EQ("url", resource.url);
Response response;
response.data = std::make_unique<std::string>(R"TILEJSON({ "tilejson": "2.1.0", "attribution": ")TILEJSON" +
mapboxOSM +
R"TILEJSON(", "tiles": [ "tiles" ] })TILEJSON");
return response;
};

test.observer.sourceAttributionChanged = [&] (Source&, std::string attribution) {
EXPECT_EQ(mapboxOSM, attribution);
EXPECT_FALSE(mapboxOSM.find("©️ OpenStreetMap") == std::string::npos);
test.end();
};

test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
FAIL() << "Should never be called";
};

RasterSource source("source", "url", 512);
source.baseImpl->setObserver(&test.observer);
source.baseImpl->load(test.fileSource);
source.baseImpl->update(test.updateParameters);

test.run();
}

0 comments on commit 5a26cd4

Please sign in to comment.