1 #include <mbgl/map/map.hpp>
2 #include <mbgl/map/camera.hpp>
3 #include <mbgl/map/transform.hpp>
4 #include <mbgl/map/transform_state.hpp>
5 #include <mbgl/annotation/annotation_manager.hpp>
6 #include <mbgl/style/style_impl.hpp>
7 #include <mbgl/style/observer.hpp>
8 #include <mbgl/renderer/update_parameters.hpp>
9 #include <mbgl/renderer/renderer_frontend.hpp>
10 #include <mbgl/renderer/renderer_observer.hpp>
11 #include <mbgl/storage/file_source.hpp>
12 #include <mbgl/storage/resource.hpp>
13 #include <mbgl/storage/response.hpp>
14 #include <mbgl/util/constants.hpp>
15 #include <mbgl/util/math.hpp>
16 #include <mbgl/util/exception.hpp>
17 #include <mbgl/util/mapbox.hpp>
18 #include <mbgl/util/tile_coordinate.hpp>
19 #include <mbgl/actor/scheduler.hpp>
20 #include <mbgl/util/logging.hpp>
21 #include <mbgl/math/log2.hpp>
22 #include <utility>
23 
24 namespace mbgl {
25 
26 using namespace style;
27 
28 struct StillImageRequest {
StillImageRequestmbgl::StillImageRequest29     StillImageRequest(Map::StillImageCallback&& callback_)
30         : callback(std::move(callback_)) {
31     }
32 
33     Map::StillImageCallback callback;
34 };
35 
36 class Map::Impl : public style::Observer,
37                   public RendererObserver {
38 public:
39     Impl(Map&,
40          RendererFrontend&,
41          MapObserver&,
42          float pixelRatio,
43          FileSource&,
44          Scheduler&,
45          MapMode,
46          ConstrainMode,
47          ViewportMode);
48 
49     ~Impl();
50 
51     // StyleObserver
52     void onSourceChanged(style::Source&) override;
53     void onUpdate() override;
54     void onStyleLoading() override;
55     void onStyleLoaded() override;
56     void onStyleError(std::exception_ptr) override;
57 
58     // RendererObserver
59     void onInvalidate() override;
60     void onResourceError(std::exception_ptr) override;
61     void onWillStartRenderingFrame() override;
62     void onDidFinishRenderingFrame(RenderMode, bool) override;
63     void onWillStartRenderingMap() override;
64     void onDidFinishRenderingMap() override;
65 
66     Map& map;
67     MapObserver& observer;
68     RendererFrontend& rendererFrontend;
69     FileSource& fileSource;
70     Scheduler& scheduler;
71 
72     Transform transform;
73 
74     const MapMode mode;
75     const float pixelRatio;
76 
77     MapDebugOptions debugOptions { MapDebugOptions::NoDebug };
78 
79     std::unique_ptr<Style> style;
80     AnnotationManager annotationManager;
81 
82     bool cameraMutated = false;
83 
84     uint8_t prefetchZoomDelta = util::DEFAULT_PREFETCH_ZOOM_DELTA;
85 
86     bool loading = false;
87     bool rendererFullyLoaded;
88     std::unique_ptr<StillImageRequest> stillImageRequest;
89 };
90 
Map(RendererFrontend & rendererFrontend,MapObserver & mapObserver,const Size size,const float pixelRatio,FileSource & fileSource,Scheduler & scheduler,MapMode mapMode,ConstrainMode constrainMode,ViewportMode viewportMode)91 Map::Map(RendererFrontend& rendererFrontend,
92          MapObserver& mapObserver,
93          const Size size,
94          const float pixelRatio,
95          FileSource& fileSource,
96          Scheduler& scheduler,
97          MapMode mapMode,
98          ConstrainMode constrainMode,
99          ViewportMode viewportMode)
100     : impl(std::make_unique<Impl>(*this,
101                                   rendererFrontend,
102                                   mapObserver,
103                                   pixelRatio,
104                                   fileSource,
105                                   scheduler,
106                                   mapMode,
107                                   constrainMode,
108                                   viewportMode)) {
109     impl->transform.resize(size);
110 }
111 
Impl(Map & map_,RendererFrontend & frontend,MapObserver & mapObserver,float pixelRatio_,FileSource & fileSource_,Scheduler & scheduler_,MapMode mode_,ConstrainMode constrainMode_,ViewportMode viewportMode_)112 Map::Impl::Impl(Map& map_,
113                 RendererFrontend& frontend,
114                 MapObserver& mapObserver,
115                 float pixelRatio_,
116                 FileSource& fileSource_,
117                 Scheduler& scheduler_,
118                 MapMode mode_,
119                 ConstrainMode constrainMode_,
120                 ViewportMode viewportMode_)
121     : map(map_),
122       observer(mapObserver),
123       rendererFrontend(frontend),
124       fileSource(fileSource_),
125       scheduler(scheduler_),
126       transform(observer,
127                 constrainMode_,
128                 viewportMode_),
129       mode(mode_),
130       pixelRatio(pixelRatio_),
131       style(std::make_unique<Style>(scheduler, fileSource, pixelRatio)),
132       annotationManager(*style) {
133 
134     style->impl->setObserver(this);
135     rendererFrontend.setObserver(*this);
136 }
137 
~Impl()138 Map::Impl::~Impl() {
139     // Explicitly reset the RendererFrontend first to ensure it releases
140     // All shared resources (AnnotationManager)
141     rendererFrontend.reset();
142 };
143 
144 Map::~Map() = default;
145 
renderStill(StillImageCallback callback)146 void Map::renderStill(StillImageCallback callback) {
147     if (!callback) {
148         Log::Error(Event::General, "StillImageCallback not set");
149         return;
150     }
151 
152     if (impl->mode != MapMode::Static && impl->mode != MapMode::Tile) {
153         callback(std::make_exception_ptr(util::MisuseException("Map is not in static or tile image render modes")));
154         return;
155     }
156 
157     if (impl->stillImageRequest) {
158         callback(std::make_exception_ptr(util::MisuseException("Map is currently rendering an image")));
159         return;
160     }
161 
162     if (impl->style->impl->getLastError()) {
163         callback(impl->style->impl->getLastError());
164         return;
165     }
166 
167     impl->stillImageRequest = std::make_unique<StillImageRequest>(std::move(callback));
168 
169     impl->onUpdate();
170 }
171 
renderStill(const CameraOptions & camera,MapDebugOptions debugOptions,StillImageCallback callback)172 void Map::renderStill(const CameraOptions& camera, MapDebugOptions debugOptions, StillImageCallback callback) {
173     impl->cameraMutated = true;
174     impl->debugOptions = debugOptions;
175     impl->transform.jumpTo(camera);
176     renderStill(std::move(callback));
177 }
178 
triggerRepaint()179 void Map::triggerRepaint() {
180     impl->onUpdate();
181 }
182 
183 #pragma mark - Map::Impl RendererObserver
184 
onWillStartRenderingMap()185 void Map::Impl::onWillStartRenderingMap() {
186     if (mode == MapMode::Continuous) {
187         observer.onWillStartRenderingMap();
188     }
189 }
190 
onWillStartRenderingFrame()191 void Map::Impl::onWillStartRenderingFrame() {
192     if (mode == MapMode::Continuous) {
193         observer.onWillStartRenderingFrame();
194     }
195 }
196 
onDidFinishRenderingFrame(RenderMode renderMode,bool needsRepaint)197 void Map::Impl::onDidFinishRenderingFrame(RenderMode renderMode, bool needsRepaint) {
198     rendererFullyLoaded = renderMode == RenderMode::Full;
199 
200     if (mode == MapMode::Continuous) {
201         observer.onDidFinishRenderingFrame(MapObserver::RenderMode(renderMode));
202 
203         if (needsRepaint || transform.inTransition()) {
204             onUpdate();
205         }
206     } else if (stillImageRequest && rendererFullyLoaded) {
207         auto request = std::move(stillImageRequest);
208         request->callback(nullptr);
209     }
210 }
211 
onDidFinishRenderingMap()212 void Map::Impl::onDidFinishRenderingMap() {
213     if (mode == MapMode::Continuous && loading) {
214         observer.onDidFinishRenderingMap(MapObserver::RenderMode::Full);
215         if (loading) {
216             loading = false;
217             observer.onDidFinishLoadingMap();
218         }
219     }
220 };
221 
222 #pragma mark - Style
223 
getStyle()224 style::Style& Map::getStyle() {
225     return *impl->style;
226 }
227 
getStyle() const228 const style::Style& Map::getStyle() const {
229     return *impl->style;
230 }
231 
setStyle(std::unique_ptr<Style> style)232 void Map::setStyle(std::unique_ptr<Style> style) {
233     assert(style);
234     impl->onStyleLoading();
235     impl->style = std::move(style);
236     impl->annotationManager.setStyle(*impl->style);
237 }
238 
239 #pragma mark - Transitions
240 
cancelTransitions()241 void Map::cancelTransitions() {
242     impl->transform.cancelTransitions();
243     impl->onUpdate();
244 }
245 
setGestureInProgress(bool inProgress)246 void Map::setGestureInProgress(bool inProgress) {
247     impl->transform.setGestureInProgress(inProgress);
248     impl->onUpdate();
249 }
250 
isGestureInProgress() const251 bool Map::isGestureInProgress() const {
252     return impl->transform.isGestureInProgress();
253 }
254 
isRotating() const255 bool Map::isRotating() const {
256     return impl->transform.isRotating();
257 }
258 
isScaling() const259 bool Map::isScaling() const {
260     return impl->transform.isScaling();
261 }
262 
isPanning() const263 bool Map::isPanning() const {
264     return impl->transform.isPanning();
265 }
266 
267 #pragma mark -
268 
getCameraOptions(const EdgeInsets & padding) const269 CameraOptions Map::getCameraOptions(const EdgeInsets& padding) const {
270     return impl->transform.getCameraOptions(padding);
271 }
272 
jumpTo(const CameraOptions & camera)273 void Map::jumpTo(const CameraOptions& camera) {
274     impl->cameraMutated = true;
275     impl->transform.jumpTo(camera);
276     impl->onUpdate();
277 }
278 
easeTo(const CameraOptions & camera,const AnimationOptions & animation)279 void Map::easeTo(const CameraOptions& camera, const AnimationOptions& animation) {
280     impl->cameraMutated = true;
281     impl->transform.easeTo(camera, animation);
282     impl->onUpdate();
283 }
284 
flyTo(const CameraOptions & camera,const AnimationOptions & animation)285 void Map::flyTo(const CameraOptions& camera, const AnimationOptions& animation) {
286     impl->cameraMutated = true;
287     impl->transform.flyTo(camera, animation);
288     impl->onUpdate();
289 }
290 
291 #pragma mark - Position
292 
moveBy(const ScreenCoordinate & point,const AnimationOptions & animation)293 void Map::moveBy(const ScreenCoordinate& point, const AnimationOptions& animation) {
294     impl->cameraMutated = true;
295     impl->transform.moveBy(point, animation);
296     impl->onUpdate();
297 }
298 
setLatLng(const LatLng & latLng,const AnimationOptions & animation)299 void Map::setLatLng(const LatLng& latLng, const AnimationOptions& animation) {
300     impl->cameraMutated = true;
301     setLatLng(latLng, optional<ScreenCoordinate> {}, animation);
302 }
303 
setLatLng(const LatLng & latLng,const EdgeInsets & padding,const AnimationOptions & animation)304 void Map::setLatLng(const LatLng& latLng, const EdgeInsets& padding, const AnimationOptions& animation) {
305     impl->cameraMutated = true;
306     impl->transform.setLatLng(latLng, padding, animation);
307     impl->onUpdate();
308 }
309 
setLatLng(const LatLng & latLng,optional<ScreenCoordinate> anchor,const AnimationOptions & animation)310 void Map::setLatLng(const LatLng& latLng, optional<ScreenCoordinate> anchor, const AnimationOptions& animation) {
311     impl->cameraMutated = true;
312     impl->transform.setLatLng(latLng, anchor, animation);
313     impl->onUpdate();
314 }
315 
getLatLng(const EdgeInsets & padding) const316 LatLng Map::getLatLng(const EdgeInsets& padding) const {
317     return impl->transform.getLatLng(padding);
318 }
319 
resetPosition(const EdgeInsets & padding)320 void Map::resetPosition(const EdgeInsets& padding) {
321     impl->cameraMutated = true;
322     CameraOptions camera;
323     camera.angle = 0;
324     camera.pitch = 0;
325     camera.center = LatLng(0, 0);
326     camera.padding = padding;
327     camera.zoom = 0;
328     impl->transform.jumpTo(camera);
329     impl->onUpdate();
330 }
331 
332 
333 #pragma mark - Zoom
334 
setZoom(double zoom,const AnimationOptions & animation)335 void Map::setZoom(double zoom, const AnimationOptions& animation) {
336     impl->cameraMutated = true;
337     setZoom(zoom, EdgeInsets(), animation);
338 }
339 
setZoom(double zoom,optional<ScreenCoordinate> anchor,const AnimationOptions & animation)340 void Map::setZoom(double zoom, optional<ScreenCoordinate> anchor, const AnimationOptions& animation) {
341     impl->cameraMutated = true;
342     impl->transform.setZoom(zoom, anchor, animation);
343     impl->onUpdate();
344 }
345 
setZoom(double zoom,const EdgeInsets & padding,const AnimationOptions & animation)346 void Map::setZoom(double zoom, const EdgeInsets& padding, const AnimationOptions& animation) {
347     impl->cameraMutated = true;
348     impl->transform.setZoom(zoom, padding, animation);
349     impl->onUpdate();
350 }
351 
getZoom() const352 double Map::getZoom() const {
353     return impl->transform.getZoom();
354 }
355 
setLatLngZoom(const LatLng & latLng,double zoom,const AnimationOptions & animation)356 void Map::setLatLngZoom(const LatLng& latLng, double zoom, const AnimationOptions& animation) {
357     impl->cameraMutated = true;
358     setLatLngZoom(latLng, zoom, {}, animation);
359 }
360 
setLatLngZoom(const LatLng & latLng,double zoom,const EdgeInsets & padding,const AnimationOptions & animation)361 void Map::setLatLngZoom(const LatLng& latLng, double zoom, const EdgeInsets& padding, const AnimationOptions& animation) {
362     impl->cameraMutated = true;
363     impl->transform.setLatLngZoom(latLng, zoom, padding, animation);
364     impl->onUpdate();
365 }
366 
cameraForLatLngBounds(const LatLngBounds & bounds,const EdgeInsets & padding,optional<double> bearing,optional<double> pitch) const367 CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding, optional<double> bearing, optional<double> pitch) const {
368     return cameraForLatLngs({
369         bounds.northwest(),
370         bounds.southwest(),
371         bounds.southeast(),
372         bounds.northeast(),
373     }, padding, bearing, pitch);
374 }
375 
cameraForLatLngs(const std::vector<LatLng> & latLngs,const Transform & transform,const EdgeInsets & padding)376 CameraOptions cameraForLatLngs(const std::vector<LatLng>& latLngs, const Transform& transform, const EdgeInsets& padding) {
377     CameraOptions options;
378     if (latLngs.empty()) {
379         return options;
380     }
381     Size size = transform.getState().getSize();
382     // Calculate the bounds of the possibly rotated shape with respect to the viewport.
383     ScreenCoordinate nePixel = {-INFINITY, -INFINITY};
384     ScreenCoordinate swPixel = {INFINITY, INFINITY};
385     double viewportHeight = size.height;
386     for (LatLng latLng : latLngs) {
387         ScreenCoordinate pixel = transform.latLngToScreenCoordinate(latLng);
388         swPixel.x = std::min(swPixel.x, pixel.x);
389         nePixel.x = std::max(nePixel.x, pixel.x);
390         swPixel.y = std::min(swPixel.y, viewportHeight - pixel.y);
391         nePixel.y = std::max(nePixel.y, viewportHeight - pixel.y);
392     }
393     double width = nePixel.x - swPixel.x;
394     double height = nePixel.y - swPixel.y;
395 
396     // Calculate the zoom level.
397     double minScale = INFINITY;
398     if (width > 0 || height > 0) {
399         double scaleX = double(size.width) / width;
400         double scaleY = double(size.height) / height;
401         scaleX -= (padding.left() + padding.right()) / width;
402         scaleY -= (padding.top() + padding.bottom()) / height;
403         minScale = util::min(scaleX, scaleY);
404     }
405     double zoom = transform.getZoom() + ::log2(minScale);
406     zoom = util::clamp(zoom, transform.getState().getMinZoom(), transform.getState().getMaxZoom());
407 
408     // Calculate the center point of a virtual bounds that is extended in all directions by padding.
409     ScreenCoordinate centerPixel = nePixel + swPixel;
410     ScreenCoordinate paddedNEPixel = {
411         padding.right() / minScale,
412         padding.top() / minScale,
413     };
414     ScreenCoordinate paddedSWPixel = {
415         padding.left() / minScale,
416         padding.bottom() / minScale,
417     };
418     centerPixel = centerPixel + paddedNEPixel - paddedSWPixel;
419     centerPixel /= 2.0;
420 
421     // CameraOptions origin is at the top-left corner.
422     centerPixel.y = viewportHeight - centerPixel.y;
423 
424     options.center = transform.screenCoordinateToLatLng(centerPixel);
425     options.zoom = zoom;
426     return options;
427 }
428 
cameraForLatLngs(const std::vector<LatLng> & latLngs,const EdgeInsets & padding,optional<double> bearing,optional<double> pitch) const429 CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const EdgeInsets& padding, optional<double> bearing, optional<double> pitch) const {
430 
431     if (!bearing && !pitch) {
432         return mbgl::cameraForLatLngs(latLngs, impl->transform, padding);
433     }
434 
435     Transform transform(impl->transform.getState());
436 
437     if (bearing) {
438         double angle = -*bearing * util::DEG2RAD; // Convert to radians
439         transform.setAngle(angle);
440     }
441     if (pitch) {
442         double pitchAsRadian = *pitch * util::DEG2RAD; // Convert to radians
443         transform.setPitch(pitchAsRadian);
444     }
445 
446     CameraOptions options = mbgl::cameraForLatLngs(latLngs, transform, padding);
447     options.angle = transform.getAngle();
448     options.pitch = transform.getPitch();
449 
450     return options;
451 }
452 
cameraForGeometry(const Geometry<double> & geometry,const EdgeInsets & padding,optional<double> bearing,optional<double> pitch) const453 CameraOptions Map::cameraForGeometry(const Geometry<double>& geometry, const EdgeInsets& padding, optional<double> bearing, optional<double> pitch) const {
454 
455     std::vector<LatLng> latLngs;
456     forEachPoint(geometry, [&](const Point<double>& pt) {
457         latLngs.push_back({ pt.y, pt.x });
458     });
459     return cameraForLatLngs(latLngs, padding, bearing, pitch);
460 }
461 
latLngBoundsForCamera(const CameraOptions & camera) const462 LatLngBounds Map::latLngBoundsForCamera(const CameraOptions& camera) const {
463     Transform shallow { impl->transform.getState() };
464     Size size = shallow.getState().getSize();
465 
466     shallow.jumpTo(camera);
467     return LatLngBounds::hull(
468         shallow.screenCoordinateToLatLng({}),
469         shallow.screenCoordinateToLatLng({ double(size.width), double(size.height) })
470     );
471 }
472 
resetZoom()473 void Map::resetZoom() {
474     impl->cameraMutated = true;
475     setZoom(0);
476 }
477 
478 #pragma mark - Bounds
479 
getLatLngBounds() const480 optional<LatLngBounds> Map::getLatLngBounds() const {
481     return impl->transform.getState().getLatLngBounds();
482 }
483 
setLatLngBounds(optional<LatLngBounds> bounds)484 void Map::setLatLngBounds(optional<LatLngBounds> bounds) {
485     impl->cameraMutated = true;
486     impl->transform.setLatLngBounds(bounds);
487     impl->onUpdate();
488 }
489 
setMinZoom(const double minZoom)490 void Map::setMinZoom(const double minZoom) {
491     impl->transform.setMinZoom(minZoom);
492     if (getZoom() < minZoom) {
493         setZoom(minZoom);
494     }
495 }
496 
getMinZoom() const497 double Map::getMinZoom() const {
498     return impl->transform.getState().getMinZoom();
499 }
500 
setMaxZoom(const double maxZoom)501 void Map::setMaxZoom(const double maxZoom) {
502     impl->transform.setMaxZoom(maxZoom);
503     if (getZoom() > maxZoom) {
504         setZoom(maxZoom);
505     }
506 }
507 
getMaxZoom() const508 double Map::getMaxZoom() const {
509     return impl->transform.getState().getMaxZoom();
510 }
511 
setMinPitch(double minPitch)512 void Map::setMinPitch(double minPitch) {
513     impl->transform.setMinPitch(minPitch * util::DEG2RAD);
514     if (getPitch() < minPitch) {
515         setPitch(minPitch);
516     }
517 }
518 
getMinPitch() const519 double Map::getMinPitch() const {
520     return impl->transform.getState().getMinPitch() * util::RAD2DEG;
521 }
522 
setMaxPitch(double maxPitch)523 void Map::setMaxPitch(double maxPitch) {
524     impl->transform.setMaxPitch(maxPitch * util::DEG2RAD);
525     if (getPitch() > maxPitch) {
526         setPitch(maxPitch);
527     }
528 }
529 
getMaxPitch() const530 double Map::getMaxPitch() const {
531     return impl->transform.getState().getMaxPitch() * util::RAD2DEG;
532 }
533 
534 #pragma mark - Size
535 
setSize(const Size size)536 void Map::setSize(const Size size) {
537     impl->transform.resize(size);
538     impl->onUpdate();
539 }
540 
getSize() const541 Size Map::getSize() const {
542     return impl->transform.getState().getSize();
543 }
544 
545 #pragma mark - Rotation
546 
rotateBy(const ScreenCoordinate & first,const ScreenCoordinate & second,const AnimationOptions & animation)547 void Map::rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second, const AnimationOptions& animation) {
548     impl->cameraMutated = true;
549     impl->transform.rotateBy(first, second, animation);
550     impl->onUpdate();
551 }
552 
setBearing(double degrees,const AnimationOptions & animation)553 void Map::setBearing(double degrees, const AnimationOptions& animation) {
554     impl->cameraMutated = true;
555     setBearing(degrees, EdgeInsets(), animation);
556 }
557 
setBearing(double degrees,optional<ScreenCoordinate> anchor,const AnimationOptions & animation)558 void Map::setBearing(double degrees, optional<ScreenCoordinate> anchor, const AnimationOptions& animation) {
559     impl->cameraMutated = true;
560     impl->transform.setAngle(-degrees * util::DEG2RAD, anchor, animation);
561     impl->onUpdate();
562 }
563 
setBearing(double degrees,const EdgeInsets & padding,const AnimationOptions & animation)564 void Map::setBearing(double degrees, const EdgeInsets& padding, const AnimationOptions& animation) {
565     impl->cameraMutated = true;
566     impl->transform.setAngle(-degrees * util::DEG2RAD, padding, animation);
567     impl->onUpdate();
568 }
569 
getBearing() const570 double Map::getBearing() const {
571     return -impl->transform.getAngle() * util::RAD2DEG;
572 }
573 
resetNorth(const AnimationOptions & animation)574 void Map::resetNorth(const AnimationOptions& animation) {
575     impl->cameraMutated = true;
576     impl->transform.setAngle(0, animation);
577     impl->onUpdate();
578 }
579 
580 #pragma mark - Pitch
581 
setPitch(double pitch,const AnimationOptions & animation)582 void Map::setPitch(double pitch, const AnimationOptions& animation) {
583     impl->cameraMutated = true;
584     setPitch(pitch, {}, animation);
585 }
586 
setPitch(double pitch,optional<ScreenCoordinate> anchor,const AnimationOptions & animation)587 void Map::setPitch(double pitch, optional<ScreenCoordinate> anchor, const AnimationOptions& animation) {
588     impl->cameraMutated = true;
589     impl->transform.setPitch(pitch * util::DEG2RAD, anchor, animation);
590     impl->onUpdate();
591 }
592 
getPitch() const593 double Map::getPitch() const {
594     return impl->transform.getPitch() * util::RAD2DEG;
595 }
596 
597 #pragma mark - North Orientation
598 
setNorthOrientation(NorthOrientation orientation)599 void Map::setNorthOrientation(NorthOrientation orientation) {
600     impl->transform.setNorthOrientation(orientation);
601     impl->onUpdate();
602 }
603 
getNorthOrientation() const604 NorthOrientation Map::getNorthOrientation() const {
605     return impl->transform.getNorthOrientation();
606 }
607 
608 #pragma mark - Constrain mode
609 
setConstrainMode(mbgl::ConstrainMode mode)610 void Map::setConstrainMode(mbgl::ConstrainMode mode) {
611     impl->transform.setConstrainMode(mode);
612     impl->onUpdate();
613 }
614 
getConstrainMode() const615 ConstrainMode Map::getConstrainMode() const {
616     return impl->transform.getConstrainMode();
617 }
618 
619 #pragma mark - Viewport mode
620 
setViewportMode(mbgl::ViewportMode mode)621 void Map::setViewportMode(mbgl::ViewportMode mode) {
622     impl->transform.setViewportMode(mode);
623     impl->onUpdate();
624 }
625 
getViewportMode() const626 ViewportMode Map::getViewportMode() const {
627     return impl->transform.getViewportMode();
628 }
629 
630 #pragma mark - Projection mode
631 
setAxonometric(bool axonometric)632 void Map::setAxonometric(bool axonometric) {
633     impl->transform.setAxonometric(axonometric);
634     impl->onUpdate();
635 }
636 
getAxonometric() const637 bool Map::getAxonometric() const {
638     return impl->transform.getAxonometric();
639 }
640 
setXSkew(double xSkew)641 void Map::setXSkew(double xSkew) {
642     impl->transform.setXSkew(xSkew);
643     impl->onUpdate();
644 }
645 
getXSkew() const646 double Map::getXSkew() const {
647     return impl->transform.getXSkew();
648 }
649 
setYSkew(double ySkew)650 void Map::setYSkew(double ySkew) {
651     impl->transform.setYSkew(ySkew);
652     impl->onUpdate();
653 }
654 
getYSkew() const655 double Map::getYSkew() const {
656     return impl->transform.getYSkew();
657 }
658 
659 #pragma mark - Projection
660 
pixelForLatLng(const LatLng & latLng) const661 ScreenCoordinate Map::pixelForLatLng(const LatLng& latLng) const {
662     // If the center and point longitudes are not in the same side of the
663     // antimeridian, we unwrap the point longitude so it would be seen if
664     // e.g. the next antimeridian side is visible.
665     LatLng unwrappedLatLng = latLng.wrapped();
666     unwrappedLatLng.unwrapForShortestPath(getLatLng());
667     return impl->transform.latLngToScreenCoordinate(unwrappedLatLng);
668 }
669 
latLngForPixel(const ScreenCoordinate & pixel) const670 LatLng Map::latLngForPixel(const ScreenCoordinate& pixel) const {
671     return impl->transform.screenCoordinateToLatLng(pixel);
672 }
673 
674 #pragma mark - Annotations
675 
addAnnotationImage(std::unique_ptr<style::Image> image)676 void Map::addAnnotationImage(std::unique_ptr<style::Image> image) {
677     impl->annotationManager.addImage(std::move(image));
678 }
679 
removeAnnotationImage(const std::string & id)680 void Map::removeAnnotationImage(const std::string& id) {
681     impl->annotationManager.removeImage(id);
682 }
683 
getTopOffsetPixelsForAnnotationImage(const std::string & id)684 double Map::getTopOffsetPixelsForAnnotationImage(const std::string& id) {
685     return impl->annotationManager.getTopOffsetPixelsForImage(id);
686 }
687 
addAnnotation(const Annotation & annotation)688 AnnotationID Map::addAnnotation(const Annotation& annotation) {
689     auto result = impl->annotationManager.addAnnotation(annotation);
690     impl->onUpdate();
691     return result;
692 }
693 
updateAnnotation(AnnotationID id,const Annotation & annotation)694 void Map::updateAnnotation(AnnotationID id, const Annotation& annotation) {
695     if (impl->annotationManager.updateAnnotation(id, annotation)) {
696         impl->onUpdate();
697     }
698 }
699 
removeAnnotation(AnnotationID annotation)700 void Map::removeAnnotation(AnnotationID annotation) {
701     impl->annotationManager.removeAnnotation(annotation);
702     impl->onUpdate();
703 }
704 
705 #pragma mark - Toggles
706 
setDebug(MapDebugOptions debugOptions)707 void Map::setDebug(MapDebugOptions debugOptions) {
708     impl->debugOptions = debugOptions;
709     impl->onUpdate();
710 }
711 
cycleDebugOptions()712 void Map::cycleDebugOptions() {
713 #if not MBGL_USE_GLES2
714     if (impl->debugOptions & MapDebugOptions::StencilClip)
715         impl->debugOptions = MapDebugOptions::NoDebug;
716     else if (impl->debugOptions & MapDebugOptions::Overdraw)
717         impl->debugOptions = MapDebugOptions::StencilClip;
718 #else
719     if (impl->debugOptions & MapDebugOptions::Overdraw)
720         impl->debugOptions = MapDebugOptions::NoDebug;
721 #endif // MBGL_USE_GLES2
722     else if (impl->debugOptions & MapDebugOptions::Collision)
723         impl->debugOptions = MapDebugOptions::Overdraw;
724     else if (impl->debugOptions & MapDebugOptions::Timestamps)
725         impl->debugOptions = impl->debugOptions | MapDebugOptions::Collision;
726     else if (impl->debugOptions & MapDebugOptions::ParseStatus)
727         impl->debugOptions = impl->debugOptions | MapDebugOptions::Timestamps;
728     else if (impl->debugOptions & MapDebugOptions::TileBorders)
729         impl->debugOptions = impl->debugOptions | MapDebugOptions::ParseStatus;
730     else
731         impl->debugOptions = MapDebugOptions::TileBorders;
732 
733     impl->onUpdate();
734 }
735 
getDebug() const736 MapDebugOptions Map::getDebug() const {
737     return impl->debugOptions;
738 }
739 
setPrefetchZoomDelta(uint8_t delta)740 void Map::setPrefetchZoomDelta(uint8_t delta) {
741     impl->prefetchZoomDelta = delta;
742 }
743 
getPrefetchZoomDelta() const744 uint8_t Map::getPrefetchZoomDelta() const {
745     return impl->prefetchZoomDelta;
746 }
747 
isFullyLoaded() const748 bool Map::isFullyLoaded() const {
749     return impl->style->impl->isLoaded() && impl->rendererFullyLoaded;
750 }
751 
onSourceChanged(style::Source & source)752 void Map::Impl::onSourceChanged(style::Source& source) {
753     observer.onSourceChanged(source);
754 }
755 
onInvalidate()756 void Map::Impl::onInvalidate() {
757     onUpdate();
758 }
759 
onUpdate()760 void Map::Impl::onUpdate() {
761     // Don't load/render anything in still mode until explicitly requested.
762     if (mode != MapMode::Continuous && !stillImageRequest) {
763         return;
764     }
765 
766     TimePoint timePoint = mode == MapMode::Continuous ? Clock::now() : Clock::time_point::max();
767 
768     transform.updateTransitions(timePoint);
769 
770     UpdateParameters params = {
771         style->impl->isLoaded(),
772         mode,
773         pixelRatio,
774         debugOptions,
775         timePoint,
776         transform.getState(),
777         style->impl->getGlyphURL(),
778         style->impl->spriteLoaded,
779         style->impl->getTransitionOptions(),
780         style->impl->getLight()->impl,
781         style->impl->getImageImpls(),
782         style->impl->getSourceImpls(),
783         style->impl->getLayerImpls(),
784         annotationManager,
785         prefetchZoomDelta,
786         bool(stillImageRequest)
787     };
788 
789     rendererFrontend.update(std::make_shared<UpdateParameters>(std::move(params)));
790 }
791 
onStyleLoading()792 void Map::Impl::onStyleLoading() {
793     loading = true;
794     rendererFullyLoaded = false;
795     observer.onWillStartLoadingMap();
796 }
797 
onStyleLoaded()798 void Map::Impl::onStyleLoaded() {
799     if (!cameraMutated) {
800         map.jumpTo(style->getDefaultCamera());
801     }
802 
803     annotationManager.onStyleLoaded();
804     observer.onDidFinishLoadingStyle();
805 }
806 
onStyleError(std::exception_ptr error)807 void Map::Impl::onStyleError(std::exception_ptr error) {
808     observer.onDidFailLoadingMap(error);
809 }
810 
onResourceError(std::exception_ptr error)811 void Map::Impl::onResourceError(std::exception_ptr error) {
812     if (mode != MapMode::Continuous && stillImageRequest) {
813         auto request = std::move(stillImageRequest);
814         request->callback(error);
815     }
816 }
817 
dumpDebugLogs() const818 void Map::dumpDebugLogs() const {
819     Log::Info(Event::General, "--------------------------------------------------------------------------------");
820     impl->style->impl->dumpDebugLogs();
821     Log::Info(Event::General, "--------------------------------------------------------------------------------");
822 }
823 
824 } // namespace mbgl
825