Skip to content

Commit 81ec588

Browse files
lenaicNick
andcommitted
[Fabric] Add support for image content mode and tint features (microsoft#1828)
* Add RCTUIImageView to RCTUIKit to support iOS features on macOS. * Add support for tint and resize mode to Image on Fabric. * Clean up logging and add macOS tag. * Fix code style to match the style guide. --------- Co-authored-by: Nick <lefever@meta.com>
1 parent 0e9ad41 commit 81ec588

File tree

4 files changed

+102
-10
lines changed

4 files changed

+102
-10
lines changed

Libraries/Image/RCTUIImageViewAnimated.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,5 @@
88
#import <React/RCTAnimatedImage.h>
99
#import <React/RCTDefines.h>
1010

11-
#if !TARGET_OS_OSX // [macOS]
12-
@interface RCTUIImageViewAnimated : UIImageView
13-
#else // [macOS
14-
@interface RCTUIImageViewAnimated : NSImageView
15-
#endif // macOS]
16-
11+
@interface RCTUIImageViewAnimated : RCTUIImageView // [macOS]
1712
@end

React/Base/RCTUIKit.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,3 +581,17 @@ typedef UITouch RCTUITouch;
581581
@interface RCTUITouch : NSEvent
582582
@end
583583
#endif
584+
585+
// RCTUIImageView
586+
587+
#if !TARGET_OS_OSX
588+
typedef UIImageView RCTUIImageView;
589+
#else
590+
@interface RCTUIImageView : NSImageView
591+
NS_ASSUME_NONNULL_BEGIN
592+
@property (nonatomic, assign) BOOL clipsToBounds;
593+
@property (nonatomic, strong) RCTUIColor *tintColor;
594+
@property (nonatomic, assign) UIViewContentMode contentMode;
595+
NS_ASSUME_NONNULL_END
596+
@end
597+
#endif

React/Base/macOS/RCTUIKit.m

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,4 +761,86 @@ - (void)setHidden:(BOOL)hidden
761761

762762
@end
763763

764+
// RCTUIImageView
765+
766+
@implementation RCTUIImageView
767+
768+
- (instancetype)initWithFrame:(CGRect)frame
769+
{
770+
if (self = [super initWithFrame:frame]) {
771+
[self setLayer:[[CALayer alloc] init]];
772+
[self setWantsLayer:YES];
773+
}
774+
775+
return self;
776+
}
777+
778+
- (BOOL)clipsToBounds
779+
{
780+
return [[self layer] masksToBounds];
781+
}
782+
783+
- (void)setClipsToBounds:(BOOL)clipsToBounds
784+
{
785+
[[self layer] setMasksToBounds:clipsToBounds];
786+
}
787+
788+
- (void)setContentMode:(UIViewContentMode)contentMode
789+
{
790+
_contentMode = contentMode;
791+
792+
CALayer *layer = [self layer];
793+
switch (contentMode) {
794+
case UIViewContentModeScaleAspectFill:
795+
[layer setContentsGravity:kCAGravityResizeAspectFill];
796+
break;
797+
798+
case UIViewContentModeScaleAspectFit:
799+
[layer setContentsGravity:kCAGravityResizeAspect];
800+
break;
801+
802+
case UIViewContentModeScaleToFill:
803+
[layer setContentsGravity:kCAGravityResize];
804+
break;
805+
806+
case UIViewContentModeCenter:
807+
[layer setContentsGravity:kCAGravityCenter];
808+
break;
809+
810+
default:
811+
break;
812+
}
813+
}
814+
815+
- (UIImage *)image
816+
{
817+
return [[self layer] contents];
818+
}
819+
820+
- (void)setImage:(UIImage *)image
821+
{
822+
CALayer *layer = [self layer];
823+
824+
if ([layer contents] != image || [layer backgroundColor] != nil) {
825+
if (_tintColor != nil) {
826+
image = [image copy];
827+
[image lockFocus];
828+
[_tintColor set];
829+
NSRect imageRect = { NSZeroPoint, image.size };
830+
NSRectFillUsingOperation(imageRect, NSCompositingOperationSourceIn);
831+
[image unlockFocus];
832+
}
833+
834+
if (image != nil && [image resizingMode] == NSImageResizingModeTile) {
835+
[layer setContents:nil];
836+
[layer setBackgroundColor:[NSColor colorWithPatternImage:image].CGColor];
837+
} else {
838+
[layer setContents:image];
839+
[layer setBackgroundColor:nil];
840+
}
841+
}
842+
}
843+
844+
@end
845+
764846
#endif

React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@ - (instancetype)initWithFrame:(CGRect)frame
3131
_props = defaultProps;
3232

3333
_imageView = [RCTUIImageViewAnimated new];
34-
#if !TARGET_OS_OSX // [macOS]
3534
_imageView.clipsToBounds = YES;
3635
_imageView.contentMode = RCTContentModeFromImageResizeMode(defaultProps->resizeMode);
37-
#endif // [macOS]
3836
_imageView.layer.minificationFilter = kCAFilterTrilinear;
3937
_imageView.layer.magnificationFilter = kCAFilterTrilinear;
4038

@@ -58,7 +56,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
5856
auto const &oldImageProps = *std::static_pointer_cast<ImageProps const>(_props);
5957
auto const &newImageProps = *std::static_pointer_cast<ImageProps const>(props);
6058

61-
#if !TARGET_OS_OSX // [macOS]
6259
// `resizeMode`
6360
if (oldImageProps.resizeMode != newImageProps.resizeMode) {
6461
_imageView.contentMode = RCTContentModeFromImageResizeMode(newImageProps.resizeMode);
@@ -68,7 +65,6 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
6865
if (oldImageProps.tintColor != newImageProps.tintColor) {
6966
_imageView.tintColor = RCTUIColorFromSharedColor(newImageProps.tintColor);
7067
}
71-
#endif // [macOS]
7268

7369
[super updateProps:props oldProps:oldProps];
7470
}
@@ -149,6 +145,11 @@ - (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(voi
149145
image = [image resizableImageWithCapInsets:RCTUIEdgeInsetsFromEdgeInsets(imageProps.capInsets)
150146
resizingMode:UIImageResizingModeStretch];
151147
}
148+
#else
149+
if (imageProps.resizeMode == ImageResizeMode::Repeat) {
150+
image.capInsets = RCTUIEdgeInsetsFromEdgeInsets(imageProps.capInsets);
151+
image.resizingMode = NSImageResizingModeTile;
152+
}
152153
#endif // [macOS]
153154

154155
if (imageProps.blurRadius > __FLT_EPSILON__) {

0 commit comments

Comments
 (0)