RCTText should clip when the creates Layout is wider than requested
Summary: AbstractDrawCommand's bounds are supposed to be the rectangle that the DrawCommand will draw into, so that it can compare bounds against clip rect bounds and reliable skip clipping when it's not needed. It is however not true for RCTText that can create text Layout that in some cases can go out of it's requested bounds (happens with TextView, too). To fix the issue, instead of passing requested bounds, pass the actual ones. In this case, AbstractDrawCommand will make sure to clip DrawTextLayout if for some reason it draws outside of the allowed boundaries. Reviewed By: ahmedre Differential Revision: D2786306
This commit is contained in:
parent
d23f86e47b
commit
e3abc51dd7
|
@ -18,9 +18,10 @@ import android.text.Layout;
|
|||
/* package */ final class DrawTextLayout extends AbstractDrawCommand {
|
||||
|
||||
private Layout mLayout;
|
||||
private float mLayoutWidth;
|
||||
|
||||
/* package */ DrawTextLayout(Layout layout) {
|
||||
mLayout = layout;
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,12 +29,30 @@ import android.text.Layout;
|
|||
*/
|
||||
public void setLayout(Layout layout) {
|
||||
mLayout = layout;
|
||||
|
||||
// determine how wide we actually are
|
||||
float maxLineWidth = 0;
|
||||
int lineCount = layout.getLineCount();
|
||||
for (int i = 0; i != lineCount; ++i) {
|
||||
maxLineWidth = Math.max(maxLineWidth, layout.getLineMax(i));
|
||||
}
|
||||
|
||||
mLayoutWidth = maxLineWidth;
|
||||
}
|
||||
|
||||
public Layout getLayout() {
|
||||
return mLayout;
|
||||
}
|
||||
|
||||
public float getLayoutWidth() {
|
||||
// mLayout.getWidth() doesn't return correct width of the text Layout
|
||||
return mLayoutWidth;
|
||||
}
|
||||
|
||||
public float getLayoutHeight() {
|
||||
return mLayout.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
float left = getLeft();
|
||||
|
|
|
@ -122,21 +122,14 @@ import com.facebook.react.uimanager.ViewProps;
|
|||
mNumberOfLines,
|
||||
false);
|
||||
|
||||
// determine how wide we actually are
|
||||
float maxLineWidth = 0;
|
||||
int lineCount = layout.getLineCount();
|
||||
for (int i = 0; i != lineCount; ++i) {
|
||||
maxLineWidth = Math.max(maxLineWidth, layout.getLineMax(i));
|
||||
}
|
||||
|
||||
measureOutput.width = maxLineWidth;
|
||||
measureOutput.height = layout.getHeight();
|
||||
|
||||
if (mDrawCommand != null && !mDrawCommand.isFrozen()) {
|
||||
mDrawCommand.setLayout(layout);
|
||||
} else {
|
||||
mDrawCommand = new DrawTextLayout(layout);
|
||||
}
|
||||
|
||||
measureOutput.width = mDrawCommand.getLayoutWidth();
|
||||
measureOutput.height = mDrawCommand.getLayoutHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -180,6 +173,18 @@ import com.facebook.react.uimanager.ViewProps;
|
|||
INCLUDE_PADDING));
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
mDrawCommand = (DrawTextLayout) mDrawCommand.updateBoundsAndFreeze(
|
||||
left,
|
||||
top,
|
||||
|
|
Loading…
Reference in New Issue