ios: apply clang-format to Objective-C++ sources (#4060)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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()]];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user