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

Add image accessor to MGLStyle #7096

Merged
merged 4 commits into from
Dec 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ class Map : private util::noncopyable {
// Add image, bound to the style
void addImage(const std::string&, std::unique_ptr<const SpriteImage>);
void removeImage(const std::string&);
const SpriteImage* getImage(const std::string&);

// Defaults
std::string getStyleName() const;
Expand Down
17 changes: 17 additions & 0 deletions platform/darwin/src/MGLStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,23 @@ static const NSInteger MGLStyleDefaultVersion = 9;

#pragma mark Managing a Style’s Images

/**
Returns the image associated with the given name in the style.

@note Names and their associated images are not guaranteed to exist across
styles or different versions of the same style. Applications that use this
API must first set the style URL to an explicitly versioned style using a
convenience method like `+[MGLStyle outdoorsStyleURLWithVersion:]`,
`MGLMapView`'s “Style URL” inspectable in Interface Builder, or a manually
constructed `NSURL`. This approach also avoids image name changes that will
occur in the default style over time.

@param name The name associated with the image you want to obtain.
@return The image associated with the given name, or `nil` if no image is
associated with that name.
*/
- (nullable MGLImage *)imageForName:(NSString *)name;

/**
Adds or overrides an image used by the style’s layers.

Expand Down
26 changes: 23 additions & 3 deletions platform/darwin/src/MGLStyle.mm
Original file line number Diff line number Diff line change
Expand Up @@ -482,19 +482,39 @@ - (void)removeStyleClass:(NSString *)styleClass

- (void)setImage:(MGLImage *)image forName:(NSString *)name
{
NSAssert(image, @"image is null");
NSAssert(name, @"name is null");
if (!image) {
[NSException raise:NSInvalidArgumentException
format:@"Cannot assign nil image to “%@”.", name];
}
if (!name) {
[NSException raise:NSInvalidArgumentException
format:@"Cannot assign image %@ to a nil name.", image];
}

self.mapView.mbglMap->addImage([name UTF8String], image.mgl_spriteImage);
}

- (void)removeImageForName:(NSString *)name
{
NSAssert(name, @"name is null");
if (!name) {
[NSException raise:NSInvalidArgumentException
format:@"Cannot remove image with nil name."];
}

self.mapView.mbglMap->removeImage([name UTF8String]);
}

- (MGLImage *)imageForName:(NSString *)name
{
if (!name) {
[NSException raise:NSInvalidArgumentException
format:@"Cannot get image with nil name."];
}

auto spriteImage = self.mapView.mbglMap->getImage([name UTF8String]);
return spriteImage ? [[MGLImage alloc] initWithMGLSpriteImage:spriteImage] : nil;
}

- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; name = %@, URL = %@>",
Expand Down
24 changes: 24 additions & 0 deletions platform/darwin/test/MGLStyleTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
#import <mbgl/util/default_styles.hpp>

#import <XCTest/XCTest.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#else
#import <Cocoa/Cocoa.h>
#endif
#import <objc/runtime.h>

@interface MGLStyleTests : XCTestCase
Expand Down Expand Up @@ -175,4 +180,23 @@ - (NSString *)stringWithContentsOfStyleHeader {
return styleHeader;
}

- (void)testImages {
NSString *imageName = @"TrackingLocationMask";
#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);

[self.mapView.style setImage:image forName:imageName];
MGLImage *styleImage = [self.mapView.style imageForName:imageName];

XCTAssertNotNil(styleImage);
XCTAssertEqual(image.size.width, styleImage.size.width);
XCTAssertEqual(image.size.height, styleImage.size.height);
}

@end
6 changes: 6 additions & 0 deletions platform/darwin/test/Media.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "TrackingLocationMask.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "TrackingLocationMask@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "TrackingLocationMask@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions platform/ios/app/Assets.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
Expand Down Expand Up @@ -36,6 +46,16 @@
"filename" : "Icon-60@3x.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
Expand Down
4 changes: 4 additions & 0 deletions platform/ios/ios.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
DA25D5C01CCD9F8400607828 /* Root.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5BF1CCD9F8400607828 /* Root.plist */; };
DA25D5C61CCDA06800607828 /* Root.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5C41CCDA06800607828 /* Root.strings */; };
DA25D5CD1CCDA11500607828 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5B91CCD9EDE00607828 /* Settings.bundle */; };
DA2784FC1DF02FF4001D5B8D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA2784FB1DF02FF4001D5B8D /* Media.xcassets */; };
DA27C24E1CBB3811000B0ECD /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA27C24D1CBB3811000B0ECD /* GLKit.framework */; };
DA27C24F1CBB4C11000B0ECD /* MGLAccountManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */; };
DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */; };
Expand Down Expand Up @@ -618,6 +619,7 @@
DA25D5B91CCD9EDE00607828 /* Settings.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Settings.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
DA25D5BF1CCD9F8400607828 /* Root.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Root.plist; sourceTree = "<group>"; };
DA25D5C51CCDA06800607828 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Root.strings; sourceTree = "<group>"; };
DA2784FB1DF02FF4001D5B8D /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = ../../darwin/test/Media.xcassets; sourceTree = "<group>"; };
DA27C24D1CBB3811000B0ECD /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
DA2DBBCC1D51E80400D38FF9 /* MGLStyleLayerTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLStyleLayerTests.h; path = ../../darwin/test/MGLStyleLayerTests.h; sourceTree = "<group>"; };
DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLStyleLayerTests.m; path = ../../darwin/test/MGLStyleLayerTests.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1065,6 +1067,7 @@
DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */,
DD58A4C51D822BD000E1F038 /* MGLExpressionTests.mm */,
DA2E88551CC036F400F24E7B /* Info.plist */,
DA2784FB1DF02FF4001D5B8D /* Media.xcassets */,
);
name = "SDK Tests";
path = test;
Expand Down Expand Up @@ -1805,6 +1808,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DA2784FC1DF02FF4001D5B8D /* Media.xcassets in Resources */,
353BAEF71D646370009A8DA9 /* amsterdam.geojson in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
6 changes: 6 additions & 0 deletions platform/ios/src/UIImage+MGLAdditions.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

#include <mbgl/sprite/sprite_image.hpp>

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (MGLAdditions)

- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage;

- (std::unique_ptr<mbgl::SpriteImage>)mgl_spriteImage;

@end

NS_ASSUME_NONNULL_END
7 changes: 7 additions & 0 deletions platform/ios/src/UIImage+MGLAdditions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

@implementation UIImage (MGLAdditions)

- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage
{
std::string png = encodePNG(spriteImage->image);
NSData *data = [[NSData alloc] initWithBytes:png.data() length:png.size()];
return [self initWithData:data scale:spriteImage->pixelRatio];
}

- (std::unique_ptr<mbgl::SpriteImage>)mgl_spriteImage
{
CGImageRef cgImage = self.CGImage;
Expand Down
4 changes: 4 additions & 0 deletions platform/macos/macos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
55D9B4B11D005D3900C1CCE2 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D9B4B01D005D3900C1CCE2 /* libz.tbd */; };
DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */; };
DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */; };
DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA2784FD1DF03060001D5B8D /* Media.xcassets */; };
DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */; };
DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */; };
Expand Down Expand Up @@ -296,6 +297,7 @@
DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; };
DA2207BA1DC076930002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = "<group>"; };
DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLStyleValueTests.swift; sourceTree = "<group>"; };
DA2784FD1DF03060001D5B8D /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = ../../darwin/test/Media.xcassets; sourceTree = "<group>"; };
DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MGLStyleLayerTests.xib; sourceTree = "<group>"; };
DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCoordinateFormatter.h; sourceTree = "<group>"; };
DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCoordinateFormatter.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -842,6 +844,7 @@
DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */,
DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */,
DAE6C33A1CC30DB200DB3429 /* Info.plist */,
DA2784FD1DF03060001D5B8D /* Media.xcassets */,
);
name = "SDK Tests";
path = test;
Expand Down Expand Up @@ -1150,6 +1153,7 @@
buildActionMask = 2147483647;
files = (
35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */,
DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */,
DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
6 changes: 6 additions & 0 deletions platform/macos/src/NSImage+MGLAdditions.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

#include <mbgl/sprite/sprite_image.hpp>

NS_ASSUME_NONNULL_BEGIN

@interface NSImage (MGLAdditions)

- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage;

- (std::unique_ptr<mbgl::SpriteImage>)mgl_spriteImage;

@end

NS_ASSUME_NONNULL_END
13 changes: 10 additions & 3 deletions platform/macos/src/NSImage+MGLAdditions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

@implementation NSImage (MGLAdditions)

- (nullable instancetype)initWithMGLSpriteImage:(const mbgl::SpriteImage *)spriteImage {
std::string png = encodePNG(spriteImage->image);
NSData *data = [[NSData alloc] initWithBytes:png.data() length:png.size()];
NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:data];
if ([self initWithSize:NSMakeSize(spriteImage->getWidth(), spriteImage->getHeight())]) {
[self addRepresentation:rep];
}
return self;
}

- (std::unique_ptr<mbgl::SpriteImage>)mgl_spriteImage {
// Create a bitmap image representation from the image, respecting backing
// scale factor and any resizing done on the image at runtime.
Expand All @@ -10,9 +20,6 @@ @implementation NSImage (MGLAdditions)
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:{ NSZeroPoint, self.size }];
[self unlockFocus];

// Get the image’s raw pixel data as an RGBA buffer.
std::string pixelString((const char *)rep.bitmapData, rep.pixelsWide * rep.pixelsHigh * 4 /* RGBA */);

mbgl::PremultipliedImage cPremultipliedImage(rep.pixelsWide, rep.pixelsHigh);
std::copy(rep.bitmapData, rep.bitmapData + cPremultipliedImage.size(), cPremultipliedImage.data.get());
return std::make_unique<mbgl::SpriteImage>(std::move(cPremultipliedImage),
Expand Down
7 changes: 7 additions & 0 deletions src/mbgl/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,13 @@ void Map::removeImage(const std::string& name) {
impl->onUpdate(Update::Repaint);
}

const SpriteImage* Map::getImage(const std::string& name) {
if (impl->style) {
return impl->style->spriteAtlas->getSprite(name).get();
}
return nullptr;
}

#pragma mark - Defaults

std::string Map::getStyleName() const {
Expand Down
Binary file added test/fixtures/map/get_icon/expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions test/map/map.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,3 +394,15 @@ TEST(Map, RemoveImage) {
map.removeImage("test-icon");
test::checkImage("test/fixtures/map/remove_icon", test::render(map, test.view));
}

TEST(Map, GetImage) {
MapTest test;

Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still);
auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0);

map.setStyleJSON(util::read_file("test/fixtures/api/icon_style.json"));
map.addImage("test-icon", std::move(image));
test::checkImage("test/fixtures/map/get_icon", map.getImage("test-icon")->image);
}