Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<c47da5069c3dfd7a287125bd0dfbc0c0>>
* @generated SignedSource<<84bfc7b7a1b239c514b6d7c38dd91283>>
*/

/**
Expand Down Expand Up @@ -102,12 +102,6 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean = accessor.enableAccumulatedUpdatesInRawPropsAndroid()

/**
* Enable antialiased border radius clipping for Android API 28 and below using manual masking with Porter-Duff compositing
*/
@JvmStatic
public fun enableAndroidAntialiasedBorderRadiusClipping(): Boolean = accessor.enableAndroidAntialiasedBorderRadiusClipping()

/**
* Enables linear text rendering on Android wherever subpixel text rendering is enabled
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<0d98c7f7d2762c248a9670a447b5a93e>>
* @generated SignedSource<<1b59188082b9222b22b5cb0585cd166f>>
*/

/**
Expand Down Expand Up @@ -32,7 +32,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
private var disableViewPreallocationAndroidCache: Boolean? = null
private var enableAccessibilityOrderCache: Boolean? = null
private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null
private var enableAndroidAntialiasedBorderRadiusClippingCache: Boolean? = null
private var enableAndroidLinearTextCache: Boolean? = null
private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null
private var enableBridgelessArchitectureCache: Boolean? = null
Expand Down Expand Up @@ -219,15 +218,6 @@ internal class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAcces
return cached
}

override fun enableAndroidAntialiasedBorderRadiusClipping(): Boolean {
var cached = enableAndroidAntialiasedBorderRadiusClippingCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.enableAndroidAntialiasedBorderRadiusClipping()
enableAndroidAntialiasedBorderRadiusClippingCache = cached
}
return cached
}

override fun enableAndroidLinearText(): Boolean {
var cached = enableAndroidLinearTextCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<01dbfbb85643951c562e2cf1725387ff>>
* @generated SignedSource<<2fd657c62d07ed766a9241cb1c14d98d>>
*/

/**
Expand Down Expand Up @@ -52,8 +52,6 @@ public object ReactNativeFeatureFlagsCxxInterop {

@DoNotStrip @JvmStatic public external fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean

@DoNotStrip @JvmStatic public external fun enableAndroidAntialiasedBorderRadiusClipping(): Boolean

@DoNotStrip @JvmStatic public external fun enableAndroidLinearText(): Boolean

@DoNotStrip @JvmStatic public external fun enableAndroidTextMeasurementOptimizations(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<79077f7e8b2a7d435ac44c0a31ab87cc>>
* @generated SignedSource<<f3204842cd731d7eff8c4c4eeeead515>>
*/

/**
Expand Down Expand Up @@ -47,8 +47,6 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi

override fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean = false

override fun enableAndroidAntialiasedBorderRadiusClipping(): Boolean = false

override fun enableAndroidLinearText(): Boolean = true

override fun enableAndroidTextMeasurementOptimizations(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<b6c95e5954a185b0ee8c0ae8dde4a74b>>
* @generated SignedSource<<251381892c7d15310d61b35913c5cba6>>
*/

/**
Expand Down Expand Up @@ -36,7 +36,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
private var disableViewPreallocationAndroidCache: Boolean? = null
private var enableAccessibilityOrderCache: Boolean? = null
private var enableAccumulatedUpdatesInRawPropsAndroidCache: Boolean? = null
private var enableAndroidAntialiasedBorderRadiusClippingCache: Boolean? = null
private var enableAndroidLinearTextCache: Boolean? = null
private var enableAndroidTextMeasurementOptimizationsCache: Boolean? = null
private var enableBridgelessArchitectureCache: Boolean? = null
Expand Down Expand Up @@ -235,16 +234,6 @@ internal class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcc
return cached
}

override fun enableAndroidAntialiasedBorderRadiusClipping(): Boolean {
var cached = enableAndroidAntialiasedBorderRadiusClippingCache
if (cached == null) {
cached = currentProvider.enableAndroidAntialiasedBorderRadiusClipping()
accessedFeatureFlags.add("enableAndroidAntialiasedBorderRadiusClipping")
enableAndroidAntialiasedBorderRadiusClippingCache = cached
}
return cached
}

override fun enableAndroidLinearText(): Boolean {
var cached = enableAndroidLinearTextCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<30a507b84b656705ee1abec794472d6b>>
* @generated SignedSource<<7e47ac680222281a813e65484e7f8e39>>
*/

/**
Expand Down Expand Up @@ -47,8 +47,6 @@ public interface ReactNativeFeatureFlagsProvider {

@DoNotStrip public fun enableAccumulatedUpdatesInRawPropsAndroid(): Boolean

@DoNotStrip public fun enableAndroidAntialiasedBorderRadiusClipping(): Boolean

@DoNotStrip public fun enableAndroidLinearText(): Boolean

@DoNotStrip public fun enableAndroidTextMeasurementOptimizations(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ import android.os.Build
import android.view.View
import android.widget.ImageView
import androidx.annotation.ColorInt
import androidx.core.graphics.withClip
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.uimanager.PixelUtil.dpToPx
import com.facebook.react.uimanager.PixelUtil.pxToDp
import com.facebook.react.uimanager.common.UIManagerType
Expand Down Expand Up @@ -542,8 +540,7 @@ public object BackgroundStyleApplicator {
// On Android 28 and below, use antialiased clipping with Porter-Duff compositing. On newer
// Android versions, use the standard clipPath.
if (
ReactNativeFeatureFlags.enableAndroidAntialiasedBorderRadiusClipping() &&
Build.VERSION.SDK_INT <= Build.VERSION_CODES.P &&
Build.VERSION.SDK_INT <= Build.VERSION_CODES.P &&
view.width > 0 &&
view.height > 0 &&
drawContent != null
Expand Down Expand Up @@ -575,49 +572,50 @@ public object BackgroundStyleApplicator {
paddingBoxPath: Path,
drawContent: () -> Unit,
) {
// Clip to the view's own bounds before saveLayer. On API <= 28 hardware-accelerated canvases,
// Save the layer for Porter-Duff compositing
val saveCount = canvas.saveLayer(0f, 0f, view.width.toFloat(), view.height.toFloat(), null)

// Clip to the view's own bounds inside the layer. On API <= 28 hardware-accelerated canvases,
// the window boundary is tracked by the GPU scissor but not reflected in the canvas clip stack.
// Without an explicit software clip, saveLayer may allocate a buffer with uninitialized pixels
// beyond the GPU scissor. Adding clipRect in the view's local coordinate space forces HWUI to
// include it in the clip stack, ensuring saveLayer properly constrains its buffer. This clip is
// stable across parent transform animations since it's in the view's own coordinate space.
canvas.withClip(0, 0, view.width, view.height) {
// Save the layer for Porter-Duff compositing
val saveCount = canvas.saveLayer(0f, 0f, view.width.toFloat(), view.height.toFloat(), null)

// Draw the content first
drawContent()

val maskPaint = Paint(Paint.ANTI_ALIAS_FLAG)
maskPaint.style = Paint.Style.FILL

// Transparent pixels with INVERSE_WINDING only works on API 28
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
maskPaint.color = Color.TRANSPARENT
paddingBoxPath.setFillType(Path.FillType.INVERSE_WINDING)
canvas.drawPath(paddingBoxPath, maskPaint)
} else {
// API < 28: Use a nested saveLayer with DST_IN compositing to mask content to the
// padding box path. EVEN_ODD fill + DST_OUT has rendering bugs on API 24's hardware
// renderer, so we avoid that technique. Instead, draw the mask shape into a separate
// layer; when restored with DST_IN, content is preserved only where the mask is opaque.
val dstInPaint = Paint()
dstInPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
val maskSave =
canvas.saveLayer(0f, 0f, view.width.toFloat(), view.height.toFloat(), dstInPaint)
// Clear the layer to ensure it starts fully transparent. On API 24, saveLayer may not
// initialize the buffer to transparent, causing DST_IN to see non-zero alpha everywhere.
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
maskPaint.xfermode = null
maskPaint.color = Color.BLACK
canvas.drawPath(paddingBoxPath, maskPaint)
canvas.restoreToCount(maskSave)
}

// Restore the layer
canvas.restoreToCount(saveCount)
// beyond the GPU scissor. Adding clipRect inside the layer (rather than wrapping it with
// canvas.withClip) avoids an extra save/restore nesting level that breaks Porter-Duff
// compositing on API 24's HWUI renderer. The saveLayer already saves and restores the clip
// state, so a separate save/restore wrapper is unnecessary.
canvas.clipRect(0, 0, view.width, view.height)

// Draw the content first
drawContent()

val maskPaint = Paint(Paint.ANTI_ALIAS_FLAG)
maskPaint.style = Paint.Style.FILL

// Transparent pixels with INVERSE_WINDING only works on API 28
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
maskPaint.color = Color.TRANSPARENT
paddingBoxPath.setFillType(Path.FillType.INVERSE_WINDING)
canvas.drawPath(paddingBoxPath, maskPaint)
} else {
// API < 28: Use a nested saveLayer with DST_IN compositing to mask content to the
// padding box path. EVEN_ODD fill + DST_OUT has rendering bugs on API 24's hardware
// renderer, so we avoid that technique. Instead, draw the mask shape into a separate
// layer; when restored with DST_IN, content is preserved only where the mask is opaque.
val dstInPaint = Paint()
dstInPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
val maskSave =
canvas.saveLayer(0f, 0f, view.width.toFloat(), view.height.toFloat(), dstInPaint)
// Clear the layer to ensure it starts fully transparent. On API 24, saveLayer may not
// initialize the buffer to transparent, causing DST_IN to see non-zero alpha everywhere.
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
maskPaint.xfermode = null
maskPaint.color = Color.BLACK
canvas.drawPath(paddingBoxPath, maskPaint)
canvas.restoreToCount(maskSave)
}

// Restore the layer
canvas.restoreToCount(saveCount)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<880f137911af6d2a9d383ebd68ddc300>>
* @generated SignedSource<<7e78fc846fe46b5dc7d451817db90ec1>>
*/

/**
Expand Down Expand Up @@ -111,12 +111,6 @@ class ReactNativeFeatureFlagsJavaProvider
return method(javaProvider_);
}

bool enableAndroidAntialiasedBorderRadiusClipping() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableAndroidAntialiasedBorderRadiusClipping");
return method(javaProvider_);
}

bool enableAndroidLinearText() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("enableAndroidLinearText");
Expand Down Expand Up @@ -643,11 +637,6 @@ bool JReactNativeFeatureFlagsCxxInterop::enableAccumulatedUpdatesInRawPropsAndro
return ReactNativeFeatureFlags::enableAccumulatedUpdatesInRawPropsAndroid();
}

bool JReactNativeFeatureFlagsCxxInterop::enableAndroidAntialiasedBorderRadiusClipping(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableAndroidAntialiasedBorderRadiusClipping();
}

bool JReactNativeFeatureFlagsCxxInterop::enableAndroidLinearText(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::enableAndroidLinearText();
Expand Down Expand Up @@ -1100,9 +1089,6 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"enableAccumulatedUpdatesInRawPropsAndroid",
JReactNativeFeatureFlagsCxxInterop::enableAccumulatedUpdatesInRawPropsAndroid),
makeNativeMethod(
"enableAndroidAntialiasedBorderRadiusClipping",
JReactNativeFeatureFlagsCxxInterop::enableAndroidAntialiasedBorderRadiusClipping),
makeNativeMethod(
"enableAndroidLinearText",
JReactNativeFeatureFlagsCxxInterop::enableAndroidLinearText),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<906bda93de19c1836ce3df29e05db610>>
* @generated SignedSource<<022cea241825b693de81b5f1f6d7d638>>
*/

/**
Expand Down Expand Up @@ -66,9 +66,6 @@ class JReactNativeFeatureFlagsCxxInterop
static bool enableAccumulatedUpdatesInRawPropsAndroid(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool enableAndroidAntialiasedBorderRadiusClipping(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool enableAndroidLinearText(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<f86521eb5833e76014b3197a6ab23b60>>
* @generated SignedSource<<470390f6f44bd822b286329f5f103cbe>>
*/

/**
Expand Down Expand Up @@ -74,10 +74,6 @@ bool ReactNativeFeatureFlags::enableAccumulatedUpdatesInRawPropsAndroid() {
return getAccessor().enableAccumulatedUpdatesInRawPropsAndroid();
}

bool ReactNativeFeatureFlags::enableAndroidAntialiasedBorderRadiusClipping() {
return getAccessor().enableAndroidAntialiasedBorderRadiusClipping();
}

bool ReactNativeFeatureFlags::enableAndroidLinearText() {
return getAccessor().enableAndroidLinearText();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a218accbb46d69a2d1bf54e0213b3421>>
* @generated SignedSource<<8196f0d040b6f43e3bdc875f40b0041d>>
*/

/**
Expand Down Expand Up @@ -99,11 +99,6 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool enableAccumulatedUpdatesInRawPropsAndroid();

/**
* Enable antialiased border radius clipping for Android API 28 and below using manual masking with Porter-Duff compositing
*/
RN_EXPORT static bool enableAndroidAntialiasedBorderRadiusClipping();

/**
* Enables linear text rendering on Android wherever subpixel text rendering is enabled
*/
Expand Down
Loading
Loading