From de313f6fddfa0e98c42053d451c4d2a749a7e4e1 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Wed, 18 Oct 2017 19:29:28 -0700 Subject: [PATCH] Fix border clipping Reviewed By: achen1 Differential Revision: D5992045 fbshipit-source-id: fccd864dbc24592c3cd4df7300aca5096537e1d8 --- .../view/ReactViewBackgroundDrawable.java | 40 ++++++++++++++---- .../react/views/view/ReactViewGroup.java | 42 ++++++++++++++++--- 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java index 496007c8b..7a43ef9fc 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java @@ -98,6 +98,13 @@ public class ReactViewBackgroundDrawable extends Drawable { private @Nullable float[] mBorderCornerRadii; + public enum BorderRadiusLocation { + TOP_LEFT, + TOP_RIGHT, + BOTTOM_RIGHT, + BOTTOM_LEFT + } + @Override public void draw(Canvas canvas) { updatePathEffect(); @@ -228,8 +235,23 @@ public class ReactViewBackgroundDrawable extends Drawable { } } - public float getRadius() { - return mBorderRadius; + public float getFullBorderRadius() { + return YogaConstants.isUndefined(mBorderRadius) ? 0 : mBorderRadius; + } + + public float getBorderRadiusOrDefaultTo( + final float defaultValue, final BorderRadiusLocation location) { + if (mBorderCornerRadii == null) { + return defaultValue; + } + + final float radius = mBorderCornerRadii[location.ordinal()]; + + if (YogaConstants.isUndefined(radius)) { + return defaultValue; + } + + return radius; } public void setColor(int color) { @@ -283,11 +305,15 @@ public class ReactViewBackgroundDrawable extends Drawable { mTempRectForBorderRadius.inset(fullBorderWidth * 0.5f, fullBorderWidth * 0.5f); } - float defaultBorderRadius = !YogaConstants.isUndefined(mBorderRadius) ? mBorderRadius : 0; - float topLeftRadius = mBorderCornerRadii != null && !YogaConstants.isUndefined(mBorderCornerRadii[0]) ? mBorderCornerRadii[0] : defaultBorderRadius; - float topRightRadius = mBorderCornerRadii != null && !YogaConstants.isUndefined(mBorderCornerRadii[1]) ? mBorderCornerRadii[1] : defaultBorderRadius; - float bottomRightRadius = mBorderCornerRadii != null && !YogaConstants.isUndefined(mBorderCornerRadii[2]) ? mBorderCornerRadii[2] : defaultBorderRadius; - float bottomLeftRadius = mBorderCornerRadii != null && !YogaConstants.isUndefined(mBorderCornerRadii[3]) ? mBorderCornerRadii[3] : defaultBorderRadius; + final float borderRadius = getFullBorderRadius(); + final float topLeftRadius = + getBorderRadiusOrDefaultTo(borderRadius, BorderRadiusLocation.TOP_LEFT); + final float topRightRadius = + getBorderRadiusOrDefaultTo(borderRadius, BorderRadiusLocation.TOP_RIGHT); + final float bottomLeftRadius = + getBorderRadiusOrDefaultTo(borderRadius, BorderRadiusLocation.BOTTOM_LEFT); + final float bottomRightRadius = + getBorderRadiusOrDefaultTo(borderRadius, BorderRadiusLocation.BOTTOM_RIGHT); mPathForBorderRadius.addRoundRect( mTempRectForBorderRadius, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 828b928d4..4de2ce855 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -34,7 +34,6 @@ import com.facebook.react.uimanager.ReactClippingViewGroupHelper; import com.facebook.react.uimanager.ReactPointerEventsView; import com.facebook.react.uimanager.ReactZIndexedViewGroup; import com.facebook.react.uimanager.ViewGroupDrawingOrderHelper; -import com.facebook.yoga.YogaConstants; import javax.annotation.Nullable; /** @@ -625,23 +624,54 @@ public class ReactViewGroup extends ViewGroup implements float top = 0f; float right = getWidth(); float bottom = getHeight(); - if (mReactBackgroundDrawable.getFullBorderWidth() != 0f) { - float borderWidth = mReactBackgroundDrawable.getFullBorderWidth(); + final float borderWidth = mReactBackgroundDrawable.getFullBorderWidth(); + + if (borderWidth != 0f) { left += borderWidth; top += borderWidth; right -= borderWidth; bottom -= borderWidth; } - float radius = mReactBackgroundDrawable.getRadius(); - if (!YogaConstants.isUndefined(radius) && radius > 0.5f) { + final float borderRadius = mReactBackgroundDrawable.getFullBorderRadius(); + final float topLeftBorderRadius = + mReactBackgroundDrawable.getBorderRadiusOrDefaultTo( + borderRadius, ReactViewBackgroundDrawable.BorderRadiusLocation.TOP_LEFT); + final float topRightBorderRadius = + mReactBackgroundDrawable.getBorderRadiusOrDefaultTo( + borderRadius, ReactViewBackgroundDrawable.BorderRadiusLocation.TOP_RIGHT); + final float bottomLeftBorderRadius = + mReactBackgroundDrawable.getBorderRadiusOrDefaultTo( + borderRadius, ReactViewBackgroundDrawable.BorderRadiusLocation.BOTTOM_LEFT); + final float bottomRightBorderRadius = + mReactBackgroundDrawable.getBorderRadiusOrDefaultTo( + borderRadius, ReactViewBackgroundDrawable.BorderRadiusLocation.BOTTOM_RIGHT); + + if (topLeftBorderRadius > 0 + || topRightBorderRadius > 0 + || bottomRightBorderRadius > 0 + || bottomLeftBorderRadius > 0) { if (mPath == null) { mPath = new Path(); } + mPath.rewind(); mPath.addRoundRect( - new RectF(left, top, right, bottom), radius, radius, Path.Direction.CW); + new RectF(left, top, right, bottom), + new float[] { + Math.max(topLeftBorderRadius - borderWidth, 0), + Math.max(topLeftBorderRadius - borderWidth, 0), + Math.max(topRightBorderRadius - borderWidth, 0), + Math.max(topRightBorderRadius - borderWidth, 0), + Math.max(bottomRightBorderRadius - borderWidth, 0), + Math.max(bottomRightBorderRadius - borderWidth, 0), + Math.max(bottomLeftBorderRadius - borderWidth, 0), + Math.max(bottomLeftBorderRadius - borderWidth, 0), + }, + Path.Direction.CW); canvas.clipPath(mPath); + } else { + canvas.clipRect(new RectF(left, top, right, bottom)); } } break;