From af5002b2e13b1faaa740426ff5a5897481ef69f5 Mon Sep 17 00:00:00 2001 From: Andrew Knapp Date: Thu, 29 Aug 2024 11:21:21 -0700 Subject: [PATCH] Fix GH-41226 by suppressing path adjustment when not actually drawing a border (#46239) Summary: When not drawing a border, the mGapBetweenPaths adjustment can create noticable pixelation when drawing curves through a low number of pixels. This is noticable mostly on buttons and such on low-dpi devices. This fix only applies the fix if clipping for the border radius is done. When drawing small radius rounded backgrounds (e.g. to draw a circle or button) we see visible pixelation (see [GH-41226](https://github.com/facebook/react-native/issues/41226)) This is particularly noticable on low DPI devices. ## Changelog: [ANDROID] [FIXED] - Don't use mGapBetweenPaths if not drawing a border Pull Request resolved: https://github.com/facebook/react-native/pull/46239 Test Plan: Built an android app that directly uses CSSBackgroundDrawable to draw a background and verified repro of this issue. ![pre-fix](https://github.com/user-attachments/assets/e56a41b1-60f6-4953-9e91-b95a3380f2d7) Then modified the code according to this PR and verified that anti-aliasing is appropriately applied ![fix](https://github.com/user-attachments/assets/b6b1aecf-a713-4e0a-9759-82c2dd862991) Reviewed By: NickGerleman Differential Revision: D61925281 Pulled By: jorge-cab fbshipit-source-id: 93014629d031bd0d716cd3bb11e2c294dedad639 --- .../uimanager/drawable/CSSBackgroundDrawable.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java index fc2cd0c5d0fc8a..2048fc6a926121 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CSSBackgroundDrawable.java @@ -605,6 +605,7 @@ private void updatePath() { } // Clip border ONLY if its color is non transparent + float pathAdjustment = 0f; if (Color.alpha(colorLeft) != 0 && Color.alpha(colorTop) != 0 && Color.alpha(colorRight) != 0 @@ -615,6 +616,10 @@ private void updatePath() { mInnerClipTempRectForBorderRadius.bottom -= borderWidth.bottom; mInnerClipTempRectForBorderRadius.left += borderWidth.left; mInnerClipTempRectForBorderRadius.right -= borderWidth.right; + + // only close gap between border and main path if we draw the border, otherwise + // we wind up pixelating small pixel-radius curves + pathAdjustment = mGapBetweenPaths; } mTempRectForCenterDrawPath.top += borderWidth.top * 0.5f; @@ -661,10 +666,10 @@ private void updatePath() { // (mInnerClipTempRectForBorderRadius), ensuring the border can be // drawn on top without the gap. mBackgroundColorRenderPath.addRoundRect( - mInnerClipTempRectForBorderRadius.left - mGapBetweenPaths, - mInnerClipTempRectForBorderRadius.top - mGapBetweenPaths, - mInnerClipTempRectForBorderRadius.right + mGapBetweenPaths, - mInnerClipTempRectForBorderRadius.bottom + mGapBetweenPaths, + mInnerClipTempRectForBorderRadius.left - pathAdjustment, + mInnerClipTempRectForBorderRadius.top - pathAdjustment, + mInnerClipTempRectForBorderRadius.right + pathAdjustment, + mInnerClipTempRectForBorderRadius.bottom + pathAdjustment, new float[] { innerTopLeftRadiusX, innerTopLeftRadiusY,