diff --git a/android/src/main/java/com/horcrux/svg/GroupShadowNode.java b/android/src/main/java/com/horcrux/svg/GroupShadowNode.java index 86b81e69..e565ecf9 100644 --- a/android/src/main/java/com/horcrux/svg/GroupShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/GroupShadowNode.java @@ -76,13 +76,17 @@ public class GroupShadowNode extends RenderableShadowNode { return hitSelf; } - Matrix combinedMatrix = new Matrix(); + Matrix groupMatrix = new Matrix(mMatrix); if (matrix != null) { - combinedMatrix.postConcat(matrix); + groupMatrix.postConcat(matrix); } - combinedMatrix.postConcat(mMatrix); + Path clipPath = getClipPath(); + + if (clipPath != null && !pathContainsPoint(clipPath, groupMatrix, point)) { + return -1; + } for (int i = getChildCount() - 1; i >= 0; i--) { ReactShadowNode child = getChildAt(i); @@ -92,9 +96,9 @@ public class GroupShadowNode extends RenderableShadowNode { VirtualNode node = (VirtualNode) child; - int viewTag = node.hitTest(point, combinedMatrix); - if (viewTag != -1) { - return (node.isResponsible() || viewTag != child.getReactTag()) ? viewTag : getReactTag(); + int hitChild = node.hitTest(point, groupMatrix); + if (hitChild != -1) { + return (node.isResponsible() || hitChild != child.getReactTag()) ? hitChild : getReactTag(); } } diff --git a/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java b/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java index d3bd09f6..a12f4914 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RenderableShadowNode.java @@ -19,6 +19,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.graphics.RectF; +import android.graphics.Region; import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Arguments; @@ -294,62 +295,35 @@ abstract public class RenderableShadowNode extends VirtualNode { return -1; } -// Bitmap bitmap = Bitmap.createBitmap( -// mCanvasWidth, -// mCanvasHeight, -// Bitmap.Config.ARGB_8888); -// -// Canvas canvas = new Canvas(bitmap); -// -// if (matrix != null) { -// canvas.concat(matrix); -// } -// -// canvas.concat(mMatrix); -// -// Paint paint = new Paint(); -// clip(canvas, paint); -// setHitTestFill(paint); -// canvas.drawPath(mPath, paint); -// -// if (setHitTestStroke(paint)) { -// canvas.drawPath(mPath, paint); -// } -// -// canvas.setBitmap(bitmap); -// try { -// if (bitmap.getPixel(point.x, point.y) != 0) { -// return getReactTag(); -// } -// } catch (Exception e) { -// -// return -1; -// } finally { -// bitmap.recycle(); -// } - return -1; - } + Matrix pathMatrix = new Matrix(mMatrix); - protected void setHitTestFill(Paint paint) { - paint.reset(); - paint.setARGB(255, 0, 0, 0); - paint.setFlags(Paint.ANTI_ALIAS_FLAG); - paint.setStyle(Paint.Style.FILL); - } - - protected boolean setHitTestStroke(Paint paint) { - if (mStrokeWidth == 0) { - return false; + if (matrix != null) { + pathMatrix.postConcat(matrix); } - paint.reset(); - paint.setARGB(255, 0, 0, 0); - paint.setFlags(Paint.ANTI_ALIAS_FLAG); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(mStrokeWidth * mScale); - paint.setStrokeCap(mStrokeLinecap); - paint.setStrokeJoin(mStrokeLinejoin); - return true; + if (pathContainsPoint(mPath, pathMatrix, point)) { + Path clipPath = getClipPath(); + if (clipPath != null && !pathContainsPoint(clipPath, pathMatrix, point)) { + return -1; + } + + return getReactTag(); + } else{ + return -1; + } + } + + protected boolean pathContainsPoint(Path path, Matrix matrix, Point point) { + Path copy = new Path(path); + + copy.transform(matrix); + + RectF rectF = new RectF(); + copy.computeBounds(rectF, true); + Region region = new Region(); + region.setPath(copy, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom)); + + return region.contains(point.x, point.y); } @Override diff --git a/android/src/main/java/com/horcrux/svg/VirtualNode.java b/android/src/main/java/com/horcrux/svg/VirtualNode.java index 0a5bb928..f8c71a3d 100644 --- a/android/src/main/java/com/horcrux/svg/VirtualNode.java +++ b/android/src/main/java/com/horcrux/svg/VirtualNode.java @@ -48,6 +48,7 @@ public abstract class VirtualNode extends LayoutShadowNode { protected String mName; private SvgViewShadowNode mSvgShadowNode; + private Path mCachedClipPath; public VirtualNode() { mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density; @@ -141,8 +142,12 @@ public abstract class VirtualNode extends LayoutShadowNode { markUpdated(); } + protected @Nullable Path getClipPath() { + return mCachedClipPath; + } + protected @Nullable Path getClipPath(Canvas canvas, Paint paint) { - if (mClipPath != null) { + if (mClipPath != null && mCachedClipPath == null) { VirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPath); if (node != null) { @@ -156,13 +161,13 @@ public abstract class VirtualNode extends LayoutShadowNode { default: FLog.w(ReactConstants.TAG, "RNSVG: clipRule: " + mClipRule + " unrecognized"); } - return clipPath; + mCachedClipPath = clipPath; } else { FLog.w(ReactConstants.TAG, "RNSVG: Undefined clipPath: " + mClipPath); } } - return null; + return getClipPath(); } protected void clip(Canvas canvas, Paint paint) { diff --git a/ios/RNSVGRenderable.m b/ios/RNSVGRenderable.m index 046c98e8..021162d0 100644 --- a/ios/RNSVGRenderable.m +++ b/ios/RNSVGRenderable.m @@ -259,7 +259,7 @@ // hitTest delagate - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - return [self hitTest:point withEvent:event withTransform:CGAffineTransformMakeRotation(0)]; + return [self hitTest:point withEvent:event withTransform:CGAffineTransformIdentity]; } - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event withTransform:(CGAffineTransform)transform