Skip to content

Commit f835b82

Browse files
joevilchesfacebook-github-bot
authored andcommitted
Ensure filterLayer, backgroundImageLayer, and backgroundColorLayer are the same size/shape as the owning View (#49278)
Summary: Pull Request resolved: #49278 The previous diff (#49272) fixed an issue where we used frame to get the size of a sublayer. This is problematic in that it scales things twice if a scaling transform is applied. I looked to see where else we do this and we have this problem (sometimes) with background color and filter. To fix this in the general case I created a helper to size a layer to the same shape as the View's layer - so using bounds for the size, (0,0) for position on the frame, and cornerRadius/mask for border radius considerations. The only 3 layers that should be the exact same size are backgroundColorLayer, backgroundImageLayer, and filterLayer Changelog: [iOS] [Fixed] - Fix cases where background color, filter, and background image were sized incorrectly if there was a scaling transform Reviewed By: jorge-cab Differential Revision: D69321790 fbshipit-source-id: 70b5d18fa01967896b1bfffdb5684c2c907f3549
1 parent acaf94d commit f835b82

File tree

1 file changed

+23
-39
lines changed

1 file changed

+23
-39
lines changed

packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -883,25 +883,11 @@ - (void)invalidateLayer
883883
layer.backgroundColor = nil;
884884
if (!_backgroundColorLayer) {
885885
_backgroundColorLayer = [CALayer layer];
886-
_backgroundColorLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
887886
_backgroundColorLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
888887
[self.layer addSublayer:_backgroundColorLayer];
889888
}
890-
889+
[self shapeLayerToMatchView:_backgroundColorLayer borderMetrics:borderMetrics];
891890
_backgroundColorLayer.backgroundColor = backgroundColor.CGColor;
892-
if (borderMetrics.borderRadii.isUniform()) {
893-
_backgroundColorLayer.mask = nil;
894-
_backgroundColorLayer.cornerRadius = borderMetrics.borderRadii.topLeft.horizontal;
895-
_backgroundColorLayer.cornerCurve = CornerCurveFromBorderCurve(borderMetrics.borderCurves.topLeft);
896-
} else {
897-
CAShapeLayer *maskLayer =
898-
[self createMaskLayer:self.bounds
899-
cornerInsets:RCTGetCornerInsets(
900-
RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero)];
901-
_backgroundColorLayer.mask = maskLayer;
902-
_backgroundColorLayer.cornerRadius = 0;
903-
}
904-
905891
[_backgroundColorLayer removeAllAnimations];
906892
}
907893

@@ -987,20 +973,13 @@ - (void)invalidateLayer
987973
}
988974

989975
_filterLayer = [CALayer layer];
990-
_filterLayer.frame = CGRectMake(0, 0, layer.frame.size.width, layer.frame.size.height);
976+
[self shapeLayerToMatchView:_filterLayer borderMetrics:borderMetrics];
991977
_filterLayer.compositingFilter = @"multiplyBlendMode";
992978
_filterLayer.backgroundColor = [UIColor colorWithRed:multiplicativeBrightness
993979
green:multiplicativeBrightness
994980
blue:multiplicativeBrightness
995981
alpha:self.layer.opacity]
996982
.CGColor;
997-
if (borderMetrics.borderRadii.isUniform()) {
998-
_filterLayer.cornerRadius = borderMetrics.borderRadii.topLeft.horizontal;
999-
} else {
1000-
RCTCornerInsets cornerInsets =
1001-
RCTGetCornerInsets(RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero);
1002-
_filterLayer.mask = [self createMaskLayer:self.bounds cornerInsets:cornerInsets];
1003-
}
1004983
// So that this layer is always above any potential sublayers this view may
1005984
// add
1006985
_filterLayer.zPosition = CGFLOAT_MAX;
@@ -1016,24 +995,9 @@ - (void)invalidateLayer
1016995
const auto &linearGradient = std::get<LinearGradient>(backgroundImage);
1017996
CALayer *backgroundImageLayer = [RCTLinearGradient gradientLayerWithSize:self.layer.bounds.size
1018997
gradient:linearGradient];
1019-
backgroundImageLayer.frame = layer.bounds;
998+
[self shapeLayerToMatchView:backgroundImageLayer borderMetrics:borderMetrics];
1020999
backgroundImageLayer.masksToBounds = YES;
1021-
// To make border radius work with gradient layers
1022-
if (borderMetrics.borderRadii.isUniform()) {
1023-
backgroundImageLayer.cornerRadius = layer.cornerRadius;
1024-
backgroundImageLayer.cornerCurve = layer.cornerCurve;
1025-
backgroundImageLayer.mask = nil;
1026-
} else {
1027-
CAShapeLayer *maskLayer =
1028-
[self createMaskLayer:self.bounds
1029-
cornerInsets:RCTGetCornerInsets(
1030-
RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero)];
1031-
backgroundImageLayer.mask = maskLayer;
1032-
backgroundImageLayer.cornerRadius = 0;
1033-
}
1034-
10351000
backgroundImageLayer.zPosition = BACKGROUND_COLOR_ZPOSITION;
1036-
10371001
[self.layer addSublayer:backgroundImageLayer];
10381002
[_backgroundImageLayers addObject:backgroundImageLayer];
10391003
}
@@ -1098,6 +1062,26 @@ - (void)invalidateLayer
10981062
}
10991063
}
11001064

1065+
// Shapes the given layer to match the shape of this View's layer. This is
1066+
// basically just accounting for size, position, and border radius.
1067+
- (void)shapeLayerToMatchView:(CALayer *)layer borderMetrics:(BorderMetrics)borderMetrics
1068+
{
1069+
// Bounds is needed here to account for scaling transforms properly and ensure
1070+
// we do not scale twice
1071+
layer.frame = CGRectMake(0, 0, self.layer.bounds.size.width, self.layer.bounds.size.height);
1072+
if (borderMetrics.borderRadii.isUniform()) {
1073+
layer.mask = nil;
1074+
layer.cornerRadius = borderMetrics.borderRadii.topLeft.horizontal;
1075+
layer.cornerCurve = CornerCurveFromBorderCurve(borderMetrics.borderCurves.topLeft);
1076+
} else {
1077+
CAShapeLayer *maskLayer = [self
1078+
createMaskLayer:self.bounds
1079+
cornerInsets:RCTGetCornerInsets(RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero)];
1080+
layer.mask = maskLayer;
1081+
layer.cornerRadius = 0;
1082+
}
1083+
}
1084+
11011085
- (CAShapeLayer *)createMaskLayer:(CGRect)bounds cornerInsets:(RCTCornerInsets)cornerInsets
11021086
{
11031087
CGPathRef path = RCTPathCreateWithRoundedRect(bounds, cornerInsets, nil);

0 commit comments

Comments
 (0)