Implement clipping rectangle for ReactNativeART

Reviewed By: sebmarkbage, taomin

Differential Revision: D3140869

fb-gh-sync-id: 0da27705c4cfca7a1fcae12eed11a7335a62631f
fbshipit-source-id: 0da27705c4cfca7a1fcae12eed11a7335a62631f
This commit is contained in:
Scott Foggo 2016-04-11 19:18:50 -07:00 committed by Facebook Github Bot 5
parent 0b534d1c3d
commit 24f03af0c3
5 changed files with 56 additions and 9 deletions

View File

@ -14,4 +14,6 @@
@interface ARTGroup : ARTNode <ARTContainer>
@property (nonatomic, assign) CGRect clipping;
@end

View File

@ -13,7 +13,10 @@
- (void)renderLayerTo:(CGContextRef)context
{
// TO-DO: Clipping rectangle
if (!CGRectIsEmpty(self.clipping)) {
CGContextClipToRect(context, self.clipping);
}
for (ARTNode *node in self.subviews) {
[node renderTo:context];

View File

@ -227,13 +227,7 @@ var ClippingRectangle = React.createClass({
var y = extractNumber(props.y, 0);
var w = extractNumber(props.width, 0);
var h = extractNumber(props.height, 0);
var clipping = new Path()
.moveTo(x, y)
.line(w, 0)
.line(0, h)
.line(w, 0)
.close()
.toJSON();
var clipping = [x, y, w, h];
// The current clipping API requires x and y to be ignored in the transform
var propsExcludingXAndY = merge(props);
delete propsExcludingXAndY.x;

View File

@ -10,6 +10,7 @@
#import "ARTGroupManager.h"
#import "ARTGroup.h"
#import "RCTConvert+ART.h"
@implementation ARTGroupManager
@ -20,4 +21,6 @@ RCT_EXPORT_MODULE()
return [ARTGroup new];
}
RCT_EXPORT_VIEW_PROPERTY(clipping, CGRect)
@end

View File

@ -9,14 +9,33 @@
package com.facebook.react.views.art;
import javax.annotation.Nullable;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Region;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.annotations.ReactProp;
/**
* Shadow node for virtual ARTGroup view
*/
public class ARTGroupShadowNode extends ARTVirtualNode {
protected @Nullable RectF mClipping;
@ReactProp(name = "clipping")
public void setClipping(@Nullable ReadableArray clippingDims) {
float[] clippingData = PropHelper.toFloatArray(clippingDims);
if (clippingData != null) {
mClipping = createClipping(clippingData);
markUpdated();
}
}
@Override
public boolean isVirtual() {
return true;
@ -26,7 +45,16 @@ public class ARTGroupShadowNode extends ARTVirtualNode {
opacity *= mOpacity;
if (opacity > MIN_OPACITY_FOR_DRAW) {
saveAndSetupCanvas(canvas);
// TODO(6352006): apply clipping (iOS doesn't do it yet, it seems to cause issues)
if (mClipping != null) {
canvas.clipRect(
mClipping.left * mScale,
mClipping.top * mScale,
mClipping.right * mScale,
mClipping.bottom * mScale,
Region.Op.REPLACE);
}
for (int i = 0; i < getChildCount(); i++) {
ARTVirtualNode child = (ARTVirtualNode) getChildAt(i);
child.draw(canvas, paint, opacity);
@ -36,4 +64,21 @@ public class ARTGroupShadowNode extends ARTVirtualNode {
restoreCanvas(canvas);
}
}
/**
* Creates a {@link RectF} from an array of dimensions
* (e.g. [x, y, width, height])
*
* @param data the array of dimensions
* @return the {@link RectF} that can used to clip the canvas
*/
private static RectF createClipping(float[] data) {
if (data.length != 4) {
throw new JSApplicationIllegalArgumentException(
"Clipping should be array of length 4 (e.g. [x, y, width, height])");
}
RectF clippingRect = new RectF(
data[0], data[1], data[0] + data[2], data[1] + data[3]);
return clippingRect;
}
}