summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsheem Mamoowala <asheem.mamoowala@mapbox.com>2017-05-25 14:36:05 -0700
committerAsheem Mamoowala <asheem.mamoowala@mapbox.com>2017-06-19 09:50:08 -0700
commitab5b310a9eb7c88935cc457da1af81349fbe8d41 (patch)
treee1485c8aa2f00e2b50daa0aa7f997ddda59c2562
parent7b05606464ac4d57b59b64015629e9578cbebac2 (diff)
downloadqtlocation-mapboxgl-ab5b310a9eb7c88935cc457da1af81349fbe8d41.tar.gz
[iOS][macOS] Add ImageSource bindings
-rw-r--r--platform/android/src/style/sources/image_source.cpp81
-rw-r--r--platform/android/src/style/sources/image_source.hpp33
-rw-r--r--platform/darwin/src/MGLGeometry.h17
-rw-r--r--platform/darwin/src/MGLGeometry_Private.h22
-rw-r--r--platform/darwin/src/MGLImageSource.h135
-rw-r--r--platform/darwin/src/MGLImageSource.mm105
-rw-r--r--platform/darwin/src/MGLImageSource_Private.h9
-rw-r--r--platform/darwin/src/MGLOfflineStorage.h2
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm3
-rw-r--r--platform/darwin/src/MGLStyle.mm4
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.h14
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.m10
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift14
-rw-r--r--platform/darwin/test/MGLGeometryTests.mm19
-rw-r--r--platform/darwin/test/MGLImageSourceTests.m42
-rw-r--r--platform/darwin/test/MGLStyleTests.mm18
-rw-r--r--platform/darwin/test/Media.xcassets/RadarImage.imageset/Contents.json21
-rw-r--r--platform/darwin/test/Media.xcassets/RadarImage.imageset/radar.pngbin0 -> 44094 bytes
-rw-r--r--platform/ios/app/MBXViewController.m20
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj25
-rw-r--r--platform/ios/src/Mapbox.h1
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.h2
-rw-r--r--platform/ios/src/UIImage+MGLAdditions.mm5
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/Contents.json6
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/Contents.json21
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/southeast_radar_0.pngbin0 -> 172489 bytes
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/Contents.json21
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/southeast_radar_1.pngbin0 -> 177163 bytes
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/Contents.json21
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/southeast_radar_2.pngbin0 -> 179236 bytes
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/Contents.json21
-rw-r--r--platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/southeast_radar_3.pngbin0 -> 177074 bytes
-rw-r--r--platform/macos/app/Base.lproj/MainMenu.xib6
-rw-r--r--platform/macos/app/MapDocument.m78
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj14
-rw-r--r--platform/macos/src/Mapbox.h1
-rw-r--r--platform/macos/src/NSImage+MGLAdditions.h2
-rw-r--r--platform/macos/src/NSImage+MGLAdditions.mm15
-rw-r--r--src/mbgl/renderer/buckets/raster_bucket.cpp6
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp13
40 files changed, 788 insertions, 39 deletions
diff --git a/platform/android/src/style/sources/image_source.cpp b/platform/android/src/style/sources/image_source.cpp
new file mode 100644
index 0000000000..9909675f44
--- /dev/null
+++ b/platform/android/src/style/sources/image_source.cpp
@@ -0,0 +1,81 @@
+#include "image_source.hpp"
+
+// Java -> C++ conversion
+#include "../android_conversion.hpp"
+
+// C++ -> Java conversion
+#include "../../conversion/conversion.hpp"
+#include <mbgl/style/conversion.hpp>
+
+#include <string>
+
+namespace mbgl {
+namespace android {
+
+ ImageSource::ImageSource(jni::JNIEnv& env, jni::String sourceId)
+ : Source(env, std::make_unique<mbgl::style::ImageSource>(
+ jni::Make<std::string>(env, sourceId)
+ )
+ ) {
+ }
+
+ ImageSource::ImageSource(mbgl::Map& map, mbgl::style::ImageSource& coreSource)
+ : Source(map, coreSource) {
+ }
+
+ ImageSource::~ImageSource() = default;
+
+ void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, jni::String json) {
+ using namespace mbgl::style::conversion;
+
+ // Convert the jni object
+ Error error;
+ optional<GeoJSON> converted = convert<GeoJSON>(Value(env, json), error);
+ if(!converted) {
+ mbgl::Log::Error(mbgl::Event::JNI, "Error setting geo json: " + error.message);
+ return;
+ }
+
+ // Update the core source
+ source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(*converted);
+ }
+
+ void ImageSource::setURL(jni::JNIEnv& env, jni::String url) {
+ // Update the core source
+ source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setURL(jni::Make<std::string>(env, url));
+ }
+
+ jni::String ImageSource::getURL(jni::JNIEnv& env) {
+ std::string url = source.as<mbgl::style::ImageSource>()->ImageSource::getURL();
+ return !url.empty() ? jni::Make<jni::String>(env, url) : jni::String();
+ }
+
+
+ jni::Class<ImageSource> ImageSource::javaClass;
+
+ jni::jobject* ImageSource::createJavaPeer(jni::JNIEnv& env) {
+ static auto constructor = ImageSource::javaClass.template GetConstructor<jni::jlong>(env);
+ return ImageSource::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
+ }
+
+ void ImageSource::registerNative(jni::JNIEnv& env) {
+ // Lookup the class
+ ImageSource::javaClass = *jni::Class<ImageSource>::Find(env).NewGlobalRef(env).release();
+
+ #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
+
+ // Register the peer
+ jni::RegisterNativePeer<ImageSource>(
+ env, ImageSource::javaClass, "nativePtr",
+ std::make_unique<ImageSource, JNIEnv&, jni::String, jni::Object<>>,
+ "initialize",
+ "finalize",
+ METHOD(&ImageSource::setGeoJSONString, "nativeSetGeoJsonString"),
+ METHOD(&ImageSource::setURL, "nativeSetUrl"),
+ METHOD(&ImageSource::getURL, "nativeGetUrl"),
+ METHOD(&ImageSource::getURL, "nativeGetUrl"),
+ );
+ }
+
+} // namespace android
+} // namespace mbgl
diff --git a/platform/android/src/style/sources/image_source.hpp b/platform/android/src/style/sources/image_source.hpp
new file mode 100644
index 0000000000..d5802ed5a1
--- /dev/null
+++ b/platform/android/src/style/sources/image_source.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "source.hpp"
+#include <mbgl/style/sources/image_source.hpp>
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+
+class ImageSource : public Source {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/sources/ImageSource"; };
+
+ static jni::Class<ImageSource> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+ ImageSource(jni::JNIEnv&, jni::String, jni::Object<>);
+
+ ImageSource(mbgl::Map&, mbgl::style::ImageSource&);
+
+ ~ImageSource();
+
+ void setURL(jni::JNIEnv&, jni::String);
+ jni::String getURL(jni::JNIEnv&);
+
+ jni::jobject* createJavaPeer(jni::JNIEnv&);
+
+}; // class ImageSource
+
+} // namespace android
+} // namespace mbgl
diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h
index 9fcb9dd37c..003a7638e7 100644
--- a/platform/darwin/src/MGLGeometry.h
+++ b/platform/darwin/src/MGLGeometry.h
@@ -45,6 +45,23 @@ typedef struct MGLCoordinateBounds {
CLLocationCoordinate2D ne;
} MGLCoordinateBounds;
+/**
+ A quadrilateral area as measured on a two-dimensional map projection.
+ `MGLCoordinateQuad` differs from `MGLCoordinateBounds` in that it allows
+ representation of non-axis aligned bounds and non-rectangular quadrilaterals
+ */
+typedef struct MGLCoordinateQuad {
+ /** Coordinate at the top left corner. */
+ CLLocationCoordinate2D topLeft;
+ /** Coordinate at the top right corner. */
+ CLLocationCoordinate2D topRight;
+ /** Coordinate at the bottom right corner. */
+ CLLocationCoordinate2D bottomRight;
+ /** Coordinate at the bottom left corner. */
+ CLLocationCoordinate2D bottomLeft;
+} MGLCoordinateQuad;
+
+
/**
Creates a new `MGLCoordinateBounds` structure from the given southwest and
northeast coordinates.
diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h
index 7ad8314a79..bdc838667a 100644
--- a/platform/darwin/src/MGLGeometry_Private.h
+++ b/platform/darwin/src/MGLGeometry_Private.h
@@ -8,6 +8,7 @@
#import <mbgl/util/geo.hpp>
#import <mbgl/util/geometry.hpp>
+#import <array>
typedef double MGLLocationRadians;
typedef double MGLRadianDistance;
typedef double MGLRadianDirection;
@@ -56,6 +57,27 @@ NS_INLINE mbgl::LatLngBounds MGLLatLngBoundsFromCoordinateBounds(MGLCoordinateBo
MGLLatLngFromLocationCoordinate2D(coordinateBounds.ne));
}
+NS_INLINE std::array<mbgl::LatLng, 4> MGLLatLngArrayFromCoordinateQuad(MGLCoordinateQuad quad) {
+ return { MGLLatLngFromLocationCoordinate2D(quad.topLeft),
+ MGLLatLngFromLocationCoordinate2D(quad.topRight),
+ MGLLatLngFromLocationCoordinate2D(quad.bottomRight),
+ MGLLatLngFromLocationCoordinate2D(quad.bottomLeft) };
+}
+
+NS_INLINE MGLCoordinateQuad MGLCoordinateQuadFromLatLngArray(std::array<mbgl::LatLng, 4> quad) {
+ return { MGLLocationCoordinate2DFromLatLng(quad[0]),
+ MGLLocationCoordinate2DFromLatLng(quad[1]),
+ MGLLocationCoordinate2DFromLatLng(quad[2]),
+ MGLLocationCoordinate2DFromLatLng(quad[3]) };
+}
+
+NS_INLINE MGLCoordinateQuad MGLCoordinateQuadFromCoordinateBounds(MGLCoordinateBounds bounds) {
+ return { { bounds.ne.latitude, bounds.sw.longitude },
+ bounds.ne,
+ { bounds.sw.latitude, bounds.ne.longitude },
+ bounds.sw };
+}
+
#if TARGET_OS_IPHONE
NS_INLINE mbgl::EdgeInsets MGLEdgeInsetsFromNSEdgeInsets(UIEdgeInsets insets) {
return { insets.top, insets.left, insets.bottom, insets.right };
diff --git a/platform/darwin/src/MGLImageSource.h b/platform/darwin/src/MGLImageSource.h
new file mode 100644
index 0000000000..9ef2c6719a
--- /dev/null
+++ b/platform/darwin/src/MGLImageSource.h
@@ -0,0 +1,135 @@
+#import "MGLSource.h"
+
+#import "MGLFoundation.h"
+#import "MGLTypes.h"
+#import "MGLGeometry.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+MGL_EXPORT
+/**
+ `MGLImageSource` is a map content source that supplies a georeferenced raster
+ image to be shown on the map. The geographic location of the raster image content,
+ supplied with `MGLCoordinateQuad`, can be non-axis aligned.
+ `MGLImageSource` supports raster content from `NSURL` or an `MGLImage`.
+ Supported image formats are : PNG, TIFF, JPEG, GIF (single frame rendering),
+ and BMP.
+ An image source is added to an `MGLStyle` object along with one or more
+ `MGLRasterStyleLayer` objects. Use a raster style layer to control the
+ appearance of content supplied by the image source.
+
+ Each
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-image"><code>image</code></a>
+ source defined by the style JSON file is represented at runtime by an
+ `MGLImageSource` object that you can use to initialize new style layers. You
+ can also add and remove sources dynamically using methods such as
+ `-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`.
+
+ ### Example
+
+ ```swift
+ let coordinates: MGLCoordinateQuad = MGLCoordinateQuad(
+ topLeft: CLLocationCoordinate2D(latitude: 46.437, longitude: -80.425),
+ topRight: CLLocationCoordinate2D(latitude: 46.437, longitude: -71.516),
+ bottomRight: CLLocationCoordinate2D(latitude: 37.936, longitude: -71.516),
+ bottomLeft: CLLocationCoordinate2D(latitude: 37.936, longitude: -80.425))
+ let source = MGLImageSource(identifier: "images", coordinates: coordinates, imageURL: URL(string: "https://www.mapbox.com/mapbox-gl-js/assets/radar.gif")!)
+ mapView.style?.addSource(source)
+ ```
+ */
+@interface MGLImageSource : MGLSource
+
+#pragma mark Initializing a Source
+
+/**
+ Returns a georeferenced image source with an identifier and coordinates
+
+ @param identifier A string that uniquely identifies the source.
+ @param coordinateQuad The top left, top right, bottom right, and bottom left coordinates for the image.
+ @return An initialized image source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier coordinates:(MGLCoordinateQuad)coordinateQuad NS_DESIGNATED_INITIALIZER;
+
+/**
+ Returns a georeferenced image source with an identifier, coordinates and a URL
+
+ @param identifier A string that uniquely identifies the source.
+ @param coordinateQuad the top left, top right, bottom right, and bottom left coordinates for the image.
+ @param url An HTTP(S) URL, absolute file URL, or local file URL relative to the
+ current application’s resource bundle.
+ @return An initialized shape source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier coordinates:(MGLCoordinateQuad)coordinateQuad imageURL:(NSURL *)url;
+
+/**
+ Returns a georeferenced image source with an identifier, coordinates and an image
+
+ @param identifier A string that uniquely identifies the source.
+ @param coordinateQuad The top left, top right, bottom right, and bottom left coordinates for the image.
+ @param image The image to display for the sourcde.
+ @return An initialized shape source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier coordinates:(MGLCoordinateQuad)coordinateQuad image:(MGLImage *)image;
+
+/**
+ Returns a georeferenced image source with an identifier and coordinates
+
+ @param identifier A string that uniquely identifies the source.
+ @param bounds The aligned coordinate bounds for the image.
+ @return An initialized image source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier bounds:(MGLCoordinateBounds)bounds;
+
+/**
+ Returns a georeferenced image source with an identifier, coordinates and a URL
+
+ @param identifier A string that uniquely identifies the source.
+ @param bounds The aligned coordinate bounds for the image.@param url An HTTP(S) URL, absolute file URL, or local file URL relative to the
+ current application’s resource bundle.
+ @return An initialized shape source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier bounds:(MGLCoordinateBounds)bounds imageURL:(NSURL *)url;
+
+/**
+ Returns a georeferenced image source with an identifier, coordinates and an image
+
+ @param identifier A string that uniquely identifies the source.
+ @param bounds The aligned coordinate bounds for the image.
+ @param image The image to display for the sourcde.
+ @return An initialized shape source.
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier bounds:(MGLCoordinateBounds)bounds image:(MGLImage *)image;
+
+#pragma mark Accessing a Source’s Content
+
+/**
+ The URL to the source image.
+
+ If the receiver was initialized using `-initWithIdentifier:coordinates:` or
+ `-initWithIdentifier:coordinates:image:`, or the `image` property is set,
+ this property is set to `nil`.
+ */
+@property (nonatomic, copy, nullable)NSURL *URL;
+
+/**
+ The source image.
+
+ If the receiver was initialized using `-initWithIdentifier:coordinates:` or
+ `-initWithIdentifier:coordinates:imageURL:`, or if the `URL` property is set,
+ this property is set to `nil`.
+
+
+ */
+@property (nonatomic, retain, nullable)MGLImage *image;
+
+/**
+ The coordinates at which the source image will be placed.
+
+ If the receiver was initialized using `-initWithIdentifier:bounds:`,
+ `-initWithIdentifier:bounds:image:`, or `initWithIdentifier:bounds:imageURL`,
+ the bounds will be converted to an `MGLCoordinateQuad`.
+ */
+@property (nonatomic) MGLCoordinateQuad coordinates;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLImageSource.mm b/platform/darwin/src/MGLImageSource.mm
new file mode 100644
index 0000000000..9872a65aff
--- /dev/null
+++ b/platform/darwin/src/MGLImageSource.mm
@@ -0,0 +1,105 @@
+#import "MGLImageSource_Private.h"
+
+#import "MGLGeometry_Private.h"
+#import "MGLSource_Private.h"
+#import "MGLTileSource_Private.h"
+#import "NSURL+MGLAdditions.h"
+#if TARGET_OS_IPHONE
+ #import "UIImage+MGLAdditions.h"
+#else
+ #import "NSImage+MGLAdditions.h"
+#endif
+
+#include <mbgl/style/sources/image_source.hpp>
+#include <mbgl/util/premultiply.hpp>
+
+@interface MGLImageSource ()
+
+@property (nonatomic, readonly) mbgl::style::ImageSource *rawSource;
+
+@end
+
+@implementation MGLImageSource
+
+- (instancetype)initWithIdentifier:(NSString *)identifier coordinates:(MGLCoordinateQuad)coordinateQuad {
+
+ const auto coordsArray = MGLLatLngArrayFromCoordinateQuad(coordinateQuad);
+ auto source = std::make_unique<mbgl::style::ImageSource>(identifier.UTF8String, coordsArray);
+ return self = [super initWithPendingSource:std::move(source)];
+}
+
+
+- (instancetype)initWithIdentifier:(NSString *)identifier coordinates:(MGLCoordinateQuad)coordinateQuad imageURL:(NSURL *)url {
+ self = [self initWithIdentifier:identifier coordinates: coordinateQuad];
+ self.URL = url;
+ return self;
+}
+
+
+- (instancetype)initWithIdentifier:(NSString *)identifier coordinates:(MGLCoordinateQuad)coordinateQuad image:(MGLImage *)image {
+ self = [self initWithIdentifier:identifier coordinates: coordinateQuad];
+ self.image = image;
+
+ return self;
+}
+
+- (instancetype)initWithIdentifier:(NSString *)identifier bounds:(MGLCoordinateBounds)bounds {
+ self = [self initWithIdentifier:identifier coordinates:MGLCoordinateQuadFromCoordinateBounds(bounds)];
+ return self;
+}
+
+- (instancetype)initWithIdentifier:(NSString *)identifier bounds:(MGLCoordinateBounds)bounds imageURL:(NSURL *)url {
+ self = [self initWithIdentifier:identifier coordinates:MGLCoordinateQuadFromCoordinateBounds(bounds) imageURL:url];
+ return self;
+}
+
+- (instancetype)initWithIdentifier:(NSString *)identifier bounds:(MGLCoordinateBounds)bounds image:(MGLImage *)image {
+ self = [self initWithIdentifier:identifier coordinates:MGLCoordinateQuadFromCoordinateBounds(bounds) image:image];
+ return self;
+}
+
+- (NSURL *)URL {
+ auto url = self.rawSource->getURL();
+ return url ? [NSURL URLWithString:@(url->c_str())] : nil;
+}
+
+- (void)setURL:(NSURL *)url {
+ if (url) {
+ self.rawSource->setURL(url.mgl_URLByStandardizingScheme.absoluteString.UTF8String);
+ _image = nil;
+ } else {
+ self.image = nullptr;
+ }
+}
+
+- (void)setImage:(MGLImage *)image {
+ if (image != nullptr) {
+ mbgl::UnassociatedImage unassociatedImage = mbgl::util::unpremultiply(image.mgl_PremultipliedImage);
+ self.rawSource->setImage(std::move(unassociatedImage));
+ }
+ _image = image;
+}
+
+- (MGLCoordinateQuad)coordinates {
+ return MGLCoordinateQuadFromLatLngArray(self.rawSource->getCoordinates());
+}
+
+- (void)setCoordinates: (MGLCoordinateQuad)coordinateQuad {
+ self.rawSource->setCoordinates(MGLLatLngArrayFromCoordinateQuad(coordinateQuad));
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; image = %@>",
+ NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.image];
+}
+
+- (mbgl::style::ImageSource *)rawSource {
+ return (mbgl::style::ImageSource *)super.rawSource;
+}
+
+- (NSString *)attributionHTMLString {
+ auto attribution = self.rawSource->getAttribution();
+ return attribution ? @(attribution->c_str()) : nil;
+}
+
+@end
diff --git a/platform/darwin/src/MGLImageSource_Private.h b/platform/darwin/src/MGLImageSource_Private.h
new file mode 100644
index 0000000000..54f6e00afa
--- /dev/null
+++ b/platform/darwin/src/MGLImageSource_Private.h
@@ -0,0 +1,9 @@
+#import "MGLImageSource.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MGLImageSource (Private)
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h
index 16f134adb1..90ba15c84c 100644
--- a/platform/darwin/src/MGLOfflineStorage.h
+++ b/platform/darwin/src/MGLOfflineStorage.h
@@ -154,6 +154,8 @@ typedef NS_ENUM(NSUInteger, MGLResourceKind) {
/** JSON part of a sprite sheet. It is constructed of the prefix in
https://www.mapbox.com/mapbox-gl-js/style-spec/#root-sprite and a JSON file extension. */
MGLResourceKindSpriteJSON,
+ /** Image **/
+ MGLResourceKindImage,
};
/**
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index 81774ad3cb..040b36f8be 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -99,6 +99,9 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoK
case mbgl::Resource::Kind::SpriteJSON:
kind = MGLResourceKindSpriteJSON;
break;
+ case mbgl::Resource::Kind::Image:
+ kind = MGLResourceKindImage;
+ break;
case mbgl::Resource::Kind::Unknown:
kind = MGLResourceKindUnknown;
break;
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index 2e6f2bc29a..592ab86780 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -23,6 +23,7 @@
#import "MGLVectorSource.h"
#import "MGLRasterSource.h"
#import "MGLShapeSource.h"
+#import "MGLImageSource.h"
#import "MGLAttributionInfo_Private.h"
@@ -41,6 +42,7 @@
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/style/sources/raster_source.hpp>
+#include <mbgl/style/sources/image_source.hpp>
#if TARGET_OS_IPHONE
#import "UIImage+MGLAdditions.h"
@@ -178,6 +180,8 @@ static NSURL *MGLStyleURL_emerald;
return [[MGLShapeSource alloc] initWithRawSource:geoJSONSource];
} else if (auto rasterSource = rawSource->as<mbgl::style::RasterSource>()) {
return [[MGLRasterSource alloc] initWithRawSource:rasterSource];
+ } else if (auto imageSource = rawSource->as<mbgl::style::ImageSource>()) {
+ return [[MGLImageSource alloc] initWithRawSource:imageSource];
} else {
return [[MGLSource alloc] initWithRawSource:rawSource];
}
diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h
index 0aaa2a337a..f3026a389f 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.h
+++ b/platform/darwin/src/NSValue+MGLAdditions.h
@@ -56,6 +56,20 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (readonly) MGLCoordinateBounds MGLCoordinateBoundsValue;
+/**
+ Creates a new value object containing the specified Mapbox coordinate
+ quad structure.
+
+ @param quad The value for the new object.
+ @return A new value object that contains the coordinate quad information.
+ */
++ (instancetype)valueWithMGLCoordinateQuad:(MGLCoordinateQuad)quad;
+
+/**
+ The Mapbox coordinate quad structure representation of the value.
+ */
+- (MGLCoordinateQuad)MGLCoordinateQuadValue;
+
#pragma mark Working with Offline Map Values
/**
diff --git a/platform/darwin/src/NSValue+MGLAdditions.m b/platform/darwin/src/NSValue+MGLAdditions.m
index ef894f0eb4..1383056944 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.m
+++ b/platform/darwin/src/NSValue+MGLAdditions.m
@@ -34,6 +34,16 @@
return bounds;
}
++ (instancetype)valueWithMGLCoordinateQuad:(MGLCoordinateQuad)quad {
+ return [self valueWithBytes:&quad objCType:@encode(MGLCoordinateQuad)];
+}
+
+- (MGLCoordinateQuad)MGLCoordinateQuadValue {
+ MGLCoordinateQuad quad;
+ [self getValue:&quad];
+ return quad;
+}
+
#pragma mark Offline maps
+ (NSValue *)valueWithMGLOfflinePackProgress:(MGLOfflinePackProgress)progress {
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index 48e6b17f44..2a441d2774 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -104,6 +104,20 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
XCTAssertNotNil(mapView.style?.source(withIdentifier: "pois"))
}
+ func testMGLImageSource() {
+ //#-example-code
+ let coordinates: MGLCoordinateQuad = MGLCoordinateQuad(
+ topLeft: CLLocationCoordinate2D(latitude: 46.437, longitude: -80.425),
+ topRight: CLLocationCoordinate2D(latitude: 46.437, longitude: -71.516),
+ bottomRight: CLLocationCoordinate2D(latitude: 37.936, longitude: -71.516),
+ bottomLeft: CLLocationCoordinate2D(latitude: 37.936, longitude: -80.425))
+ let source = MGLImageSource(identifier: "images", coordinates: coordinates, imageURL: URL(string: "https://www.mapbox.com/mapbox-gl-js/assets/radar.gif")!)
+ mapView.style?.addSource(source)
+ //#-end-example-code
+
+ XCTAssertNotNil(mapView.style?.source(withIdentifier: "images"))
+ }
+
func testMGLCircleStyleLayer() {
let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(population)
diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm
index 220a837643..1c85470188 100644
--- a/platform/darwin/test/MGLGeometryTests.mm
+++ b/platform/darwin/test/MGLGeometryTests.mm
@@ -144,4 +144,23 @@
XCTAssertEqualObjects(serializedGeoJSON, geoJSON, @"MGLPointFeature should serialize as a GeoJSON point feature.");
}
+- (void)testMGLCoordinateBoundsToMGLCoordinateQuad {
+ MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(CLLocationCoordinate2DMake(37.936, -80.425),
+ CLLocationCoordinate2DMake(46.437, -71.516));
+
+ MGLCoordinateQuad quad = MGLCoordinateQuadFromCoordinateBounds(bounds);
+ XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:bounds.sw],
+ [NSValue valueWithMGLCoordinate:quad.bottomLeft],
+ @"Bounds southwest should be bottom left of quad.");
+ XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:bounds.ne],
+ [NSValue valueWithMGLCoordinate:quad.topRight],
+ @"Bounds northeast should be top right of quad.");
+
+ XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(46.437, -80.425)],
+ [NSValue valueWithMGLCoordinate:quad.topLeft],
+ @"Quad top left should be computed correctly.");
+ XCTAssertEqualObjects([NSValue valueWithMGLCoordinate:CLLocationCoordinate2DMake(37.936, -71.516)],
+ [NSValue valueWithMGLCoordinate:quad.bottomRight],
+ @"Quad bottom right should be computed correctly.");
+}
@end
diff --git a/platform/darwin/test/MGLImageSourceTests.m b/platform/darwin/test/MGLImageSourceTests.m
new file mode 100644
index 0000000000..3349a7463b
--- /dev/null
+++ b/platform/darwin/test/MGLImageSourceTests.m
@@ -0,0 +1,42 @@
+#import <XCTest/XCTest.h>
+
+#import <Mapbox/Mapbox.h>
+
+@interface MGLImageSourceTests : XCTestCase
+
+@end
+
+@implementation MGLImageSourceTests
+
+
+- (void)testMGLImageSourceWithImageURL {
+
+ MGLCoordinateQuad quad = { { 80, 37}, { 81, 37}, { 81, 39}, { 80, 39}};
+ MGLImageSource *source = [[MGLImageSource alloc] initWithIdentifier:@"source-id" coordinates:quad imageURL: [NSURL URLWithString:@"http://host/image.png"]];
+
+ XCTAssertNotNil(source.URL);
+ XCTAssertEqualObjects(source.URL.absoluteString, @"http://host/image.png");
+ XCTAssertNil(source.image);
+}
+
+- (void)testMGLImageSourceWithImage {
+
+ NSString *imageName = @"RadarImage";
+#if TARGET_OS_IPHONE
+ MGLImage *image = [MGLImage imageNamed:imageName
+ inBundle:[NSBundle bundleForClass:[self class]]
+ compatibleWithTraitCollection:nil];
+#else
+ MGLImage *image = [[NSBundle bundleForClass:[self class]] imageForResource:imageName];
+#endif
+ XCTAssertNotNil(image);
+
+ MGLCoordinateQuad quad = { { 80, 37}, { 81, 37}, { 81, 39}, { 80, 39}};
+ MGLImageSource *source = [[MGLImageSource alloc] initWithIdentifier:@"source-id" coordinates:quad image:image];
+
+ XCTAssertNotNil(source.image);
+ XCTAssertEqualObjects(source.image, image);
+ XCTAssertNil(source.URL);
+}
+
+@end
diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm
index d93483ea6e..7f82dddfac 100644
--- a/platform/darwin/test/MGLStyleTests.mm
+++ b/platform/darwin/test/MGLStyleTests.mm
@@ -210,9 +210,9 @@
MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
[self.style addSource:rasterSource];
- // Attempt to remove a shape source with the same identifier as the raster source
- MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"some-identifier" shape:nil options:nil];
- [self.style removeSource:shapeSource];
+ // Attempt to remove an image source with the same identifier as the raster source
+ MGLImageSource *imageSource = [[MGLImageSource alloc] initWithIdentifier:@"some-identifier" coordinates: { }];
+ [self.style removeSource:imageSource];
// The raster source should still be added
XCTAssertTrue([[self.style sourceWithIdentifier:rasterSource.identifier] isMemberOfClass:[MGLRasterSource class]]);
@@ -220,16 +220,16 @@
[self.style removeSource:rasterSource];
// Add the shape source
- [self.style addSource:shapeSource];
+ [self.style addSource:imageSource];
// Attempt to remove a vector source with the same identifer as the shape source
MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
[self.style removeSource:vectorSource];
- // The shape source should still be added
- XCTAssertTrue([[self.style sourceWithIdentifier:shapeSource.identifier] isMemberOfClass:[MGLShapeSource class]]);
+ // The image source should still be added
+ XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLImageSource class]]);
- // Remove the shape source
- [self.style removeSource:shapeSource];
+ // Remove the image source
+ [self.style removeSource:imageSource];
// Add the vector source
[self.style addSource:vectorSource];
@@ -237,7 +237,7 @@
// Attempt to remove the previously created raster source that has the same identifer as the shape source
[self.style removeSource:rasterSource];
// The vector source should still be added
- XCTAssertTrue([[self.style sourceWithIdentifier:shapeSource.identifier] isMemberOfClass:[MGLVectorSource class]]);
+ XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLVectorSource class]]);
}
- (void)testRemovingSourceInUse {
diff --git a/platform/darwin/test/Media.xcassets/RadarImage.imageset/Contents.json b/platform/darwin/test/Media.xcassets/RadarImage.imageset/Contents.json
new file mode 100644
index 0000000000..79be9ed970
--- /dev/null
+++ b/platform/darwin/test/Media.xcassets/RadarImage.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "radar.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/darwin/test/Media.xcassets/RadarImage.imageset/radar.png b/platform/darwin/test/Media.xcassets/RadarImage.imageset/radar.png
new file mode 100644
index 0000000000..e23697f42a
--- /dev/null
+++ b/platform/darwin/test/Media.xcassets/RadarImage.imageset/radar.png
Binary files differ
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 672bb3b997..756f4d5516 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -72,6 +72,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
MBXSettingsRuntimeStylingUpdateShapeSourceFeatures,
MBXSettingsRuntimeStylingVectorSource,
MBXSettingsRuntimeStylingRasterSource,
+ MBXSettingsRuntimeStylingImageSource,
MBXSettingsRuntimeStylingCountryLabels,
MBXSettingsRuntimeStylingRouteLine,
MBXSettingsRuntimeStylingDDSPolygon,
@@ -345,6 +346,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@"Update Shape Source: Features",
@"Style Vector Source",
@"Style Raster Source",
+ @"Style Image Source",
[NSString stringWithFormat:@"Label Countries in %@", (_usingLocaleBasedCountryLabels ? @"Local Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])],
@"Add Route Line",
@"Dynamically Style Polygon",
@@ -585,6 +587,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
case MBXSettingsRuntimeStylingRasterSource:
[self styleRasterSource];
break;
+ case MBXSettingsRuntimeStylingImageSource:
+ [self styleImageSource];
+ break;
case MBXSettingsRuntimeStylingCountryLabels:
[self styleCountryLabelsLanguage];
break;
@@ -1308,6 +1313,21 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self.mapView.style addLayer:rasterLayer];
}
+- (void)styleImageSource
+{
+ MGLCoordinateQuad coordinateQuad = {
+ { 46.437, -80.425 },
+ { 46.437, -71.516 },
+ { 37.936, -71.516 },
+ { 37.936, -80.425 } };
+
+ MGLImageSource *imageSource = [[MGLImageSource alloc] initWithIdentifier:@"style-image-source-id" coordinates:coordinateQuad imageURL:[NSURL URLWithString:@"https://www.mapbox.com/mapbox-gl-js/assets/radar.gif"]];
+ [self.mapView.style addSource:imageSource];
+
+ MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"style-raster-image-layer-id" source:imageSource];
+ [self.mapView.style addLayer:rasterLayer];
+}
+
-(void)styleCountryLabelsLanguage
{
NSArray<NSString *> *labelLayers = @[
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 0cfe72de81..0ed3fdbe8c 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -7,6 +7,13 @@
objects = {
/* Begin PBXBuildFile section */
+ 071BBAFF1EE7613E001FB02A /* MGLImageSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */; };
+ 071BBB001EE7613F001FB02A /* MGLImageSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */; };
+ 071BBB011EE76142001FB02A /* MGLImageSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFB1EE75CD4001FB02A /* MGLImageSource_Private.h */; };
+ 071BBB021EE76143001FB02A /* MGLImageSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFB1EE75CD4001FB02A /* MGLImageSource_Private.h */; };
+ 071BBB031EE76146001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 071BBB041EE76147001FB02A /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 071BBB071EE77631001FB02A /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */; };
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -538,6 +545,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 071BBAFB1EE75CD4001FB02A /* MGLImageSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource_Private.h; sourceTree = "<group>"; };
+ 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource.h; sourceTree = "<group>"; };
+ 071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; };
+ 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLImageSourceTests.m; path = ../../darwin/test/MGLImageSourceTests.m; sourceTree = "<group>"; };
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
@@ -976,6 +987,9 @@
35136D491D4277EA00C20EFD /* Sources */ = {
isa = PBXGroup;
children = (
+ 071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */,
+ 071BBAFB1EE75CD4001FB02A /* MGLImageSource_Private.h */,
+ 071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */,
3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */,
DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */,
3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */,
@@ -1133,6 +1147,7 @@
40CFA64E1D78754A008103BD /* Sources */ = {
isa = PBXGroup;
children = (
+ 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */,
40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */,
920A3E5C1E6F995200C16EFC /* MGLSourceQueryTests.m */,
4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */,
@@ -1665,6 +1680,7 @@
DA8848311CBAFA6200AB86E3 /* NSString+MGLAdditions.h in Headers */,
353933F81D3FB79F003F57D7 /* MGLLineStyleLayer.h in Headers */,
DAAF722D1DA903C700312FA4 /* MGLStyleValue_Private.h in Headers */,
+ 071BBB031EE76146001FB02A /* MGLImageSource.h in Headers */,
DA8847F41CBAFA5100AB86E3 /* MGLOfflinePack.h in Headers */,
DA88482E1CBAFA6200AB86E3 /* NSException+MGLAdditions.h in Headers */,
DA8848551CBAFB9800AB86E3 /* MGLLocationManager.h in Headers */,
@@ -1705,6 +1721,7 @@
DA8847F21CBAFA5100AB86E3 /* MGLMapCamera.h in Headers */,
3538AA1D1D542239008EC33D /* MGLForegroundStyleLayer.h in Headers */,
DA8847F51CBAFA5100AB86E3 /* MGLOfflineRegion.h in Headers */,
+ 071BBB011EE76142001FB02A /* MGLImageSource_Private.h in Headers */,
DA737EE11D056A4E005BDA16 /* MGLMapViewDelegate.h in Headers */,
DA8848851CBB033F00AB86E3 /* FABKitProtocol.h in Headers */,
DA88481B1CBAFA6200AB86E3 /* MGLGeometry_Private.h in Headers */,
@@ -1740,6 +1757,7 @@
FA68F14B1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.h in Headers */,
353933FC1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */,
3566C76D1D4A8DFA008152BC /* MGLRasterSource.h in Headers */,
+ 071BBB021EE76143001FB02A /* MGLImageSource_Private.h in Headers */,
DAED38641D62D0FC00D7640F /* NSURL+MGLAdditions.h in Headers */,
DABFB85E1CBE99E500D62B32 /* MGLAnnotation.h in Headers */,
DABFB8641CBE99E500D62B32 /* MGLOfflineStorage.h in Headers */,
@@ -1748,6 +1766,7 @@
3566C7671D4A77BA008152BC /* MGLShapeSource.h in Headers */,
DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */,
404C26E31D89B877000AA13D /* MGLTileSource.h in Headers */,
+ 071BBB041EE76147001FB02A /* MGLImageSource.h in Headers */,
DABFB8611CBE99E500D62B32 /* MGLMultiPoint.h in Headers */,
3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */,
35D3A1E71E9BE7EC002B38EE /* MGLScaleBar.h in Headers */,
@@ -1958,7 +1977,6 @@
TargetAttributes = {
DA1DC9491CB6C1C2006E619F = {
CreatedOnToolsVersion = 7.3;
- DevelopmentTeam = GJZR2MEM28;
LastSwiftMigration = 0820;
};
DA25D5B81CCD9EDE00607828 = {
@@ -2139,6 +2157,7 @@
35D9DDE21DA25EEC00DAAD69 /* MGLCodingTests.m in Sources */,
DA1F8F3D1EBD287B00367E42 /* MGLDocumentationGuideTests.swift in Sources */,
3598544D1E1D38AA00B29F84 /* MGLDistanceFormatterTests.m in Sources */,
+ 071BBB071EE77631001FB02A /* MGLImageSourceTests.m in Sources */,
DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */,
DA35A2C61CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */,
DAE7DEC21E245455007505A6 /* MGLNSStringAdditionsTests.m in Sources */,
@@ -2215,6 +2234,7 @@
DD0902A91DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */,
35D13AB91D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */,
DA35A2CB1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */,
+ 071BBB001EE7613F001FB02A /* MGLImageSource.mm in Sources */,
DA8848321CBAFA6200AB86E3 /* NSString+MGLAdditions.m in Sources */,
408AA8581DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */,
DA35A2A11CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
@@ -2296,6 +2316,7 @@
DD0902AA1DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */,
DA35A2B41CCA141D00E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
35D13ABA1D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */,
+ 071BBAFF1EE7613E001FB02A /* MGLImageSource.mm in Sources */,
DA35A2CC1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */,
408AA8591DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */,
DAA4E4281CBB730400178DFB /* MGLTypes.m in Sources */,
@@ -2616,6 +2637,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/app/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -2629,6 +2651,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "$(SRCROOT)/app/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index 67a26e8ed4..abe16cc3ee 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -52,6 +52,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLVectorSource.h"
#import "MGLShapeSource.h"
#import "MGLRasterSource.h"
+#import "MGLImageSource.h"
#import "MGLTilePyramidOfflineRegion.h"
#import "MGLTypes.h"
#import "MGLUserLocation.h"
diff --git a/platform/ios/src/UIImage+MGLAdditions.h b/platform/ios/src/UIImage+MGLAdditions.h
index 0b4cb4c015..671a5ced85 100644
--- a/platform/ios/src/UIImage+MGLAdditions.h
+++ b/platform/ios/src/UIImage+MGLAdditions.h
@@ -10,6 +10,8 @@ NS_ASSUME_NONNULL_BEGIN
- (std::unique_ptr<mbgl::style::Image>)mgl_styleImageWithIdentifier:(NSString *)identifier;
+- (mbgl::PremultipliedImage)mgl_PremultipliedImage;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/ios/src/UIImage+MGLAdditions.mm b/platform/ios/src/UIImage+MGLAdditions.mm
index b10c48a62a..029366c01e 100644
--- a/platform/ios/src/UIImage+MGLAdditions.mm
+++ b/platform/ios/src/UIImage+MGLAdditions.mm
@@ -25,8 +25,11 @@
- (std::unique_ptr<mbgl::style::Image>)mgl_styleImageWithIdentifier:(NSString *)identifier {
BOOL isTemplate = self.renderingMode == UIImageRenderingModeAlwaysTemplate;
return std::make_unique<mbgl::style::Image>([identifier UTF8String],
- MGLPremultipliedImageFromCGImage(self.CGImage),
+ self.mgl_PremultipliedImage,
float(self.scale), isTemplate);
}
+-(mbgl::PremultipliedImage)mgl_PremultipliedImage {
+ return MGLPremultipliedImageFromCGImage(self.CGImage);
+}
@end
diff --git a/platform/macos/app/Assets.xcassets/Radar/Contents.json b/platform/macos/app/Assets.xcassets/Radar/Contents.json
new file mode 100644
index 0000000000..da4a164c91
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/Contents.json
new file mode 100644
index 0000000000..ea096b04b8
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "southeast_radar_0.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/southeast_radar_0.png b/platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/southeast_radar_0.png
new file mode 100644
index 0000000000..c304b619c4
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_0.imageset/southeast_radar_0.png
Binary files differ
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/Contents.json
new file mode 100644
index 0000000000..a6a031ae2b
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "southeast_radar_1.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/southeast_radar_1.png b/platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/southeast_radar_1.png
new file mode 100644
index 0000000000..ed09fffbe1
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_1.imageset/southeast_radar_1.png
Binary files differ
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/Contents.json
new file mode 100644
index 0000000000..d607dda298
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "southeast_radar_2.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/southeast_radar_2.png b/platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/southeast_radar_2.png
new file mode 100644
index 0000000000..fee630f863
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_2.imageset/southeast_radar_2.png
Binary files differ
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/Contents.json
new file mode 100644
index 0000000000..9a110068a1
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "southeast_radar_3.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/southeast_radar_3.png b/platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/southeast_radar_3.png
new file mode 100644
index 0000000000..c4c7146afa
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Radar/southeast_3.imageset/southeast_radar_3.png
Binary files differ
diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib
index 20a4f65b3f..9a8cf05c16 100644
--- a/platform/macos/app/Base.lproj/MainMenu.xib
+++ b/platform/macos/app/Base.lproj/MainMenu.xib
@@ -554,6 +554,12 @@
<action selector="insertCustomStyleLayer:" target="-1" id="LE5-lz-kx3"/>
</connections>
</menuItem>
+ <menuItem title="Add Animated Image Source" id="tjA-fT-GbA">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="addAnimatedImageSource:" target="-1" id="TuN-Pa-hTG"/>
+ </connections>
+ </menuItem>
<menuItem title="Show All Annnotations" keyEquivalent="A" id="yMj-uM-8SN">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index 59844d363e..281497ac92 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -617,6 +617,34 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
cos(angle) * 20);
}
+- (IBAction) addAnimatedImageSource:(id)sender {
+
+ MGLImage *image = [[NSBundle bundleForClass:[self class]] imageForResource:@"southeast_0"];
+
+ MGLCoordinateBounds bounds = { {22.551103322318994, -90.24006072802854}, {36.928147474567794, -75.1441643681673} };
+ MGLImageSource *imageSource = [[MGLImageSource alloc] initWithIdentifier:@"radar-source" bounds:bounds image:image];
+ [self.mapView.style addSource:imageSource];
+
+ MGLRasterStyleLayer * imageLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"radar-layer" source:imageSource];
+ [self.mapView.style addLayer:imageLayer];
+
+ [NSTimer scheduledTimerWithTimeInterval:1.0
+ target:self
+ selector:@selector(updateAnimatedImageSource:)
+ userInfo:imageSource
+ repeats:YES];
+}
+
+
+- (void)updateAnimatedImageSource:(NSTimer *)timer {
+ MGLImageSource *imageSource = (MGLImageSource *)timer.userInfo;
+ double timeInterval = timer.fireDate.timeIntervalSinceReferenceDate;
+ int radarSuffix = (int)timeInterval % 4;
+ MGLImage *image = [[NSBundle bundleForClass:[self class]] imageForResource:[NSString stringWithFormat:@"southeast_%d", radarSuffix]];
+
+ [imageSource setValue:image forKey:@"image"];
+}
+
- (IBAction)insertCustomStyleLayer:(id)sender {
[self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) {
[self removeCustomStyleLayer:sender];
@@ -695,14 +723,18 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
MGLTransition transition = { .duration = 5, .delay = 1 };
self.mapView.style.transition = transition;
- MGLFillStyleLayer *fillStyleLayer = (MGLFillStyleLayer *)[self.mapView.style layerWithIdentifier:@"water"];
-
+ MGLStyleLayer *waterLayer = [self.mapView.style layerWithIdentifier:@"water"];
MGLStyleValue *colorFunction = [MGLStyleValue<NSColor *> valueWithInterpolationMode:MGLInterpolationModeExponential cameraStops:@{
@0.0: [MGLStyleValue<NSColor *> valueWithRawValue:[NSColor redColor]],
@10.0: [MGLStyleValue<NSColor *> valueWithRawValue:[NSColor yellowColor]],
@20.0: [MGLStyleValue<NSColor *> valueWithRawValue:[NSColor blackColor]],
} options:nil];
- fillStyleLayer.fillColor = colorFunction;
+
+ if ([waterLayer respondsToSelector:@selector(fillColor)]) {
+ [waterLayer setValue:colorFunction forKey:@"fillColor"];
+ } else if ([waterLayer respondsToSelector:@selector(lineColor)]) {
+ [waterLayer setValue:colorFunction forKey:@"lineColor"];
+ }
NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"];
NSURL *geoJSONURL = [NSURL fileURLWithPath:filePath];
@@ -714,21 +746,34 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
fillLayer.predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"type", @"park"];
[self.mapView.style addLayer:fillLayer];
+ MGLSource *streetsSource = [self.mapView.style sourceWithIdentifier:@"composite"];
+ if (streetsSource) {
NSImage *image = [NSImage imageNamed:NSImageNameIChatTheaterTemplate];
[self.mapView.style setImage:image forName:NSImageNameIChatTheaterTemplate];
- MGLSource *streetsSource = [self.mapView.style sourceWithIdentifier:@"composite"];
- MGLSymbolStyleLayer *theaterLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"theaters" source:streetsSource];
- theaterLayer.sourceLayerIdentifier = @"poi_label";
- theaterLayer.predicate = [NSPredicate predicateWithFormat:@"maki == 'theatre'"];
- theaterLayer.iconImageName = [MGLStyleValue valueWithRawValue:NSImageNameIChatTheaterTemplate];
- theaterLayer.iconScale = [MGLStyleValue valueWithRawValue:@2];
- theaterLayer.iconColor = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential cameraStops:@{
- @16.0: [MGLStyleValue valueWithRawValue:[NSColor redColor]],
- @18.0: [MGLStyleValue valueWithRawValue:[NSColor yellowColor]],
- @20.0: [MGLStyleValue valueWithRawValue:[NSColor blackColor]],
- } options:nil];
- [self.mapView.style addLayer:theaterLayer];
+ MGLSymbolStyleLayer *theaterLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"theaters" source:streetsSource];
+ theaterLayer.sourceLayerIdentifier = @"poi_label";
+ theaterLayer.predicate = [NSPredicate predicateWithFormat:@"maki == 'theatre'"];
+ theaterLayer.iconImageName = [MGLStyleValue valueWithRawValue:NSImageNameIChatTheaterTemplate];
+ theaterLayer.iconScale = [MGLStyleValue valueWithRawValue:@2];
+ theaterLayer.iconColor = [MGLStyleValue valueWithInterpolationMode:MGLInterpolationModeExponential cameraStops:@{
+ @16.0: [MGLStyleValue valueWithRawValue:[NSColor redColor]],
+ @18.0: [MGLStyleValue valueWithRawValue:[NSColor yellowColor]],
+ @20.0: [MGLStyleValue valueWithRawValue:[NSColor blackColor]],
+ } options:nil];
+ [self.mapView.style addLayer:theaterLayer];
+ }
+
+ MGLImage *image = [[NSBundle bundleForClass:[self class]] imageForResource:@"RadarImage"];
+ MGLCoordinateQuad quad = { {46.437, -80.425},
+ {46.437, -71.516},
+ {37.936, -71.516},
+ {37.936, -80.425} };
+ MGLImageSource *imageSource = [[MGLImageSource alloc] initWithIdentifier:@"radar-source" coordinates:quad image:image];
+ [self.mapView.style addSource:imageSource];
+
+ MGLRasterStyleLayer * imageLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"radar-layer" source:imageSource];
+ [self.mapView.style addLayer:imageLayer];
}
- (IBAction)dropPin:(NSMenuItem *)sender {
@@ -937,6 +982,9 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
if (menuItem.action == @selector(drawAnimatedAnnotation:)) {
return !_isShowingAnimatedAnnotation;
}
+ if (menuItem.action == @selector(addAnimatedImageSource:)) {
+ return YES;
+ }
if (menuItem.action == @selector(insertCustomStyleLayer:)) {
return ![self.mapView.style layerWithIdentifier:@"mbx-custom"];
}
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 564d81afb2..248f913a35 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
+ 0721493F1EE200E900085505 /* MGLImageSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07A019EB1ED662D800ACD43E /* MGLImageSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 07A019EF1ED665CD00ACD43E /* MGLImageSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07A019EC1ED662D800ACD43E /* MGLImageSource.mm */; };
+ 07BA4CAC1EE21887004528F5 /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BA4CAB1EE21887004528F5 /* MGLImageSourceTests.m */; };
1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */; };
1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */; };
1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A11ECFB00300021D39 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -271,6 +274,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 07A019EA1ED662D800ACD43E /* MGLImageSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource_Private.h; sourceTree = "<group>"; };
+ 07A019EB1ED662D800ACD43E /* MGLImageSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLImageSource.h; sourceTree = "<group>"; };
+ 07A019EC1ED662D800ACD43E /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; };
+ 07BA4CAB1EE21887004528F5 /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLImageSourceTests.m; sourceTree = "<group>"; };
1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
1F7454A01ECFB00300021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
1F7454A11ECFB00300021D39 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
@@ -664,6 +671,9 @@
DA8F25951D51CAC70010E6B5 /* MGLVectorSource.h */,
DA7DC9801DED5F5C0027472F /* MGLVectorSource_Private.h */,
DA8F25961D51CAC70010E6B5 /* MGLVectorSource.mm */,
+ 07A019EA1ED662D800ACD43E /* MGLImageSource_Private.h */,
+ 07A019EB1ED662D800ACD43E /* MGLImageSource.h */,
+ 07A019EC1ED662D800ACD43E /* MGLImageSource.mm */,
);
name = Sources;
sourceTree = "<group>";
@@ -774,6 +784,7 @@
DA87A9961DC9D88400810D09 /* MGLShapeSourceTests.mm */,
DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */,
920A3E581E6F859D00C16EFC /* MGLSourceQueryTests.m */,
+ 07BA4CAB1EE21887004528F5 /* MGLImageSourceTests.m */,
);
name = Sources;
sourceTree = "<group>";
@@ -1166,6 +1177,7 @@
DAE6C3B41CC31EF300DB3429 /* MGLCompassCell.h in Headers */,
DA87A99C1DC9D8DD00810D09 /* MGLShapeSource_Private.h in Headers */,
3537CA741D3F93A600380318 /* MGLStyle_Private.h in Headers */,
+ 0721493F1EE200E900085505 /* MGLImageSource.h in Headers */,
DA8F259A1D51CAD00010E6B5 /* MGLSource_Private.h in Headers */,
DA8F25931D51CA750010E6B5 /* MGLSymbolStyleLayer.h in Headers */,
DAE6C3B91CC31EF300DB3429 /* MGLOpenGLLayer.h in Headers */,
@@ -1386,6 +1398,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 07A019EF1ED665CD00ACD43E /* MGLImageSource.mm in Sources */,
40ABDB561DB0022100372083 /* NSImage+MGLAdditions.mm in Sources */,
DAE6C3901CC31E2A00DB3429 /* MGLPointAnnotation.mm in Sources */,
DAE6C3981CC31E2A00DB3429 /* NSBundle+MGLAdditions.m in Sources */,
@@ -1478,6 +1491,7 @@
DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.mm in Sources */,
DAA999011E9F5EC5002E6EA6 /* MGLFillExtrusionStyleLayerTests.mm in Sources */,
DA29875A1E1A4290002299F5 /* MGLDocumentationExampleTests.swift in Sources */,
+ 07BA4CAC1EE21887004528F5 /* MGLImageSourceTests.m in Sources */,
DAE6C3D31CC34C9900DB3429 /* MGLOfflinePackTests.m in Sources */,
DA87A9A51DCACC5000810D09 /* MGLLineStyleLayerTests.mm in Sources */,
DA87A9A31DCACC5000810D09 /* MGLRasterStyleLayerTests.mm in Sources */,
diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h
index 0f47dace70..e4ad258b6e 100644
--- a/platform/macos/src/Mapbox.h
+++ b/platform/macos/src/Mapbox.h
@@ -50,6 +50,7 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLVectorSource.h"
#import "MGLShapeSource.h"
#import "MGLRasterSource.h"
+#import "MGLImageSource.h"
#import "MGLTilePyramidOfflineRegion.h"
#import "MGLTypes.h"
#import "NSValue+MGLAdditions.h"
diff --git a/platform/macos/src/NSImage+MGLAdditions.h b/platform/macos/src/NSImage+MGLAdditions.h
index 1bcec00e8b..0e57784bc5 100644
--- a/platform/macos/src/NSImage+MGLAdditions.h
+++ b/platform/macos/src/NSImage+MGLAdditions.h
@@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
- (std::unique_ptr<mbgl::style::Image>)mgl_styleImageWithIdentifier:(NSString *)identifier;
+- (mbgl::PremultipliedImage) mgl_PremultipliedImage;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/macos/src/NSImage+MGLAdditions.mm b/platform/macos/src/NSImage+MGLAdditions.mm
index ecd8aabe15..e4ef38eea5 100644
--- a/platform/macos/src/NSImage+MGLAdditions.mm
+++ b/platform/macos/src/NSImage+MGLAdditions.mm
@@ -33,6 +33,15 @@
}
- (std::unique_ptr<mbgl::style::Image>)mgl_styleImageWithIdentifier:(NSString *)identifier {
+ mbgl::PremultipliedImage cPremultipliedImage = self.mgl_PremultipliedImage;
+ auto imageWidth = cPremultipliedImage.size.width;
+ return std::make_unique<mbgl::style::Image>([identifier UTF8String],
+ std::move(cPremultipliedImage),
+ (float)(imageWidth / self.size.width),
+ [self isTemplate]);
+}
+
+- (mbgl::PremultipliedImage)mgl_PremultipliedImage {
// Create a bitmap image representation from the image, respecting backing
// scale factor and any resizing done on the image at runtime.
// http://www.cocoabuilder.com/archive/cocoa/82430-nsimage-getting-raw-bitmap-data.html#82431
@@ -42,10 +51,6 @@
mbgl::PremultipliedImage cPremultipliedImage({ static_cast<uint32_t>(rep.pixelsWide), static_cast<uint32_t>(rep.pixelsHigh) });
std::copy(rep.bitmapData, rep.bitmapData + cPremultipliedImage.bytes(), cPremultipliedImage.data.get());
- return std::make_unique<mbgl::style::Image>([identifier UTF8String],
- std::move(cPremultipliedImage),
- (float)(rep.pixelsWide / self.size.width),
- [self isTemplate]);
+ return cPremultipliedImage;
}
-
@end
diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp
index 8c9c1658a1..49ec0065c3 100644
--- a/src/mbgl/renderer/buckets/raster_bucket.cpp
+++ b/src/mbgl/renderer/buckets/raster_bucket.cpp
@@ -13,7 +13,9 @@ RasterBucket::RasterBucket(UnassociatedImage&& image_) : image(std::move(image_)
}
void RasterBucket::upload(gl::Context& context) {
- texture = context.createTexture(image);
+ if (!texture) {
+ texture = context.createTexture(image);
+ }
if (!vertices.empty()) {
vertexBuffer = context.createVertexBuffer(std::move(vertices));
indexBuffer = context.createIndexBuffer(std::move(indices));
@@ -27,7 +29,7 @@ void RasterBucket::clear() {
segments.clear();
vertices.clear();
indices.clear();
-
+
uploaded = false;
}
void RasterBucket::render(Painter& painter,
diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp
index 7fb7caa580..f5068b9d7f 100644
--- a/src/mbgl/renderer/sources/render_image_source.cpp
+++ b/src/mbgl/renderer/sources/render_image_source.cpp
@@ -135,12 +135,13 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_,
geomCoords.push_back(gc);
}
- if (!bucket) {
- UnassociatedImage img = impl().getImage().clone();
- if (!img.valid()) {
- return;
- }
- bucket = std::make_unique<RasterBucket>(std::move(img));
+ const UnassociatedImage& image = impl().getImage();
+ if (!image.valid()) {
+ return;
+ }
+
+ if (!bucket || image != bucket->image) {
+ bucket = std::make_unique<RasterBucket>(image.clone());
} else {
bucket->clear();
}