From 88ebce05120e6e96034bedbeade994e908001d4b Mon Sep 17 00:00:00 2001 From: Denis Koroskin Date: Fri, 29 Jan 2016 15:04:00 -0800 Subject: [PATCH] Fix RCTImageView always clipping to bounds even if overflow is visible Summary: Previously, RCTImageView/DrawCommand would always clip for specific scale types (such as CENTER_CROP), but this is incorrect if we want to allow overflow: visible on RCTImageView (which iOS allows). This patch tweaks the clipping condition from paddingLeft/paddingTop < 0 (i.e. image wants to draw outside of its bounds) to actual image rect being outside of clip rect. Previously, that would mean exact same thing, but now that clip rect is aware of overflow: visible, it matters, allowing RCTImage to not clip when we want it to draw outside of the boundaries. Reviewed By: ahmedre Differential Revision: D2873350 --- .../react/flat/AbstractDrawCommand.java | 16 ++++++++++++++++ .../react/flat/DrawImageWithPipeline.java | 19 ++++++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java b/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java index aca4723cf..cf16d5851 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java @@ -137,6 +137,22 @@ import android.graphics.Canvas; return mBottom; } + public final float getClipLeft() { + return mClipLeft; + } + + public final float getClipTop() { + return mClipTop; + } + + public final float getClipRight() { + return mClipRight; + } + + public final float getClipBottom() { + return mClipBottom; + } + protected abstract void onDraw(Canvas canvas); protected boolean shouldClip() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java index c186f8f04..f54b9c683 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java @@ -44,7 +44,8 @@ import com.facebook.react.views.image.ReactImageView; private @Nullable FlatViewGroup.InvalidateCallback mCallback; private @Nullable Path mPathForRoundedBitmap; private @Nullable BitmapShader mBitmapShader; - private boolean mForceClip; + private float mHorizontalPadding; + private float mVerticalPadding; private int mReactTag; // variables used for fading the image in @@ -149,7 +150,10 @@ import com.facebook.react.views.image.ReactImageView; @Override protected boolean shouldClip() { - return mForceClip || super.shouldClip(); + return getLeft() + mHorizontalPadding < getClipLeft() || + getTop() + mVerticalPadding < getClipTop() || + getRight() - mHorizontalPadding > getClipRight() || + getBottom() - mVerticalPadding < getClipBottom(); } @Override @@ -211,11 +215,10 @@ import com.facebook.react.views.image.ReactImageView; float imageWidth = (float) bitmap.getWidth(); float imageHeight = (float) bitmap.getHeight(); - mForceClip = false; - if (mScaleType == ScaleType.FIT_XY) { mTransform.setScale(containerWidth / imageWidth, containerHeight / imageHeight); mTransform.postTranslate(left, top); + mHorizontalPadding = mVerticalPadding = 0; return; } @@ -231,13 +234,11 @@ import com.facebook.react.views.image.ReactImageView; scale = Math.max(containerWidth / imageWidth, containerHeight / imageHeight); } - float paddingLeft = (containerWidth - imageWidth * scale) / 2; - float paddingTop = (containerHeight - imageHeight * scale) / 2; - - mForceClip = paddingLeft < 0 || paddingTop < 0; + mHorizontalPadding = (containerWidth - imageWidth * scale) / 2; + mVerticalPadding = (containerHeight - imageHeight * scale) / 2; mTransform.setScale(scale, scale); - mTransform.postTranslate(left + paddingLeft, top + paddingTop); + mTransform.postTranslate(left + mHorizontalPadding, top + mVerticalPadding); if (mBitmapShader != null) { mBitmapShader.setLocalMatrix(mTransform);