Fix hit testing when using react-native transform arrays.

This commit is contained in:
Mikael Sand
2018-10-24 02:21:46 +03:00
parent f6995e856d
commit 38310677e3
13 changed files with 47 additions and 35 deletions
@@ -191,12 +191,13 @@ class GroupView extends RenderableView {
@Override
int hitTest(final float[] src) {
if (!mInvertible) {
if (!mInvertible || !mTransformInvertible) {
return -1;
}
float[] dst = new float[2];
mInvMatrix.mapPoints(dst, src);
mInvTransform.mapPoints(dst, src);
int x = Math.round(dst[0]);
int y = Math.round(dst[1]);
@@ -428,12 +428,13 @@ abstract public class RenderableView extends VirtualView {
@Override
int hitTest(final float[] src) {
if (mPath == null || !mInvertible) {
if (mPath == null || !mInvertible || !mTransformInvertible) {
return -1;
}
float[] dst = new float[2];
mInvMatrix.mapPoints(dst, src);
mInvTransform.mapPoints(dst, src);
int x = Math.round(dst[0]);
int y = Math.round(dst[1]);
@@ -9,6 +9,7 @@
package com.horcrux.svg;
import android.graphics.Matrix;
import android.view.View;
import com.facebook.infer.annotation.Assertions;
@@ -990,8 +991,10 @@ class RenderableViewManager extends ViewGroupManager<VirtualView> {
resetTransformProperty(node);
} else {
setTransformProperty(node, matrix);
node.mTransform = node.getMatrix();
}
Matrix m = node.getMatrix();
node.mTransform = m;
node.mTransformInvertible = m.invert(node.mInvTransform);
}
@ReactProp(name = "propList")
@@ -971,12 +971,13 @@ class TSpanView extends TextView {
if (mContent == null) {
return super.hitTest(src);
}
if (mPath == null || !mInvertible) {
if (mPath == null || !mInvertible || !mTransformInvertible) {
return -1;
}
float[] dst = new float[2];
mInvMatrix.mapPoints(dst, src);
mInvTransform.mapPoints(dst, src);
int x = Math.round(dst[0]);
int y = Math.round(dst[1]);
@@ -81,12 +81,13 @@ class UseView extends RenderableView {
@Override
int hitTest(float[] src) {
if (!mInvertible) {
if (!mInvertible || !mTransformInvertible) {
return -1;
}
float[] dst = new float[2];
mInvMatrix.mapPoints(dst, src);
mInvTransform.mapPoints(dst, src);
VirtualView template = getSvgView().getDefinedTemplate(mHref);
int hitChild = template.hitTest(dst);
@@ -62,7 +62,9 @@ abstract public class VirtualView extends ViewGroup {
Matrix mMatrix = new Matrix();
Matrix mTransform = new Matrix();
Matrix mInvMatrix = new Matrix();
Matrix mInvTransform = new Matrix();
boolean mInvertible = true;
boolean mTransformInvertible = true;
private RectF mClientRect;
private int mClipRule;
+2 -2
View File
@@ -81,8 +81,7 @@
{
CGRect clipBounds = CGContextGetClipBoundingBox(context);
clipBounds = CGRectApplyAffineTransform(clipBounds, self.matrix);
CGAffineTransform transform = CATransform3DGetAffineTransform(self.layer.transform);
clipBounds = CGRectApplyAffineTransform(clipBounds, transform);
clipBounds = CGRectApplyAffineTransform(clipBounds, self.transform);
CGFloat width = CGRectGetWidth(clipBounds);
CGFloat height = CGRectGetHeight(clipBounds);
@@ -128,6 +127,7 @@
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
if (self.clipPath) {
RNSVGClipPath *clipNode = (RNSVGClipPath*)[self.svgView getDefinedClipPath:self.clipPath];
+21 -22
View File
@@ -211,30 +211,29 @@
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint transformed = point;
if (self.align) {
CGPoint transformed = CGPointApplyAffineTransform(point, _invviewBoxTransform);
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
if (![node isKindOfClass:[RNSVGNode class]]) {
continue;
}
if (event) {
node.active = NO;
} else if (node.active) {
return node;
}
UIView *hitChild = [node hitTest:transformed withEvent:event];
if (hitChild) {
node.active = YES;
return (node.responsible || (node != hitChild)) ? hitChild : self;
}
}
return nil;
} else {
return [super hitTest:point withEvent:event];
transformed = CGPointApplyAffineTransform(transformed, _invviewBoxTransform);
}
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
if (![node isKindOfClass:[RNSVGNode class]]) {
continue;
}
if (event) {
node.active = NO;
} else if (node.active) {
return node;
}
UIView *hitChild = [node hitTest:transformed withEvent:event];
if (hitChild) {
node.active = YES;
return (node.responsible || (node != hitChild)) ? hitChild : self;
}
}
return nil;
}
+2 -1
View File
@@ -73,7 +73,8 @@
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
const CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
RNSVGNode const* template = [self.svgView getDefinedTemplate:self.href];
if (event) {
self.active = NO;
+1
View File
@@ -34,6 +34,7 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
@property (nonatomic, assign) BOOL responsible;
@property (nonatomic, assign) CGAffineTransform matrix;
@property (nonatomic, assign) CGAffineTransform invmatrix;
@property (nonatomic, assign) CGAffineTransform invTransform;
@property (nonatomic, assign) BOOL active;
@property (nonatomic, assign) CGPathRef path;
@property (nonatomic, assign) CGRect clientRect;
+1
View File
@@ -35,6 +35,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
{
if (self = [super init]) {
self.opacity = 1;
self.invTransform = CGAffineTransformIdentity;
}
return self;
}
+2 -2
View File
@@ -169,8 +169,7 @@ UInt32 saturate(CGFloat value) {
// This needs to be painted on a layer before being composited.
CGContextSaveGState(context);
CGContextConcatCTM(context, self.matrix);
CGAffineTransform transform = CATransform3DGetAffineTransform(self.layer.transform);
CGContextConcatCTM(context, transform);
CGContextConcatCTM(context, self.transform);
CGContextSetAlpha(context, self.opacity);
[self beginTransparencyLayer:context];
@@ -421,6 +420,7 @@ UInt32 saturate(CGFloat value) {
}
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
transformed = CGPointApplyAffineTransform(transformed, self.invTransform);
BOOL evenodd = self.fillRule == kRNSVGCGFCRuleEvenodd;
if (!CGPathContainsPoint(_hitArea, nil, transformed, evenodd) &&
+4 -3
View File
@@ -156,9 +156,10 @@ RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
RCT_CUSTOM_VIEW_PROPERTY(transform, CATransform3D, RNSVGNode)
{
view.layer.transform = json ? [RNSVGNodeManager CATransform3D:json] : defaultView.layer.transform;
// TODO: Improve this by enabling edge antialiasing only for transforms with rotation or skewing
view.layer.allowsEdgeAntialiasing = !CATransform3DIsIdentity(view.layer.transform);
CATransform3D transform3d = json ? [RNSVGNodeManager CATransform3D:json] : defaultView.layer.transform;
CGAffineTransform transform = CATransform3DGetAffineTransform(transform3d);
view.invTransform = CGAffineTransformInvert(transform);
view.transform = transform;
[view invalidate];
}
RCT_EXPORT_VIEW_PROPERTY(mask, NSString)