From acb634bc9662c1103bc7c8ca83cfdc62516d0060 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Wed, 31 Jul 2024 10:13:20 -0700 Subject: [PATCH] Fix case where certain spreads break box shadow logic (#45746) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45746 Once the spread was past a certain value, it could break some of this logic by creating a null rect or negative size. This just makes it so that in those cases, inset will be a 0x0 clear region rect and outset will be nothing Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D60317780 fbshipit-source-id: 021bf41d71ae69809076b4f5e6413d04cd878372 --- packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm index 3d46f08652e..a3516ee49b3 100644 --- a/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm +++ b/packages/react-native/React/Fabric/Utils/RCTBoxShadow.mm @@ -117,8 +117,8 @@ static void renderOutsetShadows( // the blur radius since this rect is not the shadow itself. const RCTCornerInsets shadowRectCornerInsets = RCTGetCornerInsets(cornerRadiiForBoxShadow(cornerRadii, spreadDistance), UIEdgeInsetsZero); - CGSize shadowRectSize = - CGSizeMake(layer.bounds.size.width + 2 * spreadDistance, layer.bounds.size.height + 2 * spreadDistance); + CGSize shadowRectSize = CGSizeMake( + fmax(layer.bounds.size.width + 2 * spreadDistance, 0), fmax(layer.bounds.size.height + 2 * spreadDistance, 0)); // Ensure this is drawn offscreen and will not show in the image CGRect shadowRect = CGRectMake(-shadowRectSize.width, 0, shadowRectSize.width, shadowRectSize.height); CGPathRef shadowRectPath = RCTPathCreateWithRoundedRect(shadowRect, shadowRectCornerInsets, nil); @@ -222,6 +222,11 @@ static void renderInsetShadows( // of the view. CGRect shadowCastingRect = CGRectInset(shadowFrame, -blurRadius, -blurRadius); CGRect clearRegionRect = CGRectInset(shadowFrame, spreadDistance, spreadDistance); + // This happens if the spread causes the height/width to be negative. A null + // rect breaks a lot of the logic, so lets just keep it as a point + if (CGRectIsNull(clearRegionRect)) { + clearRegionRect = CGRectMake(0, 0, 0, 0); + } CGPoint offsetToMoveOffscreen = CGPointMake( -fmax( shadowCastingRect.size.width,