Only clip node against its own boundaries IFF clipToBounds() is set to true (i.e. overflow is visible)

Summary:
Previously, every node would be clipped by its own boundaries. This made sense, because
a) RCTView cannot draw outside of its bounds, so clipping is harmless
b) all other node types were not allowed to control overflow behavior, and for them overflow was implicitly set to hidden, which means it should clip.

This diff changes the logic so that overflow can be set on any node (image, text, view etc).

The change has an important implication that make the diff a little trickier that it could be: AbstractDrawCommand clipping logic needs to be relaxed. Previously, clip bounds were *always* intersected with node bounds, which means that clip rect was always within node rect. This is no longer true, and thus shouldClip() logic needs to be modified.

Because of the above, RCTText no longer needs to artificially clip bounds against layout width/height.

Note: RCTImage is still not working with overflow: visible correctly (it still always clips). This is fixed in a follow up diff.

Reviewed By: ahmedre

Differential Revision: D2867849
This commit is contained in:
Denis Koroskin 2016-01-28 18:02:40 -08:00 коммит произвёл Ahmed El-Helw
Родитель 05e8ff1fe0
Коммит 674e74a963
3 изменённых файлов: 13 добавлений и 26 удалений

Просмотреть файл

@ -140,7 +140,7 @@ import android.graphics.Canvas;
protected abstract void onDraw(Canvas canvas);
protected boolean shouldClip() {
return mLeft != mClipLeft || mTop != mClipTop || mRight != mClipRight || mBottom != mClipBottom;
return mLeft < mClipLeft || mTop < mClipTop || mRight > mClipRight || mBottom > mClipBottom;
}
protected void onBoundsChanged() {

Просмотреть файл

@ -186,16 +186,8 @@ import com.facebook.react.uimanager.annotations.ReactProp;
top += padding.get(Spacing.TOP);
// these are actual right/bottom coordinates where this DrawCommand will draw.
float layoutRight = left + mDrawCommand.getLayoutWidth();
float layoutBottom = top + mDrawCommand.getLayoutHeight();
// We need to adjust right/bottom because Layout size is in many cases different than the
// current node's size. We could use layoutRight/layoutBottom instead of taking the minumum of
// (right,layoutRight) and that would work correctly, but it will also make AbstractDrawCommand
// clip when the clipping is not really necessary (because it doesn't like draw bounds smaller
// than clip bounds).
right = Math.max(right, layoutRight);
bottom = Math.max(bottom, layoutBottom);
right = left + mDrawCommand.getLayoutWidth();
bottom = top + mDrawCommand.getLayoutHeight();
mDrawCommand = (DrawTextLayout) mDrawCommand.updateBoundsAndFreeze(
left,

Просмотреть файл

@ -347,10 +347,10 @@ import com.facebook.react.uimanager.events.EventDispatcher;
float top,
float right,
float bottom,
float parentClipLeft,
float parentClipTop,
float parentClipRight,
float parentClipBottom,
float clipLeft,
float clipTop,
float clipRight,
float clipBottom,
boolean isAndroidView,
boolean needsCustomLayoutForChildren) {
if (node.hasNewLayout()) {
@ -368,20 +368,15 @@ import com.facebook.react.uimanager.events.EventDispatcher;
Math.round(bottom - top)));
}
float clipLeft = Math.max(left, parentClipLeft);
float clipTop = Math.max(top, parentClipTop);
float clipRight = Math.min(right, parentClipRight);
float clipBottom = Math.min(bottom, parentClipBottom);
if (node.clipToBounds()) {
clipLeft = Math.max(left, clipLeft);
clipTop = Math.max(top, clipTop);
clipRight = Math.min(right, clipRight);
clipBottom = Math.min(bottom, clipBottom);
}
node.collectState(this, left, top, right, bottom, clipLeft, clipTop, clipRight, clipBottom);
if (!node.clipToBounds()) {
clipLeft = parentClipLeft;
clipTop = parentClipTop;
clipRight = parentClipRight;
clipBottom = parentClipBottom;
}
for (int i = 0, childCount = node.getChildCount(); i != childCount; ++i) {
FlatShadowNode child = (FlatShadowNode) node.getChildAt(i);
if (child.isVirtual()) {