summaryrefslogtreecommitdiff
path: root/platform/default/src/mbgl/map/map_snapshotter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/default/src/mbgl/map/map_snapshotter.cpp')
-rw-r--r--platform/default/src/mbgl/map/map_snapshotter.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/platform/default/src/mbgl/map/map_snapshotter.cpp b/platform/default/src/mbgl/map/map_snapshotter.cpp
new file mode 100644
index 0000000000..ae14b20721
--- /dev/null
+++ b/platform/default/src/mbgl/map/map_snapshotter.cpp
@@ -0,0 +1,224 @@
+#include <mbgl/map/map_snapshotter.hpp>
+
+#include <mbgl/actor/actor_ref.hpp>
+#include <mbgl/gl/headless_frontend.hpp>
+#include <mbgl/map/map.hpp>
+#include <mbgl/map/transform_state.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/util/event.hpp>
+#include <mbgl/map/transform.hpp>
+
+namespace mbgl {
+
+class MapSnapshotter::Impl {
+public:
+ Impl(FileSource*,
+ std::shared_ptr<Scheduler>,
+ const std::pair<bool, std::string> style,
+ const Size&,
+ const float pixelRatio,
+ const optional<CameraOptions> cameraOptions,
+ const optional<LatLngBounds> region,
+ const optional<std::string> programCacheDir,
+ const optional<std::string> localFontFamily = {});
+
+ void setStyleURL(std::string styleURL);
+ std::string getStyleURL() const;
+
+ void setStyleJSON(std::string styleJSON);
+ std::string getStyleJSON() const;
+
+ void setSize(Size);
+ Size getSize() const;
+
+ void setCameraOptions(CameraOptions);
+ CameraOptions getCameraOptions() const;
+
+ void setRegion(LatLngBounds);
+ LatLngBounds getRegion() const;
+
+ void snapshot(ActorRef<MapSnapshotter::Callback>);
+
+private:
+ std::shared_ptr<Scheduler> scheduler;
+ HeadlessFrontend frontend;
+ Map map;
+};
+
+MapSnapshotter::Impl::Impl(FileSource* fileSource,
+ std::shared_ptr<Scheduler> scheduler_,
+ const std::pair<bool, std::string> style,
+ const Size& size,
+ const float pixelRatio,
+ const optional<CameraOptions> cameraOptions,
+ const optional<LatLngBounds> region,
+ const optional<std::string> programCacheDir,
+ const optional<std::string> localFontFamily)
+ : scheduler(std::move(scheduler_))
+ , frontend(size, pixelRatio, *fileSource, *scheduler, programCacheDir, GLContextMode::Unique, localFontFamily)
+ , map(frontend, MapObserver::nullObserver(), size, pixelRatio, *fileSource, *scheduler, MapMode::Static) {
+
+ if (style.first) {
+ map.getStyle().loadJSON(style.second);
+ } else{
+ map.getStyle().loadURL(style.second);
+ }
+
+ if (cameraOptions) {
+ map.jumpTo(*cameraOptions);
+ }
+
+ // Set region, if specified
+ if (region) {
+ this->setRegion(*region);
+ }
+}
+
+void MapSnapshotter::Impl::snapshot(ActorRef<MapSnapshotter::Callback> callback) {
+ map.renderStill([this, callback = std::move(callback)] (std::exception_ptr error) mutable {
+
+ // Create lambda that captures the current transform state
+ // and can be used to translate for geographic to screen
+ // coordinates
+ assert (frontend.getTransformState());
+ PointForFn pointForFn { [=, center=map.getLatLng(), transformState = *frontend.getTransformState()] (const LatLng& latLng) {
+ LatLng unwrappedLatLng = latLng.wrapped();
+ unwrappedLatLng.unwrapForShortestPath(center);
+ Transform transform { transformState };
+ return transform.latLngToScreenCoordinate(unwrappedLatLng);
+ }};
+
+ // Create lambda that captures the current transform state
+ // and can be used to translate for geographic to screen
+ // coordinates
+ assert (frontend.getTransformState());
+ LatLngForFn latLngForFn { [=, transformState = *frontend.getTransformState()] (const ScreenCoordinate& screenCoordinate) {
+ Transform transform { transformState };
+ return transform.screenCoordinateToLatLng(screenCoordinate);
+ }};
+
+ // Collect all source attributions
+ std::vector<std::string> attributions;
+ for (auto source : map.getStyle().getSources()) {
+ auto attribution = source->getAttribution();
+ if (attribution) {
+ attributions.push_back(*attribution);
+ }
+ }
+
+ // Invoke callback
+ callback.invoke(
+ &MapSnapshotter::Callback::operator(),
+ error,
+ error ? PremultipliedImage() : frontend.readStillImage(),
+ std::move(attributions),
+ std::move(pointForFn),
+ std::move(latLngForFn)
+ );
+ });
+}
+
+void MapSnapshotter::Impl::setStyleURL(std::string styleURL) {
+ map.getStyle().loadURL(styleURL);
+}
+
+std::string MapSnapshotter::Impl::getStyleURL() const {
+ return map.getStyle().getURL();
+}
+
+void MapSnapshotter::Impl::setStyleJSON(std::string styleJSON) {
+ map.getStyle().loadJSON(styleJSON);
+}
+
+std::string MapSnapshotter::Impl::getStyleJSON() const {
+ return map.getStyle().getJSON();
+}
+
+void MapSnapshotter::Impl::setSize(Size size) {
+ map.setSize(size);
+ frontend.setSize(size);
+}
+
+Size MapSnapshotter::Impl::getSize() const {
+ return map.getSize();
+}
+
+void MapSnapshotter::Impl::setCameraOptions(CameraOptions cameraOptions) {
+ map.jumpTo(cameraOptions);
+}
+
+CameraOptions MapSnapshotter::Impl::getCameraOptions() const {
+ EdgeInsets insets;
+ return map.getCameraOptions(insets);
+}
+
+void MapSnapshotter::Impl::setRegion(LatLngBounds region) {
+ mbgl::EdgeInsets insets = { 0, 0, 0, 0 };
+ std::vector<LatLng> latLngs = { region.southwest(), region.northeast() };
+ map.jumpTo(map.cameraForLatLngs(latLngs, insets));
+}
+
+LatLngBounds MapSnapshotter::Impl::getRegion() const {
+ return map.latLngBoundsForCamera(getCameraOptions());
+}
+
+MapSnapshotter::MapSnapshotter(FileSource* fileSource,
+ std::shared_ptr<Scheduler> scheduler,
+ const std::pair<bool, std::string> style,
+ const Size& size,
+ const float pixelRatio,
+ const optional<CameraOptions> cameraOptions,
+ const optional<LatLngBounds> region,
+ const optional<std::string> programCacheDir,
+ const optional<std::string> localFontFamily)
+ : impl(std::make_unique<util::Thread<MapSnapshotter::Impl>>("Map Snapshotter", fileSource, std::move(scheduler), style, size, pixelRatio, cameraOptions, region, programCacheDir, localFontFamily)) {
+}
+
+MapSnapshotter::~MapSnapshotter() = default;
+
+void MapSnapshotter::snapshot(ActorRef<MapSnapshotter::Callback> callback) {
+ impl->actor().invoke(&Impl::snapshot, std::move(callback));
+}
+
+void MapSnapshotter::setStyleURL(const std::string& styleURL) {
+ impl->actor().invoke(&Impl::setStyleURL, styleURL);
+}
+
+std::string MapSnapshotter::getStyleURL() const {
+ return impl->actor().ask(&Impl::getStyleURL).get();
+}
+
+void MapSnapshotter::setStyleJSON(const std::string& styleJSON) {
+ impl->actor().invoke(&Impl::setStyleJSON, styleJSON);
+}
+
+std::string MapSnapshotter::getStyleJSON() const {
+ return impl->actor().ask(&Impl::getStyleJSON).get();
+}
+
+void MapSnapshotter::setSize(const Size& size) {
+ impl->actor().invoke(&Impl::setSize, size);
+}
+
+Size MapSnapshotter::getSize() const {
+ return impl->actor().ask(&Impl::getSize).get();
+}
+
+void MapSnapshotter::setCameraOptions(const CameraOptions& options) {
+ impl->actor().invoke(&Impl::setCameraOptions, options);
+}
+
+CameraOptions MapSnapshotter::getCameraOptions() const {
+ return impl->actor().ask(&Impl::getCameraOptions).get();
+}
+
+void MapSnapshotter::setRegion(const LatLngBounds& bounds) {
+ impl->actor().invoke(&Impl::setRegion, std::move(bounds));
+}
+
+LatLngBounds MapSnapshotter::getRegion() const {
+ return impl->actor().ask(&Impl::getRegion).get();
+}
+
+} // namespace mbgl