summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/map/map.hpp1
-rw-r--r--platform/qt/include/qmapbox.hpp3
-rw-r--r--platform/qt/include/qmapboxgl.hpp1
-rw-r--r--platform/qt/src/qmapbox.cpp1
-rw-r--r--src/mbgl/map/change.hpp3
-rw-r--r--src/mbgl/map/map.cpp9
-rw-r--r--src/mbgl/style/source_observer.hpp1
-rw-r--r--src/mbgl/style/style.cpp28
-rw-r--r--src/mbgl/style/style.hpp2
-rw-r--r--src/mbgl/style/tile_source_impl.cpp12
-rw-r--r--src/mbgl/style/tile_source_impl.hpp2
-rw-r--r--test/src/mbgl/test/stub_style_observer.hpp7
-rw-r--r--test/style/source.cpp39
13 files changed, 103 insertions, 6 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index 914c2cd0b3..2a0d2888bd 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -155,6 +155,7 @@ public:
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);
diff --git a/platform/qt/include/qmapbox.hpp b/platform/qt/include/qmapbox.hpp
index dcdc33d59d..0a6a41b3e1 100644
--- a/platform/qt/include/qmapbox.hpp
+++ b/platform/qt/include/qmapbox.hpp
@@ -45,7 +45,8 @@ enum MapChange {
MapChangeWillStartRenderingMap,
MapChangeDidFinishRenderingMap,
MapChangeDidFinishRenderingMapFullyRendered,
- MapChangeDidFinishLoadingStyle
+ MapChangeDidFinishLoadingStyle,
+ MapChangeSourceAttributionDidChange
};
struct Q_DECL_EXPORT CameraOptions {
diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp
index fec96e6fb7..ba5631e1e4 100644
--- a/platform/qt/include/qmapboxgl.hpp
+++ b/platform/qt/include/qmapboxgl.hpp
@@ -95,7 +95,6 @@ public:
NorthLeftwards,
};
-
QMapboxGL(QObject *parent = 0, const QMapboxGLSettings& = QMapboxGLSettings());
virtual ~QMapboxGL();
diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp
index 5f4ad01873..4a871c151d 100644
--- a/platform/qt/src/qmapbox.cpp
+++ b/platform/qt/src/qmapbox.cpp
@@ -32,6 +32,7 @@ static_assert(mbgl::underlying_type(QMapbox::MapChangeWillStartRenderingMap) ==
static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishRenderingMap) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMap), "error");
static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishRenderingMapFullyRendered) == mbgl::underlying_type(mbgl::MapChangeDidFinishRenderingMapFullyRendered), "error");
static_assert(mbgl::underlying_type(QMapbox::MapChangeDidFinishLoadingStyle) == mbgl::underlying_type(mbgl::MapChangeDidFinishLoadingStyle), "error");
+static_assert(mbgl::underlying_type(QMapbox::MapChangeSourceAttributionDidChange) == mbgl::underlying_type(mbgl::MapChangeSourceAttributionDidChange), "error");
namespace QMapbox {
diff --git a/src/mbgl/map/change.hpp b/src/mbgl/map/change.hpp
index 343d7d8e4f..50079af710 100644
--- a/src/mbgl/map/change.hpp
+++ b/src/mbgl/map/change.hpp
@@ -19,7 +19,8 @@ enum MapChange : uint8_t {
MapChangeWillStartRenderingMap = 11,
MapChangeDidFinishRenderingMap = 12,
MapChangeDidFinishRenderingMapFullyRendered = 13,
- MapChangeDidFinishLoadingStyle = 14
+ MapChangeDidFinishLoadingStyle = 14,
+ MapChangeSourceAttributionDidChange = 15
};
} // namespace mbgl
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 9d8a063c44..a67de9c2c4 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -38,6 +38,7 @@ class Map::Impl : public style::Observer {
public:
Impl(View&, FileSource&, MapMode, GLContextMode, ConstrainMode, ViewportMode);
+ void onSourceAttributionChanged(style::Source&, const std::string&) override;
void onUpdate(Update) override;
void onStyleLoaded() override;
void onStyleError() override;
@@ -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;
@@ -980,6 +985,10 @@ void Map::onLowMemory() {
impl->view.invalidate();
}
+void Map::Impl::onSourceAttributionChanged(style::Source&, const std::string&) {
+ view.notifyMapChange(MapChangeSourceAttributionDidChange);
+}
+
void Map::Impl::onUpdate(Update flags) {
if (flags & Update::Dimensions) {
transform.resize(view.getSize());
diff --git a/src/mbgl/style/source_observer.hpp b/src/mbgl/style/source_observer.hpp
index 26b25b78da..a6cdab6ba2 100644
--- a/src/mbgl/style/source_observer.hpp
+++ b/src/mbgl/style/source_observer.hpp
@@ -17,6 +17,7 @@ public:
virtual ~SourceObserver() = default;
virtual void onSourceLoaded(Source&) {}
+ virtual void onSourceAttributionChanged(Source&, const std::string&) {}
virtual void onSourceError(Source&, std::exception_ptr) {}
virtual void onTileChanged(Source&, const OverscaledTileID&) {}
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index a684db62d5..f0917c3b60 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -18,6 +18,7 @@
#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>
@@ -25,6 +26,7 @@
#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>
@@ -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(std::move(attribution));
+ }
+ }
+
+ case SourceType::GeoJSON:
+ case SourceType::Video:
+ case SourceType::Annotations:
+ break;
+ }
+ }
+ return result;
+}
+
bool Style::hasTransitions() const {
return hasPendingTransitions;
}
@@ -465,6 +489,10 @@ void Style::onSourceLoaded(Source& source) {
observer->onUpdate(Update::Repaint);
}
+void Style::onSourceAttributionChanged(Source& source, const 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",
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index a3c51a45e7..5bd886923a 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -67,6 +67,7 @@ public:
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;
@@ -132,6 +133,7 @@ private:
// SourceObserver implementation.
void onSourceLoaded(Source&) override;
+ void onSourceAttributionChanged(Source&, const 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;
diff --git a/src/mbgl/style/tile_source_impl.cpp b/src/mbgl/style/tile_source_impl.cpp
index b201045d03..a318fdd755 100644
--- a/src/mbgl/style/tile_source_impl.cpp
+++ b/src/mbgl/style/tile_source_impl.cpp
@@ -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();
@@ -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
}
@@ -105,6 +106,9 @@ void TileSourceImpl::loadDescription(FileSource& fileSource) {
loaded = true;
observer->onSourceLoaded(base);
+ if (attributionChanged) {
+ observer->onSourceAttributionChanged(base, newTileset.attribution);
+ }
}
});
}
@@ -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
diff --git a/src/mbgl/style/tile_source_impl.hpp b/src/mbgl/style/tile_source_impl.hpp
index d0b4b3d8ee..4ce1eac223 100644
--- a/src/mbgl/style/tile_source_impl.hpp
+++ b/src/mbgl/style/tile_source_impl.hpp
@@ -33,6 +33,8 @@ public:
const variant<std::string, Tileset>& getURLOrTileset() const {
return urlOrTileset;
}
+
+ std::string getAttribution() const;
protected:
Range<uint8_t> getZoomRange() final;
diff --git a/test/src/mbgl/test/stub_style_observer.hpp b/test/src/mbgl/test/stub_style_observer.hpp
index aa780121f5..7189fd8af4 100644
--- a/test/src/mbgl/test/stub_style_observer.hpp
+++ b/test/src/mbgl/test/stub_style_observer.hpp
@@ -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:
@@ -30,6 +30,10 @@ public:
if (sourceLoaded) sourceLoaded(source);
}
+ void onSourceAttributionChanged(Source& source, const std::string& attribution) override {
+ if (sourceAttributionChanged) sourceAttributionChanged(source, attribution);
+ }
+
void onSourceError(Source& source, std::exception_ptr error) override {
if (sourceError) sourceError(source, error);
}
@@ -52,6 +56,7 @@ public:
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;
diff --git a/test/style/source.cpp b/test/style/source.cpp
index 519ca9288e..859aa82893 100644
--- a/test/style/source.cpp
+++ b/test/style/source.cpp
@@ -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->loadDescription(test.fileSource);
+ source.baseImpl->updateTiles(test.updateParameters);
+
+ test.run();
+}