Skip to content

Commit ca2fc14

Browse files
Abbondanzometa-codesync[bot]
authored andcommitted
Fix mask-based clipping for < API 27 (#54914)
Summary: Pull Request resolved: #54914 The previous implementation for path clipping on API 27 would only attempt to draw a clipping mask within the bounds of the inner content, applying anti-aliasing to the edge of that padding box path. However, it would neglect to account for outlines, resulting in drawing inner contents *outside* the boundary of the box. This change inverts the logic by applying a mask to the entire content boundary and using DST_OUT to "delete" content outside of the padding box, while also still honoring the padding box path and its anti-aliasing Changelog: [Internal] Reviewed By: haixia-meta Differential Revision: D89324397 fbshipit-source-id: 1261d8500f44545445ff12e8e21412498fd4d040
1 parent df9d31b commit ca2fc14

1 file changed

Lines changed: 11 additions & 4 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BackgroundStyleApplicator.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -580,21 +580,28 @@ public object BackgroundStyleApplicator {
580580
// Draw the content first
581581
drawContent()
582582

583-
// Create the antialiased mask path with Porter-Duff DST_IN to clip
584583
val maskPaint = Paint(Paint.ANTI_ALIAS_FLAG)
585584
maskPaint.style = Paint.Style.FILL
586-
maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
587585

588586
// Transparent pixels with INVERSE_WINDING only works on API 28
589587
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
588+
maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
590589
maskPaint.color = Color.TRANSPARENT
591590
paddingBoxPath.setFillType(Path.FillType.INVERSE_WINDING)
591+
canvas.drawPath(paddingBoxPath, maskPaint)
592592
} else {
593+
// Create an inverse path: outer rect minus the rounded rect (using even-odd fill rule)
594+
val inversePath = Path()
595+
inversePath.addRect(0f, 0f, view.width.toFloat(), view.height.toFloat(), Path.Direction.CW)
596+
inversePath.addPath(paddingBoxPath)
597+
inversePath.setFillType(Path.FillType.EVEN_ODD)
598+
599+
// Use DST_OUT to remove content where the mask is drawn (outside the rounded rect)
600+
maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
593601
maskPaint.color = Color.BLACK
602+
canvas.drawPath(inversePath, maskPaint)
594603
}
595604

596-
canvas.drawPath(paddingBoxPath, maskPaint)
597-
598605
// Restore the layer
599606
canvas.restoreToCount(saveCount)
600607
}

0 commit comments

Comments
 (0)