ios: apply clang-format to Objective-C++ sources (#4060)

This commit is contained in:
Bart Louwers
2026-02-24 14:37:35 +01:00
committed by GitHub
parent 41832b518d
commit 5787f9cc38
134 changed files with 29751 additions and 27896 deletions

View File

@@ -7,49 +7,49 @@
@implementation MLNAttributionButton
- (instancetype)initWithAttributionInfo:(MLNAttributionInfo *)info {
if (self = [super initWithFrame:NSZeroRect]) {
self.bordered = NO;
self.bezelStyle = NSBezelStyleBadge;
if (self = [super initWithFrame:NSZeroRect]) {
self.bordered = NO;
self.bezelStyle = NSBezelStyleBadge;
// Extract any prefix consisting of intellectual property symbols.
NSScanner *scanner = [NSScanner scannerWithString:info.title.string];
NSCharacterSet *symbolSet = [NSCharacterSet characterSetWithCharactersInString:@"©℗®℠™ &"];
NSString *symbol;
[scanner scanCharactersFromSet:symbolSet intoString:&symbol];
// Extract any prefix consisting of intellectual property symbols.
NSScanner *scanner = [NSScanner scannerWithString:info.title.string];
NSCharacterSet *symbolSet = [NSCharacterSet characterSetWithCharactersInString:@"©℗®℠™ &"];
NSString *symbol;
[scanner scanCharactersFromSet:symbolSet intoString:&symbol];
// Remove the underline from the symbol for aesthetic reasons.
NSMutableAttributedString *title = info.title.mutableCopy;
[title removeAttribute:NSUnderlineStyleAttributeName range:NSMakeRange(0, symbol.length)];
// Remove the underline from the symbol for aesthetic reasons.
NSMutableAttributedString *title = info.title.mutableCopy;
[title removeAttribute:NSUnderlineStyleAttributeName range:NSMakeRange(0, symbol.length)];
self.attributedTitle = title;
[self sizeToFit];
self.attributedTitle = title;
[self sizeToFit];
_URL = info.URL;
if (_URL) {
self.toolTip = _URL.absoluteString;
}
self.target = self;
self.action = @selector(openURL:);
_URL = info.URL;
if (_URL) {
self.toolTip = _URL.absoluteString;
}
return self;
self.target = self;
self.action = @selector(openURL:);
}
return self;
}
- (BOOL)wantsLayer {
return YES;
return YES;
}
- (void)resetCursorRects {
if (self.URL) {
// The whole button gets a pointing hand cursor, just like a hyperlink.
[self addCursorRect:self.bounds cursor:[NSCursor pointingHandCursor]];
}
if (self.URL) {
// The whole button gets a pointing hand cursor, just like a hyperlink.
[self addCursorRect:self.bounds cursor:[NSCursor pointingHandCursor]];
}
}
- (IBAction)openURL:(__unused id)sender {
if (self.URL) {
[[NSWorkspace sharedWorkspace] openURL:self.URL];
}
if (self.URL) {
[[NSWorkspace sharedWorkspace] openURL:self.URL];
}
}
@end

View File

@@ -7,114 +7,114 @@
@implementation MLNMapView (IBAdditions)
+ (NSSet<NSString *> *)keyPathsForValuesAffectingStyleURL__ {
return [NSSet setWithObject:@"styleURL"];
return [NSSet setWithObject:@"styleURL"];
}
- (nullable NSString *)styleURL__ {
return self.styleURL.absoluteString;
return self.styleURL.absoluteString;
}
- (void)setStyleURL__:(nullable NSString *)URLString {
URLString = [URLString stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSURL *url = URLString.length ? [NSURL URLWithString:URLString] : nil;
if (URLString.length && !url) {
[NSException raise:MLNInvalidStyleURLException
format:@"“%@” is not a valid style URL.", URLString];
}
self.styleURL = url;
URLString =
[URLString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSURL *url = URLString.length ? [NSURL URLWithString:URLString] : nil;
if (URLString.length && !url) {
[NSException raise:MLNInvalidStyleURLException
format:@"“%@” is not a valid style URL.", URLString];
}
self.styleURL = url;
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingLatitude {
return [NSSet setWithObjects:@"centerCoordinate", @"camera", nil];
return [NSSet setWithObjects:@"centerCoordinate", @"camera", nil];
}
- (double)latitude {
return self.centerCoordinate.latitude;
return self.centerCoordinate.latitude;
}
- (void)setLatitude:(double)latitude {
if (!isnan(self.pendingLongitude)) {
// With both components present, set the real center coordinate and
// forget the pending parts.
self.centerCoordinate = CLLocationCoordinate2DMake(latitude, self.pendingLongitude);
self.pendingLatitude = NAN;
self.pendingLongitude = NAN;
} else {
// Not enough info to make a valid center coordinate yet. Stash this
// latitude away until the longitude is set too.
self.pendingLatitude = latitude;
}
if (!isnan(self.pendingLongitude)) {
// With both components present, set the real center coordinate and
// forget the pending parts.
self.centerCoordinate = CLLocationCoordinate2DMake(latitude, self.pendingLongitude);
self.pendingLatitude = NAN;
self.pendingLongitude = NAN;
} else {
// Not enough info to make a valid center coordinate yet. Stash this
// latitude away until the longitude is set too.
self.pendingLatitude = latitude;
}
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingLongitude {
return [NSSet setWithObjects:@"centerCoordinate", @"camera", nil];
return [NSSet setWithObjects:@"centerCoordinate", @"camera", nil];
}
- (double)longitude {
return self.centerCoordinate.longitude;
return self.centerCoordinate.longitude;
}
- (void)setLongitude:(double)longitude {
if (!isnan(self.pendingLatitude)) {
// With both components present, set the real center coordinate and
// forget the pending parts.
self.centerCoordinate = CLLocationCoordinate2DMake(self.pendingLatitude, longitude);
self.pendingLatitude = NAN;
self.pendingLongitude = NAN;
} else {
// Not enough info to make a valid center coordinate yet. Stash this
// longitude away until the latitude is set too.
self.pendingLongitude = longitude;
}
if (!isnan(self.pendingLatitude)) {
// With both components present, set the real center coordinate and
// forget the pending parts.
self.centerCoordinate = CLLocationCoordinate2DMake(self.pendingLatitude, longitude);
self.pendingLatitude = NAN;
self.pendingLongitude = NAN;
} else {
// Not enough info to make a valid center coordinate yet. Stash this
// longitude away until the latitude is set too.
self.pendingLongitude = longitude;
}
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingAllowsZooming {
return [NSSet setWithObject:@"zoomEnabled"];
return [NSSet setWithObject:@"zoomEnabled"];
}
- (BOOL)allowsZooming {
return self.zoomEnabled;
return self.zoomEnabled;
}
- (void)setAllowsZooming:(BOOL)allowsZooming {
self.zoomEnabled = allowsZooming;
self.zoomEnabled = allowsZooming;
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingAllowsScrolling {
return [NSSet setWithObject:@"scrollEnabled"];
return [NSSet setWithObject:@"scrollEnabled"];
}
- (BOOL)allowsScrolling {
return self.scrollEnabled;
return self.scrollEnabled;
}
- (void)setAllowsScrolling:(BOOL)allowsScrolling {
self.scrollEnabled = allowsScrolling;
self.scrollEnabled = allowsScrolling;
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingAllowsRotating {
return [NSSet setWithObject:@"rotateEnabled"];
return [NSSet setWithObject:@"rotateEnabled"];
}
- (BOOL)allowsRotating {
return self.rotateEnabled;
return self.rotateEnabled;
}
- (void)setAllowsRotating:(BOOL)allowsRotating {
self.rotateEnabled = allowsRotating;
self.rotateEnabled = allowsRotating;
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingAllowsTilting {
return [NSSet setWithObject:@"pitchEnabled"];
return [NSSet setWithObject:@"pitchEnabled"];
}
- (BOOL)allowsTilting {
return self.pitchEnabled;
return self.pitchEnabled;
}
- (void)setAllowsTilting:(BOOL)allowsTilting {
self.pitchEnabled = allowsTilting;
self.pitchEnabled = allowsTilting;
}
@end

View File

@@ -9,7 +9,7 @@
typedef struct _CGLContextObject* CGLContextObj;
class MLNMapViewImpl : public mbgl::MapObserver {
public:
public:
static std::unique_ptr<MLNMapViewImpl> Create(MLNMapView*);
MLNMapViewImpl(MLNMapView*);
@@ -61,7 +61,7 @@ class MLNMapViewImpl : public mbgl::MapObserver {
void onSpriteError(const std::optional<mbgl::style::Sprite>&, std::exception_ptr) override;
void onSpriteRequested(const std::optional<mbgl::style::Sprite>&) override;
protected:
protected:
/// Cocoa map view that this adapter bridges to.
__weak MLNMapView* mapView = nullptr;
};

View File

@@ -1,10 +1,10 @@
#import "MLNMapView+Impl.h"
#import <MLNStyle_Private.h>
#import "MLNMapView+Impl.h"
#import "NSBundle+MLNAdditions.h"
#if MLN_RENDER_BACKEND_METAL
#import "MLNMapView+Metal.h"
#else // MLN_RENDER_BACKEND_OPENGL
#else // MLN_RENDER_BACKEND_OPENGL
#import "MLNMapView+OpenGL.h"
#endif
@@ -13,188 +13,199 @@
std::unique_ptr<MLNMapViewImpl> MLNMapViewImpl::Create(MLNMapView* nativeView) {
#if MLN_RENDER_BACKEND_METAL
return std::make_unique<MLNMapViewMetalImpl>(nativeView);
#else // MLN_RENDER_BACKEND_OPENGL
return std::make_unique<MLNMapViewOpenGLImpl>(nativeView);
return std::make_unique<MLNMapViewMetalImpl>(nativeView);
#else // MLN_RENDER_BACKEND_OPENGL
return std::make_unique<MLNMapViewOpenGLImpl>(nativeView);
#endif
}
MLNMapViewImpl::MLNMapViewImpl(MLNMapView* nativeView_) : mapView(nativeView_) {
}
MLNMapViewImpl::MLNMapViewImpl(MLNMapView* nativeView_) : mapView(nativeView_) {}
void MLNMapViewImpl::render() {
[mapView renderSync];
}
void MLNMapViewImpl::render() { [mapView renderSync]; }
void MLNMapViewImpl::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) {
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
[mapView cameraWillChangeAnimated:animated];
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
[mapView cameraWillChangeAnimated:animated];
}
void MLNMapViewImpl::onCameraIsChanging() {
[mapView cameraIsChanging];
}
void MLNMapViewImpl::onCameraIsChanging() { [mapView cameraIsChanging]; }
void MLNMapViewImpl::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) {
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
[mapView cameraDidChangeAnimated:animated];
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
[mapView cameraDidChangeAnimated:animated];
}
void MLNMapViewImpl::onWillStartLoadingMap() {
[mapView mapViewWillStartLoadingMap];
}
void MLNMapViewImpl::onWillStartLoadingMap() { [mapView mapViewWillStartLoadingMap]; }
void MLNMapViewImpl::onDidFinishLoadingMap() {
[mapView mapViewDidFinishLoadingMap];
}
void MLNMapViewImpl::onDidFinishLoadingMap() { [mapView mapViewDidFinishLoadingMap]; }
void MLNMapViewImpl::onDidFailLoadingMap(mbgl::MapLoadError mapError, const std::string& what) {
NSString *description;
MLNErrorCode code;
switch (mapError) {
case mbgl::MapLoadError::StyleParseError:
code = MLNErrorCodeParseStyleFailed;
description = NSLocalizedStringWithDefaultValue(@"PARSE_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style is corrupted.", @"User-friendly error description");
break;
case mbgl::MapLoadError::StyleLoadError:
code = MLNErrorCodeLoadStyleFailed;
description = NSLocalizedStringWithDefaultValue(@"LOAD_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style can't be loaded.", @"User-friendly error description");
break;
case mbgl::MapLoadError::NotFoundError:
code = MLNErrorCodeNotFound;
description = NSLocalizedStringWithDefaultValue(@"STYLE_NOT_FOUND_DESC", nil, nil, @"The map failed to load because the style can’t be found or is incompatible.", @"User-friendly error description");
break;
default:
code = MLNErrorCodeUnknown;
description = NSLocalizedStringWithDefaultValue(@"LOAD_MAP_FAILED_DESC", nil, nil, @"The map failed to load because an unknown error occurred.", @"User-friendly error description");
}
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: description,
NSLocalizedFailureReasonErrorKey: @(what.c_str()),
};
NSError *error = [NSError errorWithDomain:MLNErrorDomain code:code userInfo:userInfo];
[mapView mapViewDidFailLoadingMapWithError:error];
NSString* description;
MLNErrorCode code;
switch (mapError) {
case mbgl::MapLoadError::StyleParseError:
code = MLNErrorCodeParseStyleFailed;
description = NSLocalizedStringWithDefaultValue(
@"PARSE_STYLE_FAILED_DESC", nil, nil,
@"The map failed to load because the style is corrupted.",
@"User-friendly error description");
break;
case mbgl::MapLoadError::StyleLoadError:
code = MLNErrorCodeLoadStyleFailed;
description = NSLocalizedStringWithDefaultValue(
@"LOAD_STYLE_FAILED_DESC", nil, nil,
@"The map failed to load because the style can't be loaded.",
@"User-friendly error description");
break;
case mbgl::MapLoadError::NotFoundError:
code = MLNErrorCodeNotFound;
description = NSLocalizedStringWithDefaultValue(
@"STYLE_NOT_FOUND_DESC", nil, nil,
@"The map failed to load because the style can’t be found or is incompatible.",
@"User-friendly error description");
break;
default:
code = MLNErrorCodeUnknown;
description = NSLocalizedStringWithDefaultValue(
@"LOAD_MAP_FAILED_DESC", nil, nil,
@"The map failed to load because an unknown error occurred.",
@"User-friendly error description");
}
NSDictionary* userInfo = @{
NSLocalizedDescriptionKey : description,
NSLocalizedFailureReasonErrorKey : @(what.c_str()),
};
NSError* error = [NSError errorWithDomain:MLNErrorDomain code:code userInfo:userInfo];
[mapView mapViewDidFailLoadingMapWithError:error];
}
void MLNMapViewImpl::onWillStartRenderingFrame() {
[mapView mapViewWillStartRenderingFrame];
}
void MLNMapViewImpl::onWillStartRenderingFrame() { [mapView mapViewWillStartRenderingFrame]; }
void MLNMapViewImpl::onDidFinishRenderingFrame(const mbgl::MapObserver::RenderFrameStatus& status) {
bool fullyRendered = status.mode == mbgl::MapObserver::RenderMode::Full;
[mapView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered renderingStats:status.renderingStats];
bool fullyRendered = status.mode == mbgl::MapObserver::RenderMode::Full;
[mapView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered
renderingStats:status.renderingStats];
}
void MLNMapViewImpl::onWillStartRenderingMap() {
[mapView mapViewWillStartRenderingMap];
}
void MLNMapViewImpl::onWillStartRenderingMap() { [mapView mapViewWillStartRenderingMap]; }
void MLNMapViewImpl::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) {
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
[mapView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
[mapView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
}
void MLNMapViewImpl::onDidBecomeIdle() {
[mapView mapViewDidBecomeIdle];
}
void MLNMapViewImpl::onDidBecomeIdle() { [mapView mapViewDidBecomeIdle]; }
void MLNMapViewImpl::onDidFinishLoadingStyle() {
[mapView mapViewDidFinishLoadingStyle];
}
void MLNMapViewImpl::onDidFinishLoadingStyle() { [mapView mapViewDidFinishLoadingStyle]; }
void MLNMapViewImpl::onSourceChanged(mbgl::style::Source& source) {
NSString *identifier = @(source.getID().c_str());
MLNSource * nativeSource = [mapView.style sourceWithIdentifier:identifier];
[mapView sourceDidChange:nativeSource];
NSString* identifier = @(source.getID().c_str());
MLNSource* nativeSource = [mapView.style sourceWithIdentifier:identifier];
[mapView sourceDidChange:nativeSource];
}
bool MLNMapViewImpl::onCanRemoveUnusedStyleImage(const std::string &imageIdentifier) {
NSString *imageName = [NSString stringWithUTF8String:imageIdentifier.c_str()];
return [mapView shouldRemoveStyleImage:imageName];
bool MLNMapViewImpl::onCanRemoveUnusedStyleImage(const std::string& imageIdentifier) {
NSString* imageName = [NSString stringWithUTF8String:imageIdentifier.c_str()];
return [mapView shouldRemoveStyleImage:imageName];
}
void MLNMapViewImpl::onRegisterShaders(mbgl::gfx::ShaderRegistry& shaders) {
void MLNMapViewImpl::onRegisterShaders(mbgl::gfx::ShaderRegistry& shaders) {}
void MLNMapViewImpl::onPreCompileShader(mbgl::shaders::BuiltIn shaderID,
mbgl::gfx::Backend::Type backend,
const std::string& defines) {
NSString* definesCopy = [NSString stringWithUTF8String:defines.c_str()];
[mapView shaderWillCompile:static_cast<int>(shaderID)
backend:static_cast<int>(backend)
defines:definesCopy];
}
void MLNMapViewImpl::onPreCompileShader(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) {
NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()];
[mapView shaderWillCompile:static_cast<int>(shaderID) backend:static_cast<int>(backend) defines:definesCopy];
void MLNMapViewImpl::onPostCompileShader(mbgl::shaders::BuiltIn shaderID,
mbgl::gfx::Backend::Type backend,
const std::string& defines) {
NSString* definesCopy = [NSString stringWithUTF8String:defines.c_str()];
[mapView shaderDidCompile:static_cast<int>(shaderID)
backend:static_cast<int>(backend)
defines:definesCopy];
}
void MLNMapViewImpl::onPostCompileShader(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) {
NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()];
[mapView shaderDidCompile:static_cast<int>(shaderID) backend:static_cast<int>(backend) defines:definesCopy];
void MLNMapViewImpl::onShaderCompileFailed(mbgl::shaders::BuiltIn shaderID,
mbgl::gfx::Backend::Type backend,
const std::string& defines) {
NSString* definesCopy = [NSString stringWithUTF8String:defines.c_str()];
[mapView shaderDidFailCompile:static_cast<int>(shaderID)
backend:static_cast<int>(backend)
defines:definesCopy];
}
void MLNMapViewImpl::onShaderCompileFailed(mbgl::shaders::BuiltIn shaderID, mbgl::gfx::Backend::Type backend, const std::string& defines) {
NSString *definesCopy = [NSString stringWithUTF8String:defines.c_str()];
[mapView shaderDidFailCompile:static_cast<int>(shaderID) backend:static_cast<int>(backend) defines:definesCopy];
void MLNMapViewImpl::onGlyphsLoaded(const mbgl::FontStack& fontStack,
const mbgl::GlyphRange& range) {
NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init];
std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) {
[fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]];
});
[mapView glyphsDidLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)];
}
void MLNMapViewImpl::onGlyphsLoaded(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range) {
NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init];
std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) {
[fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]];
});
void MLNMapViewImpl::onGlyphsError(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range,
std::exception_ptr error) {
NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init];
std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) {
[fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]];
});
[mapView glyphsDidLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)];
[mapView glyphsDidError:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)];
}
void MLNMapViewImpl::onGlyphsError(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range, std::exception_ptr error) {
NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init];
std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) {
[fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]];
});
void MLNMapViewImpl::onGlyphsRequested(const mbgl::FontStack& fontStack,
const mbgl::GlyphRange& range) {
NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init];
std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) {
[fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]];
});
[mapView glyphsDidError:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)];
[mapView glyphsWillLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)];
}
void MLNMapViewImpl::onGlyphsRequested(const mbgl::FontStack& fontStack, const mbgl::GlyphRange& range) {
NSMutableArray* fontStackCopy = [[NSMutableArray alloc] init];
std::for_each(fontStack.begin(), fontStack.end(), ^(const std::string& str) {
[fontStackCopy addObject:[NSString stringWithUTF8String:str.c_str()]];
});
[mapView glyphsWillLoad:fontStackCopy range:NSMakeRange(range.first, range.second - range.first)];
}
void MLNMapViewImpl::onTileAction(mbgl::TileOperation operation, const mbgl::OverscaledTileID& tile, const std::string& sourceID) {
[mapView tileDidTriggerAction:MLNTileOperation(static_cast<int>(operation))
x:tile.canonical.x
y:tile.canonical.y
z:tile.canonical.z
wrap:tile.wrap
overscaledZ:tile.overscaledZ
sourceID:[NSString stringWithUTF8String:sourceID.c_str()]];
void MLNMapViewImpl::onTileAction(mbgl::TileOperation operation, const mbgl::OverscaledTileID& tile,
const std::string& sourceID) {
[mapView tileDidTriggerAction:MLNTileOperation(static_cast<int>(operation))
x:tile.canonical.x
y:tile.canonical.y
z:tile.canonical.z
wrap:tile.wrap
overscaledZ:tile.overscaledZ
sourceID:[NSString stringWithUTF8String:sourceID.c_str()]];
}
void MLNMapViewImpl::onSpriteLoaded(const std::optional<mbgl::style::Sprite>& spriteID) {
if (!spriteID.has_value()) {
[mapView spriteDidLoad:nil url:nil];
return;
}
if (!spriteID.has_value()) {
[mapView spriteDidLoad:nil url:nil];
return;
}
[mapView spriteDidLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()]
url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]];
[mapView spriteDidLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()]
url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]];
}
void MLNMapViewImpl::onSpriteError(const std::optional<mbgl::style::Sprite>& spriteID, std::exception_ptr error) {
if (!spriteID.has_value()) {
[mapView spriteDidError:nil url:nil];
return;
}
void MLNMapViewImpl::onSpriteError(const std::optional<mbgl::style::Sprite>& spriteID,
std::exception_ptr error) {
if (!spriteID.has_value()) {
[mapView spriteDidError:nil url:nil];
return;
}
[mapView spriteDidError:[NSString stringWithUTF8String:spriteID.value().id.c_str()]
url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]];
[mapView spriteDidError:[NSString stringWithUTF8String:spriteID.value().id.c_str()]
url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]];
}
void MLNMapViewImpl::onSpriteRequested(const std::optional<mbgl::style::Sprite>& spriteID) {
if (!spriteID.has_value()) {
[mapView spriteWillLoad:nil url:nil];
return;
}
if (!spriteID.has_value()) {
[mapView spriteWillLoad:nil url:nil];
return;
}
[mapView spriteWillLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()]
url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]];
[mapView spriteWillLoad:[NSString stringWithUTF8String:spriteID.value().id.c_str()]
url:[NSString stringWithUTF8String:spriteID.value().spriteURL.c_str()]];
}

View File

@@ -10,34 +10,34 @@
class MLNMapViewMetalImpl final : public MLNMapViewImpl,
public mbgl::mtl::RendererBackend,
public mbgl::gfx::Renderable {
public:
public:
MLNMapViewMetalImpl(MLNMapView*);
~MLNMapViewMetalImpl() override;
public:
public:
void restoreFramebufferBinding();
// Implementation of mbgl::gfx::RendererBackend
public:
public:
mbgl::gfx::Renderable& getDefaultRenderable() override { return *this; }
private:
private:
void activate() override;
void deactivate() override;
// End implementation of mbgl::gfx::RendererBackend
// Implementation of mbgl::gl::RendererBackend
public:
public:
void updateAssumedState() override;
// End implementation of mbgl::gl::Rendererbackend
// Implementation of MLNMapViewImpl
public:
public:
mbgl::gfx::RendererBackend& getRendererBackend() override { return *this; }
mbgl::PremultipliedImage readStillImage() override;
MLNBackendResource* getObject() override;
private:
private:
bool presentsWithTransaction = false;
};

View File

@@ -4,8 +4,8 @@
#import <mbgl/mtl/renderable_resource.hpp>
#import <MetalKit/MetalKit.h>
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import <QuartzCore/CAMetalLayer.h>
#import <Metal/Metal.hpp>
@@ -14,158 +14,156 @@
@end
@implementation MLNMapViewImplDelegate {
MLNMapViewMetalImpl* _impl;
MLNMapViewMetalImpl* _impl;
}
- (instancetype)initWithImpl:(MLNMapViewMetalImpl*)impl {
if (self = [super init]) {
_impl = impl;
}
return self;
if (self = [super init]) {
_impl = impl;
}
return self;
}
- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {}
- (void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size {
}
- (void)drawInMTKView:(MTKView *)view {
_impl->render();
- (void)drawInMTKView:(MTKView*)view {
_impl->render();
}
@end
class MLNMapViewMetalRenderableResource final : public mbgl::mtl::RenderableResource {
public:
MLNMapViewMetalRenderableResource(MLNMapViewMetalImpl& backend_)
: backend(backend_),
delegate([[MLNMapViewImplDelegate alloc] initWithImpl:&backend]) {
MLNMapViewMetalRenderableResource(MLNMapViewMetalImpl& backend_)
: backend(backend_), delegate([[MLNMapViewImplDelegate alloc] initWithImpl:&backend]) {}
void bind() override {
if (!commandQueue) {
commandQueue = [mtlView.device newCommandQueue];
}
void bind() override {
if (!commandQueue) {
commandQueue = [mtlView.device newCommandQueue];
}
if (!commandBuffer) {
commandBuffer = [commandQueue commandBuffer];
commandBufferPtr = NS::RetainPtr((__bridge MTL::CommandBuffer*)commandBuffer);
}
if (!commandBuffer) {
commandBuffer = [commandQueue commandBuffer];
commandBufferPtr = NS::RetainPtr((__bridge MTL::CommandBuffer*)commandBuffer);
}
}
const mbgl::mtl::RendererBackend& getBackend() const override { return backend; }
const mbgl::mtl::RendererBackend& getBackend() const override { return backend; }
const mbgl::mtl::MTLCommandBufferPtr& getCommandBuffer() const override {
return commandBufferPtr;
const mbgl::mtl::MTLCommandBufferPtr& getCommandBuffer() const override {
return commandBufferPtr;
}
virtual mbgl::mtl::MTLBlitPassDescriptorPtr getUploadPassDescriptor() const override {
// Create from render pass descriptor?
return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init());
}
const mbgl::mtl::MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override {
if (!cachedRenderPassDescriptor) {
auto* mtlDesc = mtlView.currentRenderPassDescriptor;
cachedRenderPassDescriptor = NS::RetainPtr((__bridge MTL::RenderPassDescriptor*)mtlDesc);
}
return cachedRenderPassDescriptor;
}
virtual mbgl::mtl::MTLBlitPassDescriptorPtr getUploadPassDescriptor() const override {
// Create from render pass descriptor?
return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init());
}
void swap() override {
id<CAMetalDrawable> currentDrawable = [mtlView currentDrawable];
[commandBuffer presentDrawable:currentDrawable];
[commandBuffer commit];
const mbgl::mtl::MTLRenderPassDescriptorPtr& getRenderPassDescriptor() const override {
if (!cachedRenderPassDescriptor) {
auto* mtlDesc = mtlView.currentRenderPassDescriptor;
cachedRenderPassDescriptor = NS::RetainPtr((__bridge MTL::RenderPassDescriptor*)mtlDesc);
}
return cachedRenderPassDescriptor;
}
// Un-comment for synchronous, which can help troubleshoot rendering problems,
// particularly those related to resource tracking and multiple queued buffers.
//[commandBuffer waitUntilCompleted];
void swap() override {
id<CAMetalDrawable> currentDrawable = [mtlView currentDrawable];
[commandBuffer presentDrawable:currentDrawable];
[commandBuffer commit];
commandBuffer = nil;
commandBufferPtr.reset();
// Un-comment for synchronous, which can help troubleshoot rendering problems,
// particularly those related to resource tracking and multiple queued buffers.
//[commandBuffer waitUntilCompleted];
cachedRenderPassDescriptor.reset();
}
commandBuffer = nil;
commandBufferPtr.reset();
cachedRenderPassDescriptor.reset();
}
mbgl::Size framebufferSize() {
assert(mtlView);
return { static_cast<uint32_t>(mtlView.drawableSize.width),
static_cast<uint32_t>(mtlView.drawableSize.height) };
}
mbgl::Size framebufferSize() {
assert(mtlView);
return {static_cast<uint32_t>(mtlView.drawableSize.width),
static_cast<uint32_t>(mtlView.drawableSize.height)};
}
private:
MLNMapViewMetalImpl& backend;
mbgl::mtl::MTLCommandBufferPtr commandBufferPtr;
mutable mbgl::mtl::MTLRenderPassDescriptorPtr cachedRenderPassDescriptor;
MLNMapViewMetalImpl& backend;
mbgl::mtl::MTLCommandBufferPtr commandBufferPtr;
mutable mbgl::mtl::MTLRenderPassDescriptorPtr cachedRenderPassDescriptor;
public:
MLNMapViewImplDelegate* delegate = nil;
MTKView *mtlView = nil;
id <MTLCommandBuffer> commandBuffer;
id <MTLCommandQueue> commandQueue;
MLNMapViewImplDelegate* delegate = nil;
MTKView* mtlView = nil;
id<MTLCommandBuffer> commandBuffer;
id<MTLCommandQueue> commandQueue;
// We count how often the context was activated/deactivated so that we can truly deactivate it
// after the activation count drops to 0.
NSUInteger activationCount = 0;
// We count how often the context was activated/deactivated so that we can truly deactivate it
// after the activation count drops to 0.
NSUInteger activationCount = 0;
};
MLNMapViewMetalImpl::MLNMapViewMetalImpl(MLNMapView* nativeView_)
: MLNMapViewImpl(nativeView_),
mbgl::mtl::RendererBackend(mbgl::gfx::ContextMode::Unique),
mbgl::gfx::Renderable({ 0, 0 }, std::make_unique<MLNMapViewMetalRenderableResource>(*this)) {
mbgl::gfx::Renderable({0, 0}, std::make_unique<MLNMapViewMetalRenderableResource>(*this)) {
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
if (resource.mtlView) {
return;
}
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
if (resource.mtlView) {
return;
}
id<MTLDevice> device = (__bridge id<MTLDevice>)resource.getBackend().getDevice().get();
id<MTLDevice> device = (__bridge id<MTLDevice>)resource.getBackend().getDevice().get();
resource.mtlView = [[MTKView alloc] initWithFrame:mapView.bounds device:device];
resource.mtlView.delegate = resource.delegate;
resource.mtlView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
resource.mtlView.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
resource.mtlView.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
resource.mtlView.layer.opaque = mapView.opaque;
resource.mtlView.enableSetNeedsDisplay = NO;
CAMetalLayer* metalLayer = MLN_OBJC_DYNAMIC_CAST(resource.mtlView.layer, CAMetalLayer);
metalLayer.presentsWithTransaction = presentsWithTransaction;
resource.mtlView = [[MTKView alloc] initWithFrame:mapView.bounds device:device];
resource.mtlView.delegate = resource.delegate;
resource.mtlView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
resource.mtlView.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
resource.mtlView.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
resource.mtlView.layer.opaque = mapView.opaque;
resource.mtlView.enableSetNeedsDisplay = NO;
CAMetalLayer* metalLayer = MLN_OBJC_DYNAMIC_CAST(resource.mtlView.layer, CAMetalLayer);
metalLayer.presentsWithTransaction = presentsWithTransaction;
[mapView addSubview:resource.mtlView positioned:NSWindowBelow relativeTo:nil];
[mapView addSubview:resource.mtlView positioned:NSWindowBelow relativeTo:nil];
}
MLNMapViewMetalImpl::~MLNMapViewMetalImpl() = default;
void MLNMapViewMetalImpl::activate() {
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
if (resource.activationCount++) {
return;
}
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
if (resource.activationCount++) {
return;
}
}
void MLNMapViewMetalImpl::deactivate() {
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
if (--resource.activationCount) {
return;
}
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
if (--resource.activationCount) {
return;
}
}
/// This function is called before we start rendering, when iOS invokes our rendering method.
/// iOS already sets the correct framebuffer and viewport for us, so we need to update the
/// context state with the anticipated values.
void MLNMapViewMetalImpl::updateAssumedState() {
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
assumeFramebufferBinding(ImplicitFramebufferBinding);
assumeViewport(0, 0, resource.framebufferSize());
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
assumeFramebufferBinding(ImplicitFramebufferBinding);
assumeViewport(0, 0, resource.framebufferSize());
}
mbgl::PremultipliedImage MLNMapViewMetalImpl::readStillImage() {
// return readFramebuffer(mapView.framebufferSize); // TODO: RendererBackend::readFramebuffer
return {};
// return readFramebuffer(mapView.framebufferSize); // TODO: RendererBackend::readFramebuffer
return {};
}
MLNBackendResource* MLNMapViewMetalImpl::getObject() {
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
auto& resource = getResource<MLNMapViewMetalRenderableResource>();
return [[MLNBackendResource alloc] initWithMTKView:resource.mtlView
device:resource.mtlView.device
renderPassDescriptor:resource.mtlView.currentRenderPassDescriptor
commandBuffer:resource.commandBuffer];
return [[MLNBackendResource alloc] initWithMTKView:resource.mtlView
device:resource.mtlView.device
renderPassDescriptor:resource.mtlView.currentRenderPassDescriptor
commandBuffer:resource.commandBuffer];
}

View File

@@ -7,22 +7,19 @@
class MLNMapViewOpenGLRenderableResource final : public mbgl::gl::RenderableResource {
public:
MLNMapViewOpenGLRenderableResource(MLNMapViewOpenGLImpl& backend_) : backend(backend_) {
}
MLNMapViewOpenGLRenderableResource(MLNMapViewOpenGLImpl& backend_) : backend(backend_) {}
void bind() override {
backend.restoreFramebufferBinding();
}
void bind() override { backend.restoreFramebufferBinding(); }
private:
MLNMapViewOpenGLImpl& backend;
MLNMapViewOpenGLImpl& backend;
public:
// The current framebuffer of the NSOpenGLLayer we are painting to.
GLint fbo = 0;
// The current framebuffer of the NSOpenGLLayer we are painting to.
GLint fbo = 0;
// The reference counted count of activation calls
NSUInteger activationCount = 0;
// The reference counted count of activation calls
NSUInteger activationCount = 0;
};
MLNMapViewOpenGLImpl::MLNMapViewOpenGLImpl(MLNMapView* nativeView_)
@@ -30,60 +27,58 @@ MLNMapViewOpenGLImpl::MLNMapViewOpenGLImpl(MLNMapView* nativeView_)
mbgl::gl::RendererBackend(mbgl::gfx::ContextMode::Unique),
mbgl::gfx::Renderable(mapView.framebufferSize,
std::make_unique<MLNMapViewOpenGLRenderableResource>(*this)) {
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
// we can’t display a map, so don’t even bother to have a map layer.
mapView.layer =
mapView.isTargetingInterfaceBuilder ? [CALayer layer] : [MLNOpenGLLayer layer];
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
// we can’t display a map, so don’t even bother to have a map layer.
mapView.layer = mapView.isTargetingInterfaceBuilder ? [CALayer layer] : [MLNOpenGLLayer layer];
}
mbgl::gl::ProcAddress MLNMapViewOpenGLImpl::getExtensionFunctionPointer(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
}
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
}
return reinterpret_cast<mbgl::gl::ProcAddress>(CFBundleGetFunctionPointerForName(
framework, (__bridge CFStringRef)[NSString stringWithUTF8String:name]));
return reinterpret_cast<mbgl::gl::ProcAddress>(CFBundleGetFunctionPointerForName(
framework, (__bridge CFStringRef)[NSString stringWithUTF8String:name]));
}
void MLNMapViewOpenGLImpl::activate() {
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
if (resource.activationCount++) {
return;
}
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
if (resource.activationCount++) {
return;
}
MLNOpenGLLayer* layer = (MLNOpenGLLayer*)mapView.layer;
[layer.openGLContext makeCurrentContext];
MLNOpenGLLayer* layer = (MLNOpenGLLayer*)mapView.layer;
[layer.openGLContext makeCurrentContext];
}
void MLNMapViewOpenGLImpl::deactivate() {
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
if (--resource.activationCount) {
return;
}
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
if (--resource.activationCount) {
return;
}
[NSOpenGLContext clearCurrentContext];
[NSOpenGLContext clearCurrentContext];
}
void MLNMapViewOpenGLImpl::updateAssumedState() {
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &resource.fbo);
assumeFramebufferBinding(resource.fbo);
assumeViewport(0, 0, mapView.framebufferSize);
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &resource.fbo);
assumeFramebufferBinding(resource.fbo);
assumeViewport(0, 0, mapView.framebufferSize);
}
void MLNMapViewOpenGLImpl::restoreFramebufferBinding() {
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
setFramebufferBinding(resource.fbo);
setViewport(0, 0, mapView.framebufferSize);
auto& resource = getResource<MLNMapViewOpenGLRenderableResource>();
setFramebufferBinding(resource.fbo);
setViewport(0, 0, mapView.framebufferSize);
}
mbgl::PremultipliedImage MLNMapViewOpenGLImpl::readStillImage() {
return readFramebuffer(mapView.framebufferSize);
return readFramebuffer(mapView.framebufferSize);
}
CGLContextObj MLNMapViewOpenGLImpl::getCGLContextObj() {
MLNOpenGLLayer* layer = (MLNOpenGLLayer*)mapView.layer;
return layer.openGLContext.CGLContextObj;
MLNOpenGLLayer* layer = (MLNOpenGLLayer*)mapView.layer;
return layer.openGLContext.CGLContextObj;
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,11 @@
#import "MLNMapView_Private.h"
@implementation MLNOpenGLLayer {
NSOpenGLContext *_context;
NSOpenGLContext *_context;
}
- (MLNMapView *)mapView {
return (MLNMapView *)super.view;
return (MLNMapView *)super.view;
}
// - (BOOL)isAsynchronous {
@@ -15,44 +15,56 @@
// }
- (BOOL)needsDisplayOnBoundsChange {
return YES;
return YES;
}
- (CGRect)frame {
return self.view.bounds;
return self.view.bounds;
}
- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat {
if (!_context) {
_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
}
return _context;
if (!_context) {
_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
}
return _context;
}
- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask {
NSOpenGLPixelFormatAttribute pfas[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
NSOpenGLPFAAccelerated,
NSOpenGLPFAClosestPolicy,
NSOpenGLPFAAccumSize, 32,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 16,
NSOpenGLPFAStencilSize, 8,
NSOpenGLPFAScreenMask, mask,
NSOpenGLPFAAllowOfflineRenderers, // Allows using the integrated GPU
0
};
return [[NSOpenGLPixelFormat alloc] initWithAttributes:pfas];
NSOpenGLPixelFormatAttribute pfas[] = {
NSOpenGLPFAOpenGLProfile,
NSOpenGLProfileVersionLegacy,
NSOpenGLPFAAccelerated,
NSOpenGLPFAClosestPolicy,
NSOpenGLPFAAccumSize,
32,
NSOpenGLPFAColorSize,
24,
NSOpenGLPFAAlphaSize,
8,
NSOpenGLPFADepthSize,
16,
NSOpenGLPFAStencilSize,
8,
NSOpenGLPFAScreenMask,
mask,
NSOpenGLPFAAllowOfflineRenderers, // Allows using the integrated GPU
0};
return [[NSOpenGLPixelFormat alloc] initWithAttributes:pfas];
}
- (BOOL)canDrawInOpenGLContext:(__unused NSOpenGLContext *)context pixelFormat:(__unused NSOpenGLPixelFormat *)pixelFormat forLayerTime:(__unused CFTimeInterval)t displayTime:(__unused const CVTimeStamp *)ts {
return !self.mapView.dormant;
- (BOOL)canDrawInOpenGLContext:(__unused NSOpenGLContext *)context
pixelFormat:(__unused NSOpenGLPixelFormat *)pixelFormat
forLayerTime:(__unused CFTimeInterval)t
displayTime:(__unused const CVTimeStamp *)ts {
return !self.mapView.dormant;
}
- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat forLayerTime:(CFTimeInterval)t displayTime:(const CVTimeStamp *)ts {
[self.mapView renderSync];
[super drawInOpenGLContext:context pixelFormat:pixelFormat forLayerTime:t displayTime:ts];
- (void)drawInOpenGLContext:(NSOpenGLContext *)context
pixelFormat:(NSOpenGLPixelFormat *)pixelFormat
forLayerTime:(CFTimeInterval)t
displayTime:(const CVTimeStamp *)ts {
[self.mapView renderSync];
[super drawInOpenGLContext:context pixelFormat:pixelFormat forLayerTime:t displayTime:ts];
}
@end

View File

@@ -3,68 +3,70 @@
@implementation NSColor (MLNAdditions)
- (mbgl::Color)mgl_color {
CGFloat r, g, b, a;
CGFloat r, g, b, a;
// The MapLibre Style Spec does not specify a color space, but it is
// assumed to be sRGB for consistency with CSS.
NSColor *srgbColor = self;
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
srgbColor = [srgbColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
} else {
srgbColor = [srgbColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
}
[srgbColor getRed:&r green:&g blue:&b alpha:&a];
// The MapLibre Style Spec does not specify a color space, but it is
// assumed to be sRGB for consistency with CSS.
NSColor *srgbColor = self;
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
srgbColor = [srgbColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
} else {
srgbColor = [srgbColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
}
[srgbColor getRed:&r green:&g blue:&b alpha:&a];
// NSColor provides non-premultiplied color components, so we have to premultiply each
// color component with the alpha value to transform it into a valid
// mbgl::Color which expects premultiplied color components.
return { static_cast<float>(r*a), static_cast<float>(g*a), static_cast<float>(b*a), static_cast<float>(a) };
// NSColor provides non-premultiplied color components, so we have to premultiply each
// color component with the alpha value to transform it into a valid
// mbgl::Color which expects premultiplied color components.
return {static_cast<float>(r * a), static_cast<float>(g * a), static_cast<float>(b * a),
static_cast<float>(a)};
}
- (mbgl::Color)mgl_colorForPremultipliedValue {
CGFloat r, g, b, a;
CGFloat r, g, b, a;
// The MapLibre Style Spec does not specify a color space, but it is
// assumed to be sRGB for consistency with CSS.
NSColor *srgbColor = self;
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
srgbColor = [srgbColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
} else {
srgbColor = [srgbColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
}
[srgbColor getRed:&r green:&g blue:&b alpha:&a];
// The MapLibre Style Spec does not specify a color space, but it is
// assumed to be sRGB for consistency with CSS.
NSColor *srgbColor = self;
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
srgbColor = [srgbColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
} else {
srgbColor = [srgbColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
}
[srgbColor getRed:&r green:&g blue:&b alpha:&a];
return { static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a) };
return {static_cast<float>(r), static_cast<float>(g), static_cast<float>(b),
static_cast<float>(a)};
}
+ (NSColor *)mgl_colorWithColor:(mbgl::Color)color {
// If there is no alpha value, return original color values.
if (color.a == 0.0f) {
// macOS 10.12 Sierra and below uses calibrated RGB by default.
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
return [NSColor colorWithCalibratedRed:color.r green:color.g blue:color.b alpha:color.a];
} else {
return [NSColor colorWithRed:color.r green:color.g blue:color.b alpha:color.a];
}
}
// mbgl::Color provides premultiplied color components, so we have to convert color
// components to non-premultiplied values to return a valid NSColor object.
float red = static_cast<float>((color.r / color.a));
float green = static_cast<float>((color.g / color.a));
float blue = static_cast<float>((color.b / color.a));
// If there is no alpha value, return original color values.
if (color.a == 0.0f) {
// macOS 10.12 Sierra and below uses calibrated RGB by default.
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
return [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:color.a];
return [NSColor colorWithCalibratedRed:color.r green:color.g blue:color.b alpha:color.a];
} else {
return [NSColor colorWithRed:red green:green blue:blue alpha:color.a];
return [NSColor colorWithRed:color.r green:color.g blue:color.b alpha:color.a];
}
}
// mbgl::Color provides premultiplied color components, so we have to convert color
// components to non-premultiplied values to return a valid NSColor object.
float red = static_cast<float>((color.r / color.a));
float green = static_cast<float>((color.g / color.a));
float blue = static_cast<float>((color.b / color.a));
// macOS 10.12 Sierra and below uses calibrated RGB by default.
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
return [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:color.a];
} else {
return [NSColor colorWithRed:red green:green blue:blue alpha:color.a];
}
}
- (mbgl::style::PropertyValue<mbgl::Color>)mgl_colorPropertyValue {
mbgl::Color color = self.mgl_color;
return {{ color.r, color.g, color.b, color.a }};
mbgl::Color color = self.mgl_color;
return {{color.r, color.g, color.b, color.a}};
}
@end
@@ -72,69 +74,68 @@
@implementation NSExpression (MLNColorAdditions)
+ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components {
if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
return [NSExpression expressionForConstantValue:color];
}
if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
return [NSExpression expressionForConstantValue:color];
}
NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
NSExpression *alpha = [NSExpression expressionForConstantValue:@1.0];
return [NSExpression expressionForFunction:color
selectorName:@"colorWithRed:green:blue:alpha:"
arguments:[components arrayByAddingObject:alpha]];
NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
NSExpression *alpha = [NSExpression expressionForConstantValue:@1.0];
return [NSExpression expressionForFunction:color
selectorName:@"colorWithRed:green:blue:alpha:"
arguments:[components arrayByAddingObject:alpha]];
}
+ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components {
if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
return [NSExpression expressionForConstantValue:color];
}
if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
return [NSExpression expressionForConstantValue:color];
}
NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
return [NSExpression expressionForFunction:color
selectorName:@"colorWithRed:green:blue:alpha:"
arguments:components];
NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
return [NSExpression expressionForFunction:color
selectorName:@"colorWithRed:green:blue:alpha:"
arguments:components];
}
/**
Returns a color object corresponding to the given component expressions.
*/
+ (NSColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)componentExpressions {
// Map the component expressions to constant components. If any component is
// a non-constant expression, the components cannot be converted into a
// constant color value.
std::vector<CGFloat> components;
for (NSExpression *componentExpression in componentExpressions) {
if (componentExpression.expressionType != NSConstantValueExpressionType) {
return nil;
}
NSNumber *component = (NSNumber *)componentExpression.constantValue;
if (![component isKindOfClass:[NSNumber class]]) {
return nil;
}
components.push_back(component.doubleValue / 255.0);
// Map the component expressions to constant components. If any component is
// a non-constant expression, the components cannot be converted into a
// constant color value.
std::vector<CGFloat> components;
for (NSExpression *componentExpression in componentExpressions) {
if (componentExpression.expressionType != NSConstantValueExpressionType) {
return nil;
}
if (components.size() < 4) {
components.push_back(1.0);
} else {
// Alpha
components.back() *= 255.0;
NSNumber *component = (NSNumber *)componentExpression.constantValue;
if (![component isKindOfClass:[NSNumber class]]) {
return nil;
}
components.push_back(component.doubleValue / 255.0);
}
// macOS 10.12 Sierra and below uses calibrated RGB by default.
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
return [NSColor colorWithCalibratedRed:components[0]
green:components[1]
blue:components[2]
alpha:components[3]];
}
// The MapLibre Style Spec does not specify a color space, but it is
// assumed to be sRGB for consistency with CSS.
return [NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace]
components:&components[0]
count:components.size()];
if (components.size() < 4) {
components.push_back(1.0);
} else {
// Alpha
components.back() *= 255.0;
}
// macOS 10.12 Sierra and below uses calibrated RGB by default.
if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
return [NSColor colorWithCalibratedRed:components[0]
green:components[1]
blue:components[2]
alpha:components[3]];
}
// The MapLibre Style Spec does not specify a color space, but it is
// assumed to be sRGB for consistency with CSS.
return [NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace]
components:&components[0]
count:components.size()];
}
@end

View File

@@ -3,87 +3,86 @@
#include <mbgl/util/image+MLNAdditions.hpp>
BOOL MLNEdgeInsetsIsZero(NSEdgeInsets edgeInsets) {
return edgeInsets.left == 0 && edgeInsets.top == 0 && edgeInsets.right == 0 && edgeInsets.bottom == 0;
return edgeInsets.left == 0 && edgeInsets.top == 0 && edgeInsets.right == 0 &&
edgeInsets.bottom == 0;
}
@implementation NSImage (MLNAdditions)
- (nullable instancetype)initWithMLNPremultipliedImage:(mbgl::PremultipliedImage&&)src {
CGImageRef image = CGImageCreateWithMLNPremultipliedImage(std::move(src));
if (!image) {
return nil;
}
- (nullable instancetype)initWithMLNPremultipliedImage:(mbgl::PremultipliedImage &&)src {
CGImageRef image = CGImageCreateWithMLNPremultipliedImage(std::move(src));
if (!image) {
return nil;
}
self = [self initWithCGImage:image size:NSZeroSize];
CGImageRelease(image);
return self;
self = [self initWithCGImage:image size:NSZeroSize];
CGImageRelease(image);
return self;
}
- (nullable instancetype)initWithMLNStyleImage:(const mbgl::style::Image &)styleImage {
CGImageRef image = CGImageCreateWithMLNPremultipliedImage(styleImage.getImage().clone());
if (!image) {
return nil;
}
CGImageRef image = CGImageCreateWithMLNPremultipliedImage(styleImage.getImage().clone());
if (!image) {
return nil;
}
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithCGImage:image];
CGImageRelease(image);
CGFloat scale = styleImage.getPixelRatio();
NSSize size = NSMakeSize(styleImage.getImage().size.width / scale,
styleImage.getImage().size.height / scale);
if (self = [self initWithSize:size]) {
[self addRepresentation:rep];
[self setTemplate:styleImage.isSdf()];
if (!styleImage.getStretchX().empty() || !styleImage.getStretchY().empty()) {
self.resizingMode = NSImageResizingModeStretch;
} else {
self.resizingMode = NSImageResizingModeTile;
}
if (auto content = styleImage.getContent()) {
self.capInsets = NSEdgeInsetsMake(content->top / scale,
content->left / scale,
size.height - content->bottom / scale,
size.width - content->right / scale);
}
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithCGImage:image];
CGImageRelease(image);
CGFloat scale = styleImage.getPixelRatio();
NSSize size = NSMakeSize(styleImage.getImage().size.width / scale,
styleImage.getImage().size.height / scale);
if (self = [self initWithSize:size]) {
[self addRepresentation:rep];
[self setTemplate:styleImage.isSdf()];
if (!styleImage.getStretchX().empty() || !styleImage.getStretchY().empty()) {
self.resizingMode = NSImageResizingModeStretch;
} else {
self.resizingMode = NSImageResizingModeTile;
}
return self;
if (auto content = styleImage.getContent()) {
self.capInsets = NSEdgeInsetsMake(content->top / scale, content->left / scale,
size.height - content->bottom / scale,
size.width - content->right / scale);
}
}
return self;
}
- (std::unique_ptr<mbgl::style::Image>)mgl_styleImageWithIdentifier:(NSString *)identifier {
mbgl::PremultipliedImage cPremultipliedImage = self.mgl_premultipliedImage;
auto imageWidth = cPremultipliedImage.size.width;
mbgl::PremultipliedImage cPremultipliedImage = self.mgl_premultipliedImage;
auto imageWidth = cPremultipliedImage.size.width;
float scale = static_cast<float>(imageWidth) / self.size.width;
mbgl::style::ImageStretches stretchX, stretchY;
if (self.resizingMode == NSImageResizingModeStretch) {
stretchX.push_back({
self.capInsets.left * scale, (self.size.width - self.capInsets.right) * scale,
});
stretchY.push_back({
self.capInsets.top * scale, (self.size.height - self.capInsets.bottom) * scale,
});
}
float scale = static_cast<float>(imageWidth) / self.size.width;
mbgl::style::ImageStretches stretchX, stretchY;
if (self.resizingMode == NSImageResizingModeStretch) {
stretchX.push_back({
self.capInsets.left * scale,
(self.size.width - self.capInsets.right) * scale,
});
stretchY.push_back({
self.capInsets.top * scale,
(self.size.height - self.capInsets.bottom) * scale,
});
}
std::optional<mbgl::style::ImageContent> imageContent;
if (!MLNEdgeInsetsIsZero(self.capInsets)) {
imageContent = (mbgl::style::ImageContent){
.left = static_cast<float>(self.capInsets.left * scale),
.top = static_cast<float>(self.capInsets.top * scale),
.right = static_cast<float>((self.size.width - self.capInsets.right) * scale),
.bottom = static_cast<float>((self.size.height - self.capInsets.bottom) * scale),
};
}
std::optional<mbgl::style::ImageContent> imageContent;
if (!MLNEdgeInsetsIsZero(self.capInsets)) {
imageContent = (mbgl::style::ImageContent){
.left = static_cast<float>(self.capInsets.left * scale),
.top = static_cast<float>(self.capInsets.top * scale),
.right = static_cast<float>((self.size.width - self.capInsets.right) * scale),
.bottom = static_cast<float>((self.size.height - self.capInsets.bottom) * scale),
};
}
return std::make_unique<mbgl::style::Image>([identifier UTF8String],
std::move(cPremultipliedImage),
scale,
[self isTemplate],
stretchX, stretchY,
imageContent);
return std::make_unique<mbgl::style::Image>([identifier UTF8String],
std::move(cPremultipliedImage), scale,
[self isTemplate], stretchX, stretchY, imageContent);
}
- (mbgl::PremultipliedImage)mgl_premultipliedImage {
CGImageRef ref = [self CGImageForProposedRect:nullptr context:nullptr hints:nullptr];
return MLNPremultipliedImageFromCGImage(ref);
CGImageRef ref = [self CGImageForProposedRect:nullptr context:nullptr hints:nullptr];
return MLNPremultipliedImageFromCGImage(ref);
}
@end