diff --git a/Example/src/examples/Markers.tsx b/Example/src/examples/Markers.tsx index c0ecdbf8e..95447d47d 100644 --- a/Example/src/examples/Markers.tsx +++ b/Example/src/examples/Markers.tsx @@ -8,9 +8,10 @@ import { Ellipse, Line, Polygon, + Path, } from 'react-native-svg'; -class CircleExample extends Component { +class EllipseExample extends Component { static title = 'Circle shaped marker on ellipse'; render() { return ( @@ -47,7 +48,7 @@ class CircleExample extends Component { } } -class StrokeCircle extends Component { +class LineExample extends Component { static title = 'Triangle shaped marker on line'; render() { return ( @@ -81,7 +82,7 @@ class StrokeCircle extends Component { } } -class StrokeOpacityCircle extends Component { +class CircleExample extends Component { static title = 'Rect shaped marker on circle'; render() { return ( @@ -111,7 +112,7 @@ class StrokeOpacityCircle extends Component { } } -class PieCircle extends Component { +class RectExample extends Component { static title = 'Ellipse shaped marker on rect'; render() { return ( @@ -119,7 +120,7 @@ class PieCircle extends Component { @@ -141,7 +142,7 @@ class PieCircle extends Component { height="30" fill="none" stroke="blue" - strokeWidth="5" + strokeWidth="1" marker="url(#selection)" /> @@ -149,11 +150,69 @@ class PieCircle extends Component { } } +class PathExample extends Component { + static title = 'Path shaped marker on line'; + render() { + return ( + + + + + + + + + ); + } +} + const icon = ( - - + + + + + + + ); -const samples = [CircleExample, StrokeCircle, StrokeOpacityCircle, PieCircle]; +const samples = [ + EllipseExample, + LineExample, + CircleExample, + RectExample, + PathExample, +]; export {icon, samples}; diff --git a/FabricExample/src/App.tsx b/FabricExample/src/App.tsx index 69559132c..f811ee631 100644 --- a/FabricExample/src/App.tsx +++ b/FabricExample/src/App.tsx @@ -113,6 +113,7 @@ const names: (keyof typeof examples)[] = [ 'PanResponder', 'Reusable', 'Transforms', + 'Markers', ]; const initialState = { diff --git a/FabricExample/src/examples.tsx b/FabricExample/src/examples.tsx index 908ed89b1..f7e745021 100644 --- a/FabricExample/src/examples.tsx +++ b/FabricExample/src/examples.tsx @@ -16,6 +16,7 @@ import * as Reusable from './examples/Reusable'; import * as TouchEvents from './examples/TouchEvents'; import * as PanResponder from './examples/PanResponder'; import * as Transforms from './examples/Transforms'; +import * as Markers from './examples/Markers'; export { Svg, @@ -36,4 +37,5 @@ export { Reusable, PanResponder, Transforms, + Markers, }; diff --git a/FabricExample/src/examples/Markers.tsx b/FabricExample/src/examples/Markers.tsx new file mode 100644 index 000000000..95447d47d --- /dev/null +++ b/FabricExample/src/examples/Markers.tsx @@ -0,0 +1,218 @@ +import React, {Component} from 'react'; +import { + Svg, + Circle, + Defs, + Marker, + Rect, + Ellipse, + Line, + Polygon, + Path, +} from 'react-native-svg'; + +class EllipseExample extends Component { + static title = 'Circle shaped marker on ellipse'; + render() { + return ( + + + + + + + + + ); + } +} + +class LineExample extends Component { + static title = 'Triangle shaped marker on line'; + render() { + return ( + + + + + + + + + ); + } +} + +class CircleExample extends Component { + static title = 'Rect shaped marker on circle'; + render() { + return ( + + + + + + + + + ); + } +} + +class RectExample extends Component { + static title = 'Ellipse shaped marker on rect'; + render() { + return ( + + + + + + + + + ); + } +} + +class PathExample extends Component { + static title = 'Path shaped marker on line'; + render() { + return ( + + + + + + + + + ); + } +} + +const icon = ( + + + + + + + + +); + +const samples = [ + EllipseExample, + LineExample, + CircleExample, + RectExample, + PathExample, +]; +export {icon, samples}; diff --git a/android/build.gradle b/android/build.gradle index 209e7256b..5dfc225ad 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,10 +7,10 @@ buildscript { mavenCentral() google() } - + dependencies { - classpath("com.android.tools.build:gradle:3.6.1") - classpath "com.diffplug.spotless:spotless-plugin-gradle:5.15.0" + classpath("com.android.tools.build:gradle:7.4.2") + classpath "com.diffplug.spotless:spotless-plugin-gradle:6.17.0" } } } @@ -39,8 +39,10 @@ def safeExtGet(prop, fallback) { android { compileSdkVersion safeExtGet('compileSdkVersion', 28) - namespace "com.horcrux.svg" - + def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION + if (agpVersion.tokenize('.')[0].toInteger() >= 7) { + namespace "com.horcrux.svg" + } // Used to override the NDK path/version on internal CI or by allowing // users to customize the NDK path/version from their root project (e.g. for M1 support) if (rootProject.hasProperty("ndkPath")) { @@ -55,7 +57,7 @@ android { //noinspection OldTargetApi targetSdkVersion safeExtGet('targetSdkVersion', 28) buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() - + consumerProguardFiles 'proguard-rules.pro' } lintOptions { @@ -66,7 +68,7 @@ android { java { if (!isNewArchitectureEnabled()) { srcDirs += [ - "src/paper/java", + "src/paper/java", "build/generated/source/codegen/java" ] } diff --git a/android/src/main/java/com/horcrux/svg/PathView.java b/android/src/main/java/com/horcrux/svg/PathView.java index eaa4c918b..06829bd00 100644 --- a/android/src/main/java/com/horcrux/svg/PathView.java +++ b/android/src/main/java/com/horcrux/svg/PathView.java @@ -27,6 +27,12 @@ public PathView(ReactContext reactContext) { public void setD(String d) { mPath = PathParser.parse(d); elements = PathParser.elements; + for (PathElement elem : elements) { + for (Point point : elem.points) { + point.x *= mScale; + point.y *= mScale; + } + } invalidate(); } diff --git a/android/src/main/java/com/horcrux/svg/SvgView.java b/android/src/main/java/com/horcrux/svg/SvgView.java index b14de9755..b49dce2db 100644 --- a/android/src/main/java/com/horcrux/svg/SvgView.java +++ b/android/src/main/java/com/horcrux/svg/SvgView.java @@ -74,7 +74,7 @@ public void setId(int id) { } @Override - public void onInitializeAccessibilityNodeInfo (AccessibilityNodeInfo info) { + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); Rect r = new Rect(); diff --git a/android/src/main/java/com/horcrux/svg/VirtualView.java b/android/src/main/java/com/horcrux/svg/VirtualView.java index 5753288f5..c414af236 100644 --- a/android/src/main/java/com/horcrux/svg/VirtualView.java +++ b/android/src/main/java/com/horcrux/svg/VirtualView.java @@ -7,9 +7,9 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; -import android.graphics.Rect; import android.view.View; import android.view.ViewParent; import android.view.accessibility.AccessibilityNodeInfo; @@ -23,7 +23,6 @@ import com.facebook.react.uimanager.OnLayoutEvent; import com.facebook.react.uimanager.PointerEvents; import com.facebook.react.uimanager.UIManagerHelper; -import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.views.view.ReactViewGroup; import java.util.ArrayList; @@ -110,29 +109,28 @@ void setPointerEvents(PointerEvents pointerEvents) { } @Override - public void onInitializeAccessibilityNodeInfo (AccessibilityNodeInfo info) { + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); if (mClientRect != null) { - SvgView root = getSvgView(); - - int[] rootPositionOnScreen = new int[2]; - getSvgView().getLocationOnScreen(rootPositionOnScreen); - Rect infoBoundsInScreen = new Rect(); - infoBoundsInScreen.left = rootPositionOnScreen[0] + (int) Math.floor(mClientRect.left); - infoBoundsInScreen.top = rootPositionOnScreen[1] + (int) Math.floor(mClientRect.top); - infoBoundsInScreen.right = infoBoundsInScreen.left + (int) Math.ceil(mClientRect.width()); - infoBoundsInScreen.bottom = infoBoundsInScreen.top + (int) Math.ceil(mClientRect.height()); + SvgView root = getSvgView(); - Rect rootVisibleRect = new Rect(); - boolean isRootVisible = root.getGlobalVisibleRect(rootVisibleRect); - boolean infoIsVisibleToUser = isRootVisible && infoBoundsInScreen.intersect(rootVisibleRect); + int[] rootPositionOnScreen = new int[2]; + getSvgView().getLocationOnScreen(rootPositionOnScreen); + Rect infoBoundsInScreen = new Rect(); + infoBoundsInScreen.left = rootPositionOnScreen[0] + (int) Math.floor(mClientRect.left); + infoBoundsInScreen.top = rootPositionOnScreen[1] + (int) Math.floor(mClientRect.top); + infoBoundsInScreen.right = infoBoundsInScreen.left + (int) Math.ceil(mClientRect.width()); + infoBoundsInScreen.bottom = infoBoundsInScreen.top + (int) Math.ceil(mClientRect.height()); + Rect rootVisibleRect = new Rect(); + boolean isRootVisible = root.getGlobalVisibleRect(rootVisibleRect); + boolean infoIsVisibleToUser = isRootVisible && infoBoundsInScreen.intersect(rootVisibleRect); - String infoClassName = this.getClass().getCanonicalName(); - info.setBoundsInScreen(infoBoundsInScreen); - info.setClassName(infoClassName); - info.setVisibleToUser(infoIsVisibleToUser); + String infoClassName = this.getClass().getCanonicalName(); + info.setBoundsInScreen(infoBoundsInScreen); + info.setClassName(infoClassName); + info.setVisibleToUser(infoIsVisibleToUser); } } @@ -599,7 +597,8 @@ void setClientRect(RectF rect) { setRight(right); setBottom(bottom); } - EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(mContext, getId()); + EventDispatcher eventDispatcher = + UIManagerHelper.getEventDispatcherForReactTag(mContext, getId()); if (eventDispatcher != null) { eventDispatcher.dispatchEvent(OnLayoutEvent.obtain(this.getId(), left, top, width, height)); }