From ac274f362f7646b59e5ac050cdafe74e92cf60c8 Mon Sep 17 00:00:00 2001 From: Shashikant Panchal Date: Thu, 27 Aug 2026 16:36:18 +0530 Subject: [PATCH] fix(ios): prevent missing hairlineWidth border strokes at subpixel Y offsets (#58054) --- .../Mounting/ComponentViews/View/RCTViewComponentView.mm | 4 +++- packages/react-native/React/Views/RCTBorderDrawing.m | 8 ++------ packages/react-native/React/Views/RCTView.m | 5 ++++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 0912c50fec13..108742dd2dd1 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -887,7 +887,9 @@ static void RCTAddContourEffectToLayer( UIEdgeInsets imageCapInsets = image.capInsets; CGRect contentsCenter = CGRect{ CGPoint{imageCapInsets.left / imageSize.width, imageCapInsets.top / imageSize.height}, - CGSize{(CGFloat)1.0 / imageSize.width, (CGFloat)1.0 / imageSize.height}}; + CGSize{ + MAX(0, (imageSize.width - imageCapInsets.left - imageCapInsets.right) / imageSize.width), + MAX(0, (imageSize.height - imageCapInsets.top - imageCapInsets.bottom) / imageSize.height)}}; layer.contents = (id)image.CGImage; layer.contentsScale = image.scale; diff --git a/packages/react-native/React/Views/RCTBorderDrawing.m b/packages/react-native/React/Views/RCTBorderDrawing.m index 472885ca0c39..41f1297b67d6 100644 --- a/packages/react-native/React/Views/RCTBorderDrawing.m +++ b/packages/react-native/React/Views/RCTBorderDrawing.m @@ -247,12 +247,8 @@ static CGPathRef RCTPathCreateOuterOutline(BOOL drawToEdge, CGRect rect, RCTCorn const CGSize size = makeStretchable ? (CGSize){ // 1pt for the middle stretchable area along each axis - // we also need to round the edge insets to avoid border bleeding - // this is because if the size is decimal, when calculating the unit - // rectangle for CALayer.contentsCenter we encounter rounding errors - // which causes visual glitches - ceil(edgeInsets.left) + 1 + ceil(edgeInsets.right), - ceil(edgeInsets.top) + 1 + ceil(edgeInsets.bottom), + edgeInsets.left + 1 + edgeInsets.right, + edgeInsets.top + 1 + edgeInsets.bottom, } : viewSize; UIGraphicsImageRenderer *const imageRenderer = diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index bc39a7212f7b..614851309cb7 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -860,7 +860,10 @@ - (void)displayLayer:(CALayer *)layer CGSize size = image.size; UIEdgeInsets insets = image.capInsets; CGRectMake( - insets.left / size.width, insets.top / size.height, (CGFloat)1.0 / size.width, (CGFloat)1.0 / size.height); + insets.left / size.width, + insets.top / size.height, + MAX(0, (size.width - insets.left - insets.right) / size.width), + MAX(0, (size.height - insets.top - insets.bottom) / size.height)); }); layer.contents = (id)image.CGImage;