Skip to content

Commit 6078778

Browse files
joevilchesfacebook-github-bot
authored andcommitted
Fix issue where scaling transform + box shadow break the shadow (facebook#49272)
Summary: Turns out bounds does not account for the proper size if a scaling transform is applied while frame does. Using the example listed in facebook#49134, the size of the frame is the expected 240, but the size of the bounds is 200. We had a mismatch where we use bounds everywhere in shadow image creation, but use the frame when asking for the size of the box shadow layer. What ends up happening is we have a 240x240 layer that is getting scaled again. I refactored the shadow creation to just take a CGSize instead of a whole CALayer (which we had only used for its size anyway) so that we can be consistent with frame and bounds, and use bounds everywhere so that we only scale once. 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: D69320213
1 parent d423679 commit 6078778

File tree

3 files changed

+13
-13
lines changed

3 files changed

+13
-13
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,13 +1047,13 @@ - (void)invalidateLayer
10471047
_boxShadowLayer = [CALayer layer];
10481048
[self.layer addSublayer:_boxShadowLayer];
10491049
_boxShadowLayer.zPosition = _borderLayer.zPosition;
1050-
_boxShadowLayer.frame = RCTGetBoundingRect(_props->boxShadow, self.layer.frame.size);
1050+
_boxShadowLayer.frame = RCTGetBoundingRect(_props->boxShadow, self.layer.bounds.size);
10511051

10521052
UIImage *boxShadowImage = RCTGetBoxShadowImage(
10531053
_props->boxShadow,
10541054
RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii),
10551055
RCTUIEdgeInsetsFromEdgeInsets(borderMetrics.borderWidths),
1056-
layer);
1056+
self.layer.bounds.size);
10571057

10581058
_boxShadowLayer.contents = (id)boxShadowImage.CGImage;
10591059
}

packages/react-native/React/Fabric/Utils/RCTBoxShadow.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ RCT_EXTERN UIImage *RCTGetBoxShadowImage(
1616
const std::vector<facebook::react::BoxShadow> &shadows,
1717
RCTCornerRadii cornerRadii,
1818
UIEdgeInsets edgeInsets,
19-
CALayer *layer);
19+
CGSize layerSize);
2020

2121
RCT_EXTERN CGRect RCTGetBoundingRect(const std::vector<facebook::react::BoxShadow> &boxShadows, CGSize layerSize);

packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static CGColorRef colorRefFromSharedColor(const SharedColor &color)
104104
static void renderOutsetShadows(
105105
std::vector<BoxShadow> &outsetShadows,
106106
RCTCornerRadii cornerRadii,
107-
CALayer *layer,
107+
CGSize layerSize,
108108
CGRect boundingRect,
109109
CGContextRef context)
110110
{
@@ -129,8 +129,8 @@ static void renderOutsetShadows(
129129
// the blur radius since this rect is not the shadow itself.
130130
const RCTCornerInsets shadowRectCornerInsets =
131131
RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, spreadDistance), UIEdgeInsetsZero);
132-
CGSize shadowRectSize = CGSizeMake(
133-
fmax(layer.bounds.size.width + 2 * spreadDistance, 0), fmax(layer.bounds.size.height + 2 * spreadDistance, 0));
132+
CGSize shadowRectSize =
133+
CGSizeMake(fmax(layerSize.width + 2 * spreadDistance, 0), fmax(layerSize.height + 2 * spreadDistance, 0));
134134
// Ensure this is drawn offscreen and will not show in the image
135135
CGRect shadowRect = CGRectMake(-shadowRectSize.width, 0, shadowRectSize.width, shadowRectSize.height);
136136
CGPathRef shadowRectPath = RCTPathCreateWithRoundedRect(shadowRect, shadowRectCornerInsets, nil);
@@ -165,7 +165,7 @@ static void renderOutsetShadows(
165165
// not cover its content
166166
const RCTCornerInsets layerCornerInsets = RCTGetCornerInsets(cornerRadii, UIEdgeInsetsZero);
167167
CGPathRef shadowPathAlignedWithLayer = RCTPathCreateWithRoundedRect(
168-
CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layer.bounds.size.width, layer.bounds.size.height),
168+
CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layerSize.width, layerSize.height),
169169
layerCornerInsets,
170170
nil);
171171
CGContextAddPath(context, shadowPathAlignedWithLayer);
@@ -187,7 +187,7 @@ static void renderInsetShadows(
187187
std::vector<BoxShadow> &insetShadows,
188188
RCTCornerRadii cornerRadii,
189189
UIEdgeInsets edgeInsets,
190-
CALayer *layer,
190+
CGSize layerSize,
191191
CGRect boundingRect,
192192
CGContextRef context)
193193
{
@@ -200,7 +200,7 @@ static void renderInsetShadows(
200200
CGContextSaveGState(context);
201201

202202
CGRect layerFrameRelativeToBoundingRect =
203-
CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layer.bounds.size.width, layer.bounds.size.height);
203+
CGRectMake(-boundingRect.origin.x, -boundingRect.origin.y, layerSize.width, layerSize.height);
204204
CGRect shadowFrame =
205205
insetRect(layerFrameRelativeToBoundingRect, edgeInsets.left, edgeInsets.top, edgeInsets.right, edgeInsets.bottom);
206206

@@ -279,9 +279,9 @@ static void renderInsetShadows(
279279
const std::vector<BoxShadow> &shadows,
280280
RCTCornerRadii cornerRadii,
281281
UIEdgeInsets edgeInsets,
282-
CALayer *layer)
282+
CGSize layerSize)
283283
{
284-
CGRect boundingRect = RCTGetBoundingRect(shadows, layer.bounds.size);
284+
CGRect boundingRect = RCTGetBoundingRect(shadows, layerSize);
285285
UIGraphicsImageRendererFormat *const rendererFormat = [UIGraphicsImageRendererFormat defaultFormat];
286286
UIGraphicsImageRenderer *const renderer = [[UIGraphicsImageRenderer alloc] initWithSize:boundingRect.size
287287
format:rendererFormat];
@@ -293,8 +293,8 @@ static void renderInsetShadows(
293293
// clear out a region in the view so we do not block its contents.
294294
// Inset shadows could draw over those outset shadows but if the shadow
295295
// colors have alpha < 1 then we will have inaccurate alpha compositing
296-
renderOutsetShadows(outsetShadows, cornerRadii, layer, boundingRect, context);
297-
renderInsetShadows(insetShadows, cornerRadii, edgeInsets, layer, boundingRect, context);
296+
renderOutsetShadows(outsetShadows, cornerRadii, layerSize, boundingRect, context);
297+
renderInsetShadows(insetShadows, cornerRadii, edgeInsets, layerSize, boundingRect, context);
298298
}];
299299

300300
return boxShadowImage;

0 commit comments

Comments
 (0)