mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-06 07:06:11 +00:00
feat: use codegenNativeComponent to import native views (#1847)
Changed `requireNativeComponent` to `codegenNativeComponent` so that upcoming changes (Static View Configs, Bridgeless Mode and idk what more) in `react-native` are available in the library. Also, types and native components are now taken directly from `fabric` folder to make sure the values passed to the native components are the ones defined in props. It should work on all supported versions since `codegenNativeComponent` function exists from RN v. 0.61.0. Suggested by @RSNara and @cipolleschi Reason for [`5394bbb` (#1847)](5394bbbced): - on `Paper`, `Animated` uses `setNativeProps` method when we set `useNativeDriver` to `false`, and does not rerender the component. Therefore, new transform lands only in `SvgView` and is parsed in `RCTViewManager.m` . - on `Fabric`, the same code makes the components rerender. Due to this, information about new transform is passed to the `SvgView` child: `G` , making it apply translations from the transform in its `updateProps` method. - other than `Animated` use-case, on both archs, if we just passed `transform` prop to `Svg` component, it would end up in double transformations now as well. All of those changes are due to https://github.com/software-mansion/react-native-svg/pull/1895, which added proper parsing of RN style `transform` prop (array of transformations objects) therefore making `G` properly handle `transform` prop passed from `Svg`. Reason for [`19bcb24` (#1847)](19bcb2464b): Same as https://github.com/software-mansion/react-native-screens/pull/1624
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "18.1.0",
|
||||
"react-native": "0.70.0",
|
||||
"react-native": "0.70.4",
|
||||
"react-native-svg": "link:../"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -21,7 +21,7 @@
|
||||
"babel-jest": "^26.6.3",
|
||||
"eslint": "^7.32.0",
|
||||
"jest": "^26.6.3",
|
||||
"metro-react-native-babel-preset": "^0.72.1",
|
||||
"metro-react-native-babel-preset": "0.72.3",
|
||||
"react-test-renderer": "18.1.0"
|
||||
},
|
||||
"jest": {
|
||||
|
||||
@@ -133,26 +133,22 @@ class SvgNativeMethods extends Component {
|
||||
};
|
||||
alert = () => {
|
||||
console.log("PRESSED");
|
||||
this.root.toDataURL(base64 => {
|
||||
this.root?.toDataURL(base64 => {
|
||||
this.setState({
|
||||
base64,
|
||||
});
|
||||
});
|
||||
|
||||
console.log(this.circle.isPointInFill({x: 200, y: 100}));
|
||||
console.log(this.circle.isPointInStroke({x: 200, y: 100}));
|
||||
console.log(this.circle.getTotalLength());
|
||||
console.log(this.circle.getPointAtLength(25));
|
||||
console.log(this.circle.getBBox({fill: true}));
|
||||
console.log(this.circle.getCTM());
|
||||
console.log(this.circle.getScreenCTM());
|
||||
console.log(this.circle?.isPointInFill({x: 200, y: 100}));
|
||||
console.log(this.circle?.isPointInStroke({x: 200, y: 100}));
|
||||
console.log(this.circle?.getTotalLength());
|
||||
console.log(this.circle?.getPointAtLength(25));
|
||||
console.log(this.circle?.getBBox({fill: true}));
|
||||
console.log(this.circle?.getCTM());
|
||||
console.log(this.circle?.getScreenCTM());
|
||||
};
|
||||
root: any;
|
||||
circle: any;
|
||||
|
||||
componentDidMount() {
|
||||
this.alert();
|
||||
}
|
||||
root: Svg | null;
|
||||
circle: Circle | null;
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,12 @@ Pod::Spec.new do |s|
|
||||
s.dependency "RCTRequired"
|
||||
s.dependency "RCTTypeSafety"
|
||||
s.dependency "ReactCommon/turbomodule/core"
|
||||
|
||||
s.subspec "common" do |ss|
|
||||
ss.source_files = "common/cpp/**/*.{cpp,h}"
|
||||
ss.header_dir = "rnsvg"
|
||||
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/common/cpp\"" }
|
||||
end
|
||||
else
|
||||
s.source_files = 'apple/**/*.{h,m,mm}'
|
||||
s.exclude_files = 'apple/Utils/RNSVGFabricConversions.h'
|
||||
|
||||
@@ -61,11 +61,7 @@ android {
|
||||
|
||||
sourceSets.main {
|
||||
java {
|
||||
if (isNewArchitectureEnabled()) {
|
||||
srcDirs += [
|
||||
"src/fabric/java",
|
||||
]
|
||||
} else {
|
||||
if (!isNewArchitectureEnabled()) {
|
||||
srcDirs += [
|
||||
"src/paper/java",
|
||||
"build/generated/source/codegen/java"
|
||||
@@ -92,13 +88,3 @@ dependencies {
|
||||
implementation 'com.facebook.react:react-native:+'
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewArchitectureEnabled()) {
|
||||
react {
|
||||
reactRoot = rootProject.file("../node_modules/react-native/")
|
||||
jsRootDir = file("../src/fabric/")
|
||||
codegenDir = rootProject.file("../node_modules/react-native-codegen/")
|
||||
libraryName = "rnsvg"
|
||||
codegenJavaPackageName = "com.horcrux.rnsvg"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ apply plugin: 'com.diffplug.spotless'
|
||||
|
||||
spotless {
|
||||
java {
|
||||
target 'src/fabric/**/*.java', 'src/main/java/**/*.java', 'src/paper/java/com/horcrux/svg/**/*.java'
|
||||
target 'src/main/java/**/*.java', 'src/paper/java/com/horcrux/svg/**/*.java'
|
||||
googleJavaFormat()
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.horcrux.svg;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.fabric.ComponentFactory;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
@DoNotStrip
|
||||
public class RNSvgComponentsRegistry {
|
||||
static {
|
||||
SoLoader.loadLibrary("rnsvg_modules");
|
||||
}
|
||||
|
||||
@DoNotStrip private final HybridData mHybridData;
|
||||
|
||||
@DoNotStrip
|
||||
private native HybridData initHybrid(ComponentFactory componentFactory);
|
||||
|
||||
@DoNotStrip
|
||||
private RNSvgComponentsRegistry(ComponentFactory componentFactory) {
|
||||
mHybridData = initHybrid(componentFactory);
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public static RNSvgComponentsRegistry register(ComponentFactory componentFactory) {
|
||||
return new RNSvgComponentsRegistry(componentFactory);
|
||||
}
|
||||
}
|
||||
@@ -19,30 +19,35 @@ import android.graphics.Region;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.horcrux.rnsvg.NativeSvgRenderableModuleSpec;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
@ReactModule(name = RNSVGRenderableManager.NAME)
|
||||
class RNSVGRenderableManager extends NativeSvgRenderableModuleSpec {
|
||||
RNSVGRenderableManager(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
public static final String NAME = "RNSVGRenderableModule";
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "RNSVGRenderableManager";
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public boolean isPointInFill(int tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag);
|
||||
@Override
|
||||
public boolean isPointInFill(Double tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag.intValue());
|
||||
if (svg == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -57,8 +62,9 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public boolean isPointInStroke(int tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag);
|
||||
@Override
|
||||
public boolean isPointInStroke(Double tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag.intValue());
|
||||
if (svg == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -82,8 +88,9 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public float getTotalLength(int tag) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag);
|
||||
@Override
|
||||
public double getTotalLength(Double tag) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag.intValue());
|
||||
if (svg == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -103,8 +110,9 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public WritableMap getPointAtLength(int tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag);
|
||||
@Override
|
||||
public WritableMap getPointAtLength(Double tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag.intValue());
|
||||
if (svg == null) {
|
||||
return Arguments.createMap();
|
||||
}
|
||||
@@ -137,8 +145,9 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public WritableMap getBBox(int tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag);
|
||||
@Override
|
||||
public WritableMap getBBox(Double tag, ReadableMap options) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag.intValue());
|
||||
if (svg == null) {
|
||||
return Arguments.createMap();
|
||||
}
|
||||
@@ -187,15 +196,20 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public WritableMap getCTM(int tag) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag);
|
||||
@Override
|
||||
public WritableMap getCTM(Double tag) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag.intValue());
|
||||
if (svg == null) {
|
||||
return Arguments.createMap();
|
||||
}
|
||||
|
||||
float scale = svg.mScale;
|
||||
Matrix ctm = new Matrix(svg.mCTM);
|
||||
Matrix invViewBoxMatrix = svg.getSvgView().mInvViewBoxMatrix;
|
||||
SvgView svgView = svg.getSvgView();
|
||||
if (svgView == null) {
|
||||
throw new RuntimeException("Did not find parent SvgView for view with tag: " + tag);
|
||||
}
|
||||
Matrix invViewBoxMatrix = svgView.mInvViewBoxMatrix;
|
||||
ctm.preConcat(invViewBoxMatrix);
|
||||
|
||||
float[] values = new float[9];
|
||||
@@ -213,8 +227,9 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public WritableMap getScreenCTM(int tag) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag);
|
||||
@Override
|
||||
public WritableMap getScreenCTM(Double tag) {
|
||||
RenderableView svg = RenderableViewManager.getRenderableViewByTag(tag.intValue());
|
||||
if (svg == null) {
|
||||
return Arguments.createMap();
|
||||
}
|
||||
@@ -234,6 +249,7 @@ class RNSVGRenderableManager extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@Override
|
||||
public void getRawResource(String name, Promise promise) {
|
||||
try {
|
||||
ReactApplicationContext context = getReactApplicationContext();
|
||||
|
||||
@@ -134,7 +134,6 @@ import com.facebook.react.viewmanagers.RNSVGTextPathManagerDelegate;
|
||||
import com.facebook.react.viewmanagers.RNSVGTextPathManagerInterface;
|
||||
import com.facebook.react.viewmanagers.RNSVGUseManagerDelegate;
|
||||
import com.facebook.react.viewmanagers.RNSVGUseManagerInterface;
|
||||
import java.util.Locale;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -149,6 +148,12 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
|
||||
mClassName = svgclass.toString();
|
||||
}
|
||||
|
||||
protected ViewManagerDelegate<V> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
|
||||
static class RenderableShadowNode extends LayoutShadowNode {
|
||||
|
||||
@SuppressWarnings({"unused", "EmptyMethod"})
|
||||
@@ -455,14 +460,9 @@ class VirtualViewManager<V extends VirtualView> extends ViewGroupManager<Virtual
|
||||
|
||||
@ReactProp(name = ViewProps.POINTER_EVENTS)
|
||||
public void setPointerEvents(V view, @Nullable String pointerEventsStr) {
|
||||
if (pointerEventsStr == null) {
|
||||
view.setPointerEvents(PointerEvents.AUTO);
|
||||
} else {
|
||||
PointerEvents pointerEvents =
|
||||
PointerEvents.valueOf(pointerEventsStr.toUpperCase(Locale.US).replace("-", "_"));
|
||||
PointerEvents pointerEvents = PointerEvents.parsePointerEvents(pointerEventsStr);
|
||||
view.setPointerEvents(pointerEvents);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "onLayout")
|
||||
public void setOnLayout(V node, boolean onLayout) {
|
||||
@@ -733,11 +733,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGGroupManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<GroupView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGGroup";
|
||||
}
|
||||
|
||||
static class PathViewManager extends RenderableViewManager<PathView>
|
||||
@@ -747,11 +743,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGPathManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<PathView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGPath";
|
||||
|
||||
@ReactProp(name = "d")
|
||||
public void setD(PathView node, String d) {
|
||||
@@ -828,10 +820,6 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
view.setMethod(value);
|
||||
}
|
||||
|
||||
public void setTextAnchor(K view, @Nullable String value) {
|
||||
// TODO: is it available on Android?
|
||||
}
|
||||
|
||||
public void setDx(K view, @Nullable ReadableArray value) {
|
||||
view.setDeltaX(value);
|
||||
}
|
||||
@@ -840,14 +828,6 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
view.setDeltaY(value);
|
||||
}
|
||||
|
||||
public void setPositionX(K view, @Nullable ReadableArray value) {
|
||||
view.setPositionX(value);
|
||||
}
|
||||
|
||||
public void setPositionY(K view, @Nullable ReadableArray value) {
|
||||
view.setPositionY(value);
|
||||
}
|
||||
|
||||
public void setX(K view, @Nullable ReadableArray value) {
|
||||
view.setPositionX(value);
|
||||
}
|
||||
@@ -892,11 +872,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGTextManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<TextView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGText";
|
||||
|
||||
TextViewManager(SVGClass svgClass) {
|
||||
super(svgClass);
|
||||
@@ -911,17 +887,13 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGTSpanManagerDelegate(this);
|
||||
}
|
||||
|
||||
public static final String REACT_CLASS = "RNSVGTSpan";
|
||||
|
||||
TSpanViewManager(SVGClass svgClass) {
|
||||
super(svgClass);
|
||||
mDelegate = new RNSVGTSpanManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<TSpanView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
|
||||
@ReactProp(name = "content")
|
||||
public void setContent(TSpanView node, @Nullable String content) {
|
||||
node.setContent(content);
|
||||
@@ -935,17 +907,13 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGTextPathManagerDelegate(this);
|
||||
}
|
||||
|
||||
public static final String REACT_CLASS = "RNSVGTextPath";
|
||||
|
||||
TextPathViewManager(SVGClass svgClass) {
|
||||
super(svgClass);
|
||||
mDelegate = new RNSVGTextPathManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<TextPathView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
|
||||
@ReactProp(name = "href")
|
||||
public void setHref(TextPathView node, String href) {
|
||||
node.setHref(href);
|
||||
@@ -998,11 +966,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGImageManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<ImageView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGImage";
|
||||
|
||||
@ReactProp(name = "x")
|
||||
public void setX(ImageView node, Dynamic x) {
|
||||
@@ -1083,11 +1047,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGCircleManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<CircleView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGCircle";
|
||||
|
||||
@ReactProp(name = "cx")
|
||||
public void setCx(CircleView node, Dynamic cx) {
|
||||
@@ -1139,11 +1099,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGEllipseManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<EllipseView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGEllipse";
|
||||
|
||||
@ReactProp(name = "cx")
|
||||
public void setCx(EllipseView node, Dynamic cx) {
|
||||
@@ -1210,11 +1166,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGLineManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<LineView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGLine";
|
||||
|
||||
@ReactProp(name = "x1")
|
||||
public void setX1(LineView node, Dynamic x1) {
|
||||
@@ -1281,11 +1233,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGRectManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<RectView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGRect";
|
||||
|
||||
@ReactProp(name = "x")
|
||||
public void setX(RectView node, Dynamic x) {
|
||||
@@ -1379,11 +1327,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGClipPathManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<ClipPathView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGClipPath";
|
||||
}
|
||||
|
||||
static class DefsViewManager extends VirtualViewManager<DefsView>
|
||||
@@ -1394,11 +1338,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGDefsManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<DefsView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGDefs";
|
||||
}
|
||||
|
||||
static class UseViewManager extends RenderableViewManager<UseView>
|
||||
@@ -1409,11 +1349,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGUseManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<UseView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGUse";
|
||||
|
||||
@ReactProp(name = "href")
|
||||
public void setHref(UseView node, String href) {
|
||||
@@ -1484,11 +1420,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGSymbolManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<SymbolView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGSymbol";
|
||||
|
||||
@ReactProp(name = "minX")
|
||||
public void setMinX(SymbolView node, float minX) {
|
||||
@@ -1528,11 +1460,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGPatternManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<PatternView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGPattern";
|
||||
|
||||
@ReactProp(name = "x")
|
||||
public void setX(PatternView node, Dynamic x) {
|
||||
@@ -1643,11 +1571,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGMaskManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<MaskView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGMask";
|
||||
|
||||
@ReactProp(name = "x")
|
||||
public void setX(MaskView node, Dynamic x) {
|
||||
@@ -1723,11 +1647,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGForeignObjectManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<ForeignObjectView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGForeignObject";
|
||||
|
||||
@ReactProp(name = "x")
|
||||
public void setX(ForeignObjectView node, Dynamic x) {
|
||||
@@ -1793,11 +1713,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGMarkerManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<MarkerView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGMarker";
|
||||
|
||||
@ReactProp(name = "refX")
|
||||
public void setRefX(MarkerView node, Dynamic refX) {
|
||||
@@ -1904,11 +1820,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGLinearGradientManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<RectView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGLinearGradient";
|
||||
|
||||
@ReactProp(name = "x1")
|
||||
public void setX1(LinearGradientView node, Dynamic x1) {
|
||||
@@ -1990,11 +1902,7 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
mDelegate = new RNSVGRadialGradientManagerDelegate(this);
|
||||
}
|
||||
|
||||
private final ViewManagerDelegate<RectView> mDelegate;
|
||||
|
||||
protected ViewManagerDelegate getDelegate() {
|
||||
return mDelegate;
|
||||
}
|
||||
public static final String REACT_CLASS = "RNSVGRadialGradient";
|
||||
|
||||
@ReactProp(name = "fx")
|
||||
public void setFx(RadialGradientView node, Dynamic fx) {
|
||||
|
||||
@@ -10,50 +10,156 @@ package com.horcrux.svg;
|
||||
|
||||
import static com.horcrux.svg.RenderableViewManager.*;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.TurboReactPackage;
|
||||
import com.facebook.react.ViewManagerOnDemandReactPackage;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.ModuleSpec;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.module.annotations.ReactModuleList;
|
||||
import com.facebook.react.module.model.ReactModuleInfo;
|
||||
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
||||
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class SvgPackage implements ReactPackage {
|
||||
@ReactModuleList(
|
||||
nativeModules = {
|
||||
SvgViewModule.class,
|
||||
RNSVGRenderableManager.class,
|
||||
})
|
||||
public class SvgPackage extends TurboReactPackage implements ViewManagerOnDemandReactPackage {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
|
||||
return Arrays.<ViewManager>asList(
|
||||
new GroupViewManager(),
|
||||
new PathViewManager(),
|
||||
new CircleViewManager(),
|
||||
new EllipseViewManager(),
|
||||
new LineViewManager(),
|
||||
new RectViewManager(),
|
||||
new TextViewManager(),
|
||||
new TSpanViewManager(),
|
||||
new TextPathViewManager(),
|
||||
new ImageViewManager(),
|
||||
new ClipPathViewManager(),
|
||||
new DefsViewManager(),
|
||||
new UseViewManager(),
|
||||
new SymbolManager(),
|
||||
new LinearGradientManager(),
|
||||
new RadialGradientManager(),
|
||||
new PatternManager(),
|
||||
new MaskManager(),
|
||||
new ForeignObjectManager(),
|
||||
new MarkerManager(),
|
||||
new SvgViewManager());
|
||||
private @Nullable Map<String, ModuleSpec> mViewManagers;
|
||||
|
||||
private Map<String, ModuleSpec> getViewManagersMap(final ReactApplicationContext reactContext) {
|
||||
if (mViewManagers == null) {
|
||||
Map<String, ModuleSpec> specs = MapBuilder.newHashMap();
|
||||
specs.put(
|
||||
GroupViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new GroupViewManager()));
|
||||
specs.put(
|
||||
PathViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new PathViewManager()));
|
||||
specs.put(
|
||||
CircleViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new CircleViewManager()));
|
||||
specs.put(
|
||||
EllipseViewManager.REACT_CLASS,
|
||||
ModuleSpec.viewManagerSpec(() -> new EllipseViewManager()));
|
||||
specs.put(
|
||||
LineViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new LineViewManager()));
|
||||
specs.put(
|
||||
RectViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new RectViewManager()));
|
||||
specs.put(
|
||||
TextViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new TextViewManager()));
|
||||
specs.put(
|
||||
TSpanViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new TSpanViewManager()));
|
||||
specs.put(
|
||||
TextPathViewManager.REACT_CLASS,
|
||||
ModuleSpec.viewManagerSpec(() -> new TextPathViewManager()));
|
||||
specs.put(
|
||||
ImageViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new ImageViewManager()));
|
||||
specs.put(
|
||||
ClipPathViewManager.REACT_CLASS,
|
||||
ModuleSpec.viewManagerSpec(() -> new ClipPathViewManager()));
|
||||
specs.put(
|
||||
DefsViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new DefsViewManager()));
|
||||
specs.put(UseViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new UseViewManager()));
|
||||
specs.put(SymbolManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new SymbolManager()));
|
||||
specs.put(
|
||||
LinearGradientManager.REACT_CLASS,
|
||||
ModuleSpec.viewManagerSpec(() -> new LinearGradientManager()));
|
||||
specs.put(
|
||||
RadialGradientManager.REACT_CLASS,
|
||||
ModuleSpec.viewManagerSpec(() -> new RadialGradientManager()));
|
||||
specs.put(PatternManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new PatternManager()));
|
||||
specs.put(MaskManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new MaskManager()));
|
||||
specs.put(
|
||||
ForeignObjectManager.REACT_CLASS,
|
||||
ModuleSpec.viewManagerSpec(() -> new ForeignObjectManager()));
|
||||
specs.put(MarkerManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new MarkerManager()));
|
||||
specs.put(SvgViewManager.REACT_CLASS, ModuleSpec.viewManagerSpec(() -> new SvgViewManager()));
|
||||
mViewManagers = specs;
|
||||
}
|
||||
return mViewManagers;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext) {
|
||||
return Arrays.<NativeModule>asList(
|
||||
new SvgViewModule(reactContext), new RNSVGRenderableManager(reactContext));
|
||||
public Collection<String> getViewManagerNames(ReactApplicationContext reactContext) {
|
||||
return getViewManagersMap(reactContext).keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ModuleSpec> getViewManagers(ReactApplicationContext reactContext) {
|
||||
return new ArrayList<>(getViewManagersMap(reactContext).values());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public @Nullable ViewManager createViewManager(
|
||||
ReactApplicationContext reactContext, String viewManagerName) {
|
||||
ModuleSpec spec = getViewManagersMap(reactContext).get(viewManagerName);
|
||||
return spec != null ? (ViewManager) spec.getProvider().get() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NativeModule getModule(String name, @Nonnull ReactApplicationContext reactContext) {
|
||||
switch (name) {
|
||||
case SvgViewModule.NAME:
|
||||
return new SvgViewModule(reactContext);
|
||||
case RNSVGRenderableManager.NAME:
|
||||
return new RNSVGRenderableManager(reactContext);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
||||
try {
|
||||
Class<?> reactModuleInfoProviderClass =
|
||||
Class.forName("com.horcrux.svg.SvgPackage$$ReactModuleInfoProvider");
|
||||
return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// ReactModuleSpecProcessor does not run at build-time. Create this ReactModuleInfoProvider by
|
||||
// hand.
|
||||
return () -> {
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
|
||||
|
||||
Class<? extends NativeModule>[] moduleList =
|
||||
new Class[] {
|
||||
SvgViewModule.class, RNSVGRenderableManager.class,
|
||||
};
|
||||
|
||||
for (Class<? extends NativeModule> moduleClass : moduleList) {
|
||||
ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
|
||||
|
||||
reactModuleInfoMap.put(
|
||||
reactModule.name(),
|
||||
new ReactModuleInfo(
|
||||
reactModule.name(),
|
||||
moduleClass.getName(),
|
||||
reactModule.canOverrideExistingModule(),
|
||||
reactModule.needsEagerInit(),
|
||||
reactModule.hasConstants(),
|
||||
reactModule.isCxxModule(),
|
||||
TurboModule.class.isAssignableFrom(moduleClass)));
|
||||
}
|
||||
|
||||
return reactModuleInfoMap;
|
||||
};
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException(
|
||||
"No ReactModuleInfoProvider for MyPackage$$ReactModuleInfoProvider", e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -10,13 +10,15 @@ package com.horcrux.svg;
|
||||
|
||||
import android.util.SparseArray;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.DynamicFromObject;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewManagerDelegate;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.viewmanagers.RNSVGSvgViewManagerDelegate;
|
||||
import com.facebook.react.viewmanagers.RNSVGSvgViewManagerInterface;
|
||||
import com.facebook.react.viewmanagers.RNSVGSvgViewAndroidManagerDelegate;
|
||||
import com.facebook.react.viewmanagers.RNSVGSvgViewAndroidManagerInterface;
|
||||
import com.facebook.react.views.view.ReactViewGroup;
|
||||
import com.facebook.react.views.view.ReactViewManager;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -29,9 +31,10 @@ import javax.annotation.Nullable;
|
||||
* ViewManager for RNSVGSvgView React views. Renders as a {@link SvgView} and handles invalidating
|
||||
* the native view on view updates happening in the underlying tree.
|
||||
*/
|
||||
class SvgViewManager extends ReactViewManager implements RNSVGSvgViewManagerInterface<SvgView> {
|
||||
class SvgViewManager extends ReactViewManager
|
||||
implements RNSVGSvgViewAndroidManagerInterface<SvgView> {
|
||||
|
||||
private static final String REACT_CLASS = "RNSVGSvgView";
|
||||
public static final String REACT_CLASS = "RNSVGSvgViewAndroid";
|
||||
|
||||
private static final SparseArray<SvgView> mTagToSvgView = new SparseArray<>();
|
||||
private static final SparseArray<Runnable> mTagToRunnable = new SparseArray<>();
|
||||
@@ -43,7 +46,7 @@ class SvgViewManager extends ReactViewManager implements RNSVGSvgViewManagerInte
|
||||
}
|
||||
|
||||
public SvgViewManager() {
|
||||
mDelegate = new RNSVGSvgViewManagerDelegate(this);
|
||||
mDelegate = new RNSVGSvgViewAndroidManagerDelegate(this);
|
||||
}
|
||||
|
||||
static void setSvgView(int tag, SvgView svg) {
|
||||
@@ -182,4 +185,159 @@ class SvgViewManager extends ReactViewManager implements RNSVGSvgViewManagerInte
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHasTVPreferredFocus(SvgView view, boolean value) {
|
||||
super.setTVPreferredFocus(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderTopEndRadius(SvgView view, float value) {
|
||||
super.setBorderRadius(view, 6, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderBottomStartRadius(SvgView view, float value) {
|
||||
super.setBorderRadius(view, 7, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderBottomColor(SvgView view, @Nullable Integer value) {
|
||||
super.setBorderColor(view, 4, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextFocusDown(SvgView view, int value) {
|
||||
super.nextFocusDown(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderRightColor(SvgView view, @Nullable Integer value) {
|
||||
super.setBorderColor(view, 2, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextFocusRight(SvgView view, int value) {
|
||||
super.nextFocusRight(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderLeftColor(SvgView view, @Nullable Integer value) {
|
||||
super.setBorderColor(view, 1, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderColor(SvgView view, @Nullable Integer value) {
|
||||
super.setBorderColor(view, 0, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoveClippedSubviews(SvgView view, boolean value) {
|
||||
super.setRemoveClippedSubviews(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextFocusForward(SvgView view, int value) {
|
||||
super.nextFocusForward(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextFocusUp(SvgView view, int value) {
|
||||
super.nextFocusUp(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccessible(SvgView view, boolean value) {
|
||||
super.setAccessible(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderStartColor(SvgView view, @Nullable Integer value) {
|
||||
super.setBorderColor(view, 5, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderBottomEndRadius(SvgView view, float value) {
|
||||
super.setBorderRadius(view, 8, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderEndColor(SvgView view, @Nullable Integer value) {
|
||||
super.setBorderColor(view, 6, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocusable(SvgView view, boolean value) {
|
||||
super.setFocusable(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNativeBackgroundAndroid(SvgView view, @Nullable ReadableMap value) {
|
||||
super.setNativeBackground(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderTopStartRadius(SvgView view, float value) {
|
||||
super.setBorderRadius(view, 5, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNativeForegroundAndroid(SvgView view, @Nullable ReadableMap value) {
|
||||
super.setNativeForeground(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackfaceVisibility(SvgView view, @Nullable String value) {
|
||||
super.setBackfaceVisibility(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderStyle(SvgView view, @Nullable String value) {
|
||||
super.setBorderStyle(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNeedsOffscreenAlphaCompositing(SvgView view, boolean value) {
|
||||
super.setNeedsOffscreenAlphaCompositing(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHitSlop(SvgView view, @Nullable ReadableMap value) {
|
||||
super.setHitSlop(view, new DynamicFromObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderTopColor(SvgView view, @Nullable Integer value) {
|
||||
super.setBorderColor(view, 3, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextFocusLeft(SvgView view, int value) {
|
||||
super.nextFocusLeft(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderRadius(SvgView view, double value) {
|
||||
super.setBorderRadius(view, 0, (float) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderTopLeftRadius(SvgView view, double value) {
|
||||
super.setBorderRadius(view, 1, (float) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderTopRightRadius(SvgView view, double value) {
|
||||
super.setBorderRadius(view, 2, (float) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderBottomRightRadius(SvgView view, double value) {
|
||||
super.setBorderRadius(view, 3, (float) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBorderBottomLeftRadius(SvgView view, double value) {
|
||||
super.setBorderRadius(view, 4, (float) value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,21 +10,25 @@ package com.horcrux.svg;
|
||||
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.horcrux.rnsvg.NativeSvgViewModuleSpec;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
class SvgViewModule extends ReactContextBaseJavaModule {
|
||||
@ReactModule(name = SvgViewModule.NAME)
|
||||
class SvgViewModule extends NativeSvgViewModuleSpec {
|
||||
SvgViewModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
public static final String NAME = "RNSVGSvgViewModule";
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "RNSVGSvgViewManager";
|
||||
return NAME;
|
||||
}
|
||||
|
||||
private static void toDataURL(
|
||||
@@ -76,7 +80,8 @@ class SvgViewModule extends ReactContextBaseJavaModule {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ReactMethod
|
||||
public void toDataURL(int tag, ReadableMap options, Callback successCallback) {
|
||||
toDataURL(tag, options, successCallback, 0);
|
||||
@Override
|
||||
public void toDataURL(Double tag, ReadableMap options, Callback successCallback) {
|
||||
toDataURL(tag.intValue(), options, successCallback, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +373,7 @@ public abstract class VirtualView extends ReactViewGroup {
|
||||
|
||||
abstract Path getPath(Canvas canvas, Paint paint);
|
||||
|
||||
@Nullable
|
||||
SvgView getSvgView() {
|
||||
if (svgView != null) {
|
||||
return svgView;
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
SVG_MAIN_THIS_DIR := $(call my-dir)
|
||||
|
||||
include $(SVG_MAIN_THIS_DIR)/../../../build/generated/source/codegen/jni/Android.mk
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_PATH := $(SVG_MAIN_THIS_DIR)
|
||||
LOCAL_MODULE := rnsvg_modules
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni
|
||||
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(GENERATED_SRC_DIR)/codegen/jni/*.cpp)
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(GENERATED_SRC_DIR)/codegen/jni
|
||||
|
||||
# Please note as one of the library listed is libreact_codegen_samplelibrary
|
||||
# This name will be generated as libreact_codegen_<library-name>
|
||||
# where <library-name> is the one you specified in the Gradle configuration
|
||||
LOCAL_SHARED_LIBRARIES := libjsi \
|
||||
libfbjni \
|
||||
libglog \
|
||||
libfolly_runtime \
|
||||
libyoga \
|
||||
libreact_nativemodule_core \
|
||||
libturbomodulejsijni \
|
||||
librrc_view \
|
||||
libreact_render_core \
|
||||
libreact_render_graphics \
|
||||
libfabricjni \
|
||||
libreact_debug \
|
||||
libreact_render_componentregistry \
|
||||
libreact_render_debug \
|
||||
libruntimeexecutor \
|
||||
libreact_render_mapbuffer \
|
||||
libreact_codegen_rncore \
|
||||
libreact_codegen_rnsvg
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
-DLOG_TAG=\"ReactNative\"
|
||||
LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
72
android/src/main/jni/CMakeLists.txt
Normal file
72
android/src/main/jni/CMakeLists.txt
Normal file
@@ -0,0 +1,72 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
set(RNS_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
|
||||
set(RNS_COMMON_DIR ${RNS_ANDROID_DIR}/../common/cpp)
|
||||
set(RNS_GENERATED_DIR ${RNS_ANDROID_DIR}/build/generated)
|
||||
set(RNS_GENERATED_JNI_DIR ${RNS_GENERATED_DIR}/source/codegen/jni)
|
||||
set(RNS_GENERATED_REACT_DIR ${RNS_GENERATED_JNI_DIR}/react/renderer/components/rnsvg)
|
||||
|
||||
add_compile_options(
|
||||
-fexceptions
|
||||
-frtti
|
||||
-std=c++17
|
||||
-Wall
|
||||
-Wpedantic
|
||||
-Wno-gnu-zero-variadic-macro-arguments
|
||||
)
|
||||
|
||||
file(GLOB rnsvg_SRCS CONFIGURE_DEPENDS *.cpp ${RNS_COMMON_DIR}/react/renderer/components/rnsvg/*.cpp)
|
||||
file(GLOB rnsvg_codegen_SRCS CONFIGURE_DEPENDS ${RNS_GENERATED_REACT_DIR}/*cpp)
|
||||
|
||||
add_library(
|
||||
react_codegen_rnsvg
|
||||
SHARED
|
||||
${rnsvg_SRCS}
|
||||
${rnsvg_codegen_SRCS}
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
react_codegen_rnsvg
|
||||
PUBLIC
|
||||
.
|
||||
${RNS_COMMON_DIR}
|
||||
${RNS_GENERATED_JNI_DIR}
|
||||
${RNS_GENERATED_REACT_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
react_codegen_rnsvg
|
||||
fbjni
|
||||
folly_runtime
|
||||
glog
|
||||
jsi
|
||||
react_codegen_rncore
|
||||
react_debug
|
||||
react_nativemodule_core
|
||||
react_render_core
|
||||
react_render_debug
|
||||
react_render_graphics
|
||||
react_render_mapbuffer
|
||||
rrc_view
|
||||
turbomodulejsijni
|
||||
yoga
|
||||
react_render_imagemanager
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
react_codegen_rnsvg
|
||||
PRIVATE
|
||||
-DLOG_TAG=\"ReactNative\"
|
||||
-fexceptions
|
||||
-frtti
|
||||
-std=c++17
|
||||
-Wall
|
||||
)
|
||||
message(WARNING "CMAKE_CURRENT_SORUCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
target_include_directories(
|
||||
${CMAKE_PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include "RNSvgComponentsRegistry.h"
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
return facebook::jni::initialize(vm, [] {
|
||||
facebook::react::RNSvgComponentsRegistry::registerNatives();
|
||||
});
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
#include "RNSvgComponentsRegistry.h"
|
||||
|
||||
#include <CoreComponentsRegistry.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
|
||||
#include <react/renderer/components/rnsvg/ComponentDescriptors.h>
|
||||
#include <react/renderer/mapbuffer/MapBuffer.h>
|
||||
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
RNSvgComponentsRegistry::RNSvgComponentsRegistry(
|
||||
ComponentFactory *delegate)
|
||||
: delegate_(delegate) {}
|
||||
|
||||
std::shared_ptr<ComponentDescriptorProviderRegistry const>
|
||||
RNSvgComponentsRegistry::sharedProviderRegistry() {
|
||||
auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
|
||||
|
||||
// Svg
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGCircleComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGClipPathComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGDefsComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGEllipseComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGForeignObjectComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGGroupComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGImageComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGLinearGradientComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGLineComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGMarkerComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGMaskComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGPathComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGPatternComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGRadialGradientComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGRectComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGSvgViewComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGSymbolComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGTextComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGTextPathComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGTSpanComponentDescriptor>());
|
||||
providerRegistry->add(concreteComponentDescriptorProvider<RNSVGUseComponentDescriptor>());
|
||||
|
||||
return providerRegistry;
|
||||
}
|
||||
|
||||
jni::local_ref<RNSvgComponentsRegistry::jhybriddata>
|
||||
RNSvgComponentsRegistry::initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
ComponentFactory *delegate) {
|
||||
auto instance = makeCxxInstance(delegate);
|
||||
|
||||
auto buildRegistryFunction =
|
||||
[](EventDispatcher::Weak const &eventDispatcher,
|
||||
ContextContainer::Shared const &contextContainer)
|
||||
-> ComponentDescriptorRegistry::Shared {
|
||||
auto registry = RNSvgComponentsRegistry::sharedProviderRegistry()
|
||||
->createComponentDescriptorRegistry(
|
||||
{eventDispatcher, contextContainer});
|
||||
|
||||
return registry;
|
||||
};
|
||||
|
||||
delegate->buildRegistryFunction = buildRegistryFunction;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void RNSvgComponentsRegistry::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", RNSvgComponentsRegistry::initHybrid),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <ComponentFactory.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
|
||||
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RNSvgComponentsRegistry
|
||||
: public facebook::jni::HybridClass<RNSvgComponentsRegistry> {
|
||||
public:
|
||||
constexpr static auto kJavaDescriptor =
|
||||
"Lcom/horcrux/svg/RNSvgComponentsRegistry;";
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
RNSvgComponentsRegistry(ComponentFactory *delegate);
|
||||
|
||||
private:
|
||||
friend HybridBase;
|
||||
|
||||
static std::shared_ptr<ComponentDescriptorProviderRegistry const> sharedProviderRegistry();
|
||||
|
||||
const ComponentFactory *delegate_;
|
||||
|
||||
static jni::local_ref<jhybriddata> initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
ComponentFactory *delegate);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
88
android/src/main/jni/rnsvg.cpp
Normal file
88
android/src/main/jni/rnsvg.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleJniCpp.js
|
||||
*/
|
||||
|
||||
#include "rnsvg.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_isPointInFill(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, BooleanKind, "isPointInFill", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableMap;)Z", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_isPointInStroke(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, BooleanKind, "isPointInStroke", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableMap;)Z", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_getTotalLength(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, NumberKind, "getTotalLength", "(Ljava/lang/Double;)D", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_getPointAtLength(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, "getPointAtLength", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_getBBox(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, "getBBox", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_getCTM(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, "getCTM", "(Ljava/lang/Double;)Lcom/facebook/react/bridge/WritableMap;", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_getScreenCTM(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ObjectKind, "getScreenCTM", "(Ljava/lang/Double;)Lcom/facebook/react/bridge/WritableMap;", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgRenderableModuleSpecJSI_getRawResource(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, PromiseKind, "getRawResource", "(Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
NativeSvgRenderableModuleSpecJSI::NativeSvgRenderableModuleSpecJSI(const JavaTurboModule::InitParams ¶ms)
|
||||
: JavaTurboModule(params) {
|
||||
methodMap_["isPointInFill"] = MethodMetadata {2, __hostFunction_NativeSvgRenderableModuleSpecJSI_isPointInFill};
|
||||
methodMap_["isPointInStroke"] = MethodMetadata {2, __hostFunction_NativeSvgRenderableModuleSpecJSI_isPointInStroke};
|
||||
methodMap_["getTotalLength"] = MethodMetadata {1, __hostFunction_NativeSvgRenderableModuleSpecJSI_getTotalLength};
|
||||
methodMap_["getPointAtLength"] = MethodMetadata {2, __hostFunction_NativeSvgRenderableModuleSpecJSI_getPointAtLength};
|
||||
methodMap_["getBBox"] = MethodMetadata {2, __hostFunction_NativeSvgRenderableModuleSpecJSI_getBBox};
|
||||
methodMap_["getCTM"] = MethodMetadata {1, __hostFunction_NativeSvgRenderableModuleSpecJSI_getCTM};
|
||||
methodMap_["getScreenCTM"] = MethodMetadata {1, __hostFunction_NativeSvgRenderableModuleSpecJSI_getScreenCTM};
|
||||
methodMap_["getRawResource"] = MethodMetadata {1, __hostFunction_NativeSvgRenderableModuleSpecJSI_getRawResource};
|
||||
}
|
||||
static facebook::jsi::Value __hostFunction_NativeSvgViewModuleSpecJSI_toDataURL(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
||||
static jmethodID cachedMethodId = nullptr;
|
||||
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, VoidKind, "toDataURL", "(Ljava/lang/Double;Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;)V", args, count, cachedMethodId);
|
||||
}
|
||||
|
||||
NativeSvgViewModuleSpecJSI::NativeSvgViewModuleSpecJSI(const JavaTurboModule::InitParams ¶ms)
|
||||
: JavaTurboModule(params) {
|
||||
methodMap_["toDataURL"] = MethodMetadata {3, __hostFunction_NativeSvgViewModuleSpecJSI_toDataURL};
|
||||
}
|
||||
|
||||
std::shared_ptr<TurboModule> rnsvg_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms) {
|
||||
if (moduleName == "RNSVGRenderableModule") {
|
||||
return std::make_shared<NativeSvgRenderableModuleSpecJSI>(params);
|
||||
}
|
||||
if (moduleName == "RNSVGSvgViewModule") {
|
||||
return std::make_shared<NativeSvgViewModuleSpecJSI>(params);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
32
android/src/main/jni/rnsvg.h
Normal file
32
android/src/main/jni/rnsvg.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <ReactCommon/JavaTurboModule.h>
|
||||
#include <ReactCommon/TurboModule.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <react/renderer/components/rnsvg/RNSVGImageComponentDescriptor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* JNI C++ class for module 'NativeSvgRenderableModule'
|
||||
*/
|
||||
class JSI_EXPORT NativeSvgRenderableModuleSpecJSI : public JavaTurboModule {
|
||||
public:
|
||||
NativeSvgRenderableModuleSpecJSI(const JavaTurboModule::InitParams ¶ms);
|
||||
};
|
||||
|
||||
/**
|
||||
* JNI C++ class for module 'NativeSvgViewModule'
|
||||
*/
|
||||
class JSI_EXPORT NativeSvgViewModuleSpecJSI : public JavaTurboModule {
|
||||
public:
|
||||
NativeSvgViewModuleSpecJSI(const JavaTurboModule::InitParams ¶ms);
|
||||
};
|
||||
|
||||
|
||||
JSI_EXPORT
|
||||
std::shared_ptr<TurboModule> rnsvg_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams ¶ms);
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GeneratePropsJavaDelegate.js
|
||||
*/
|
||||
|
||||
package com.facebook.react.viewmanagers;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ColorPropConverter;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.uimanager.BaseViewManagerDelegate;
|
||||
import com.facebook.react.uimanager.BaseViewManagerInterface;
|
||||
|
||||
public class RNSVGSvgViewAndroidManagerDelegate<T extends View, U extends BaseViewManagerInterface<T> & RNSVGSvgViewAndroidManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
|
||||
public RNSVGSvgViewAndroidManagerDelegate(U viewManager) {
|
||||
super(viewManager);
|
||||
}
|
||||
@Override
|
||||
public void setProperty(T view, String propName, @Nullable Object value) {
|
||||
switch (propName) {
|
||||
case "bbWidth":
|
||||
if (value instanceof String) {
|
||||
mViewManager.setBbWidth(view, (String) value);
|
||||
} else if (value instanceof Double) {
|
||||
mViewManager.setBbWidth(view, (Double) value);
|
||||
} else {
|
||||
mViewManager.setBbWidth(view, (Double) null);
|
||||
}
|
||||
break;
|
||||
case "bbHeight":
|
||||
if (value instanceof String) {
|
||||
mViewManager.setBbHeight(view, (String) value);
|
||||
} else if (value instanceof Double) {
|
||||
mViewManager.setBbHeight(view, (Double) value);
|
||||
} else {
|
||||
mViewManager.setBbHeight(view, (Double) null);
|
||||
}
|
||||
break;
|
||||
case "minX":
|
||||
mViewManager.setMinX(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "minY":
|
||||
mViewManager.setMinY(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "vbWidth":
|
||||
mViewManager.setVbWidth(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "vbHeight":
|
||||
mViewManager.setVbHeight(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "align":
|
||||
mViewManager.setAlign(view, value == null ? null : (String) value);
|
||||
break;
|
||||
case "meetOrSlice":
|
||||
mViewManager.setMeetOrSlice(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "tintColor":
|
||||
mViewManager.setTintColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "color":
|
||||
mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "pointerEvents":
|
||||
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
|
||||
break;
|
||||
case "hasTVPreferredFocus":
|
||||
mViewManager.setHasTVPreferredFocus(view, value == null ? false : (boolean) value);
|
||||
break;
|
||||
case "borderTopEndRadius":
|
||||
mViewManager.setBorderTopEndRadius(view, value == null ? 0f : ((Double) value).floatValue());
|
||||
break;
|
||||
case "borderBottomStartRadius":
|
||||
mViewManager.setBorderBottomStartRadius(view, value == null ? 0f : ((Double) value).floatValue());
|
||||
break;
|
||||
case "borderBottomColor":
|
||||
mViewManager.setBorderBottomColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "nextFocusDown":
|
||||
mViewManager.setNextFocusDown(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "borderRightColor":
|
||||
mViewManager.setBorderRightColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "nextFocusRight":
|
||||
mViewManager.setNextFocusRight(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "borderLeftColor":
|
||||
mViewManager.setBorderLeftColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "borderColor":
|
||||
mViewManager.setBorderColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "removeClippedSubviews":
|
||||
mViewManager.setRemoveClippedSubviews(view, value == null ? false : (boolean) value);
|
||||
break;
|
||||
case "nextFocusForward":
|
||||
mViewManager.setNextFocusForward(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "nextFocusUp":
|
||||
mViewManager.setNextFocusUp(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "accessible":
|
||||
mViewManager.setAccessible(view, value == null ? false : (boolean) value);
|
||||
break;
|
||||
case "borderStartColor":
|
||||
mViewManager.setBorderStartColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "borderBottomEndRadius":
|
||||
mViewManager.setBorderBottomEndRadius(view, value == null ? 0f : ((Double) value).floatValue());
|
||||
break;
|
||||
case "borderEndColor":
|
||||
mViewManager.setBorderEndColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "focusable":
|
||||
mViewManager.setFocusable(view, value == null ? false : (boolean) value);
|
||||
break;
|
||||
case "nativeBackgroundAndroid":
|
||||
mViewManager.setNativeBackgroundAndroid(view, (ReadableMap) value);
|
||||
break;
|
||||
case "borderTopStartRadius":
|
||||
mViewManager.setBorderTopStartRadius(view, value == null ? 0f : ((Double) value).floatValue());
|
||||
break;
|
||||
case "nativeForegroundAndroid":
|
||||
mViewManager.setNativeForegroundAndroid(view, (ReadableMap) value);
|
||||
break;
|
||||
case "backfaceVisibility":
|
||||
mViewManager.setBackfaceVisibility(view, value == null ? null : (String) value);
|
||||
break;
|
||||
case "borderStyle":
|
||||
mViewManager.setBorderStyle(view, value == null ? null : (String) value);
|
||||
break;
|
||||
case "needsOffscreenAlphaCompositing":
|
||||
mViewManager.setNeedsOffscreenAlphaCompositing(view, value == null ? false : (boolean) value);
|
||||
break;
|
||||
case "hitSlop":
|
||||
mViewManager.setHitSlop(view, (ReadableMap) value);
|
||||
break;
|
||||
case "borderTopColor":
|
||||
mViewManager.setBorderTopColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "nextFocusLeft":
|
||||
mViewManager.setNextFocusLeft(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "borderTopRightRadius":
|
||||
mViewManager.setBorderTopRightRadius(view, value == null ? 0f : ((Double) value).doubleValue());
|
||||
break;
|
||||
case "borderBottomRightRadius":
|
||||
mViewManager.setBorderBottomRightRadius(view, value == null ? 0f : ((Double) value).doubleValue());
|
||||
break;
|
||||
case "borderRadius":
|
||||
mViewManager.setBorderRadius(view, value == null ? 0f : ((Double) value).doubleValue());
|
||||
break;
|
||||
case "borderBottomLeftRadius":
|
||||
mViewManager.setBorderBottomLeftRadius(view, value == null ? 0f : ((Double) value).doubleValue());
|
||||
break;
|
||||
case "borderTopLeftRadius":
|
||||
mViewManager.setBorderTopLeftRadius(view, value == null ? 0f : ((Double) value).doubleValue());
|
||||
break;
|
||||
default:
|
||||
super.setProperty(view, propName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GeneratePropsJavaInterface.js
|
||||
*/
|
||||
|
||||
package com.facebook.react.viewmanagers;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
public interface RNSVGSvgViewAndroidManagerInterface<T extends View> {
|
||||
void setBbWidth(T view, @Nullable String value);
|
||||
void setBbWidth(T view, @Nullable Double value);
|
||||
void setBbHeight(T view, @Nullable String value);
|
||||
void setBbHeight(T view, @Nullable Double value);
|
||||
void setMinX(T view, float value);
|
||||
void setMinY(T view, float value);
|
||||
void setVbWidth(T view, float value);
|
||||
void setVbHeight(T view, float value);
|
||||
void setAlign(T view, @Nullable String value);
|
||||
void setMeetOrSlice(T view, int value);
|
||||
void setTintColor(T view, @Nullable Integer value);
|
||||
void setColor(T view, @Nullable Integer value);
|
||||
void setPointerEvents(T view, @Nullable String value);
|
||||
void setHasTVPreferredFocus(T view, boolean value);
|
||||
void setBorderTopEndRadius(T view, float value);
|
||||
void setBorderBottomStartRadius(T view, float value);
|
||||
void setBorderBottomColor(T view, @Nullable Integer value);
|
||||
void setNextFocusDown(T view, int value);
|
||||
void setBorderRightColor(T view, @Nullable Integer value);
|
||||
void setNextFocusRight(T view, int value);
|
||||
void setBorderLeftColor(T view, @Nullable Integer value);
|
||||
void setBorderColor(T view, @Nullable Integer value);
|
||||
void setRemoveClippedSubviews(T view, boolean value);
|
||||
void setNextFocusForward(T view, int value);
|
||||
void setNextFocusUp(T view, int value);
|
||||
void setAccessible(T view, boolean value);
|
||||
void setBorderStartColor(T view, @Nullable Integer value);
|
||||
void setBorderBottomEndRadius(T view, float value);
|
||||
void setBorderEndColor(T view, @Nullable Integer value);
|
||||
void setFocusable(T view, boolean value);
|
||||
void setNativeBackgroundAndroid(T view, @Nullable ReadableMap value);
|
||||
void setBorderTopStartRadius(T view, float value);
|
||||
void setNativeForegroundAndroid(T view, @Nullable ReadableMap value);
|
||||
void setBackfaceVisibility(T view, @Nullable String value);
|
||||
void setBorderStyle(T view, @Nullable String value);
|
||||
void setNeedsOffscreenAlphaCompositing(T view, boolean value);
|
||||
void setHitSlop(T view, @Nullable ReadableMap value);
|
||||
void setBorderTopColor(T view, @Nullable Integer value);
|
||||
void setNextFocusLeft(T view, int value);
|
||||
void setBorderTopRightRadius(T view, double value);
|
||||
void setBorderBottomRightRadius(T view, double value);
|
||||
void setBorderRadius(T view, double value);
|
||||
void setBorderBottomLeftRadius(T view, double value);
|
||||
void setBorderTopLeftRadius(T view, double value);
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GeneratePropsJavaDelegate.js
|
||||
*/
|
||||
|
||||
package com.facebook.react.viewmanagers;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.react.bridge.ColorPropConverter;
|
||||
import com.facebook.react.uimanager.BaseViewManagerDelegate;
|
||||
import com.facebook.react.uimanager.BaseViewManagerInterface;
|
||||
|
||||
public class RNSVGSvgViewManagerDelegate<T extends View, U extends BaseViewManagerInterface<T> & RNSVGSvgViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
|
||||
public RNSVGSvgViewManagerDelegate(U viewManager) {
|
||||
super(viewManager);
|
||||
}
|
||||
@Override
|
||||
public void setProperty(T view, String propName, @Nullable Object value) {
|
||||
switch (propName) {
|
||||
case "bbWidth":
|
||||
if (value instanceof String) {
|
||||
mViewManager.setBbWidth(view, (String) value);
|
||||
} else if (value instanceof Double) {
|
||||
mViewManager.setBbWidth(view, (Double) value);
|
||||
} else {
|
||||
mViewManager.setBbWidth(view, (Double) null);
|
||||
}
|
||||
break;
|
||||
case "bbHeight":
|
||||
if (value instanceof String) {
|
||||
mViewManager.setBbHeight(view, (String) value);
|
||||
} else if (value instanceof Double) {
|
||||
mViewManager.setBbHeight(view, (Double) value);
|
||||
} else {
|
||||
mViewManager.setBbHeight(view, (Double) null);
|
||||
}
|
||||
break;
|
||||
case "minX":
|
||||
mViewManager.setMinX(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "minY":
|
||||
mViewManager.setMinY(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "vbWidth":
|
||||
mViewManager.setVbWidth(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "vbHeight":
|
||||
mViewManager.setVbHeight(view, value == null ? Float.NaN : ((Double) value).floatValue());
|
||||
break;
|
||||
case "align":
|
||||
mViewManager.setAlign(view, value == null ? null : (String) value);
|
||||
break;
|
||||
case "meetOrSlice":
|
||||
mViewManager.setMeetOrSlice(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "tintColor":
|
||||
mViewManager.setTintColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "color":
|
||||
mViewManager.setColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
||||
break;
|
||||
case "pointerEvents":
|
||||
mViewManager.setPointerEvents(view, value == null ? null : (String) value);
|
||||
break;
|
||||
default:
|
||||
super.setProperty(view, propName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
||||
* once the code is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GeneratePropsJavaInterface.js
|
||||
*/
|
||||
|
||||
package com.facebook.react.viewmanagers;
|
||||
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public interface RNSVGSvgViewManagerInterface<T extends View> {
|
||||
void setBbWidth(T view, @Nullable String value);
|
||||
void setBbWidth(T view, @Nullable Double value);
|
||||
void setBbHeight(T view, @Nullable String value);
|
||||
void setBbHeight(T view, @Nullable Double value);
|
||||
void setMinX(T view, float value);
|
||||
void setMinY(T view, float value);
|
||||
void setVbWidth(T view, float value);
|
||||
void setVbHeight(T view, float value);
|
||||
void setAlign(T view, @Nullable String value);
|
||||
void setMeetOrSlice(T view, int value);
|
||||
void setTintColor(T view, @Nullable Integer value);
|
||||
void setColor(T view, @Nullable Integer value);
|
||||
void setPointerEvents(T view, @Nullable String value);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* This code was generated by
|
||||
* [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* <p>Do not edit this file as changes may cause incorrect behavior and will be lost once the code
|
||||
* is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleJavaSpec.js
|
||||
* @nolint
|
||||
*/
|
||||
package com.horcrux.rnsvg;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
|
||||
public abstract class NativeSvgRenderableModuleSpec extends ReactContextBaseJavaModule {
|
||||
public NativeSvgRenderableModuleSpec(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract boolean isPointInFill(Double tag, ReadableMap options);
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract boolean isPointInStroke(Double tag, ReadableMap options);
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract double getTotalLength(Double tag);
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract WritableMap getPointAtLength(Double tag, ReadableMap options);
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract WritableMap getBBox(Double tag, ReadableMap options);
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract WritableMap getCTM(Double tag);
|
||||
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
@DoNotStrip
|
||||
public abstract WritableMap getScreenCTM(Double tag);
|
||||
|
||||
@ReactMethod
|
||||
@DoNotStrip
|
||||
public abstract void getRawResource(String name, Promise promise);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* This code was generated by
|
||||
* [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
||||
*
|
||||
* <p>Do not edit this file as changes may cause incorrect behavior and will be lost once the code
|
||||
* is regenerated.
|
||||
*
|
||||
* @generated by codegen project: GenerateModuleJavaSpec.js
|
||||
* @nolint
|
||||
*/
|
||||
package com.horcrux.rnsvg;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
public abstract class NativeSvgViewModuleSpec extends ReactContextBaseJavaModule {
|
||||
public NativeSvgViewModuleSpec(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@DoNotStrip
|
||||
public abstract void toDataURL(Double tag, ReadableMap options, Callback callback);
|
||||
}
|
||||
@@ -15,7 +15,14 @@
|
||||
|
||||
#import <React/RCTImageSource.h>
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
#import <React/RCTImageResponseDelegate.h>
|
||||
#endif
|
||||
|
||||
@interface RNSVGImage : RNSVGRenderable
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
<RCTImageResponseDelegate>
|
||||
#endif
|
||||
|
||||
@property (nonatomic, weak) RCTBridge *bridge;
|
||||
@property (nonatomic, assign) RCTImageSource *src;
|
||||
@@ -26,6 +33,4 @@
|
||||
@property (nonatomic, strong) NSString *align;
|
||||
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
|
||||
|
||||
- (void)setImageSrc:(RCTImageSource *)source request:(NSURLRequest *)request;
|
||||
|
||||
@end
|
||||
|
||||
@@ -29,24 +29,25 @@
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
#import <React/RCTConversions.h>
|
||||
#import <React/RCTFabricComponentsPlugins.h>
|
||||
#import <React/RCTImageResponseObserverProxy.h>
|
||||
#import <React/RCTImageSource.h>
|
||||
#import <react/renderer/components/rnsvg/ComponentDescriptors.h>
|
||||
#import <react/renderer/components/view/conversions.h>
|
||||
#import <react/renderer/imagemanager/RCTImagePrimitivesConversions.h>
|
||||
#import <rnsvg/RNSVGImageComponentDescriptor.h>
|
||||
#import "RNSVGFabricConversions.h"
|
||||
|
||||
// Some RN private method hacking below similar to how it is done in RNScreens:
|
||||
// https://github.com/software-mansion/react-native-screens/blob/90e548739f35b5ded2524a9d6410033fc233f586/ios/RNSScreenStackHeaderConfig.mm#L30
|
||||
@interface RCTBridge (Private)
|
||||
+ (RCTBridge *)currentBridge;
|
||||
@end
|
||||
|
||||
#endif // RN_FABRIC_ENABLED
|
||||
|
||||
@implementation RNSVGImage {
|
||||
CGImageRef _image;
|
||||
CGSize _imageSize;
|
||||
RCTImageLoaderCancellationBlock _reloadImageCancellationBlock;
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
RNSVGImageShadowNode::ConcreteState::Shared _state;
|
||||
RCTImageResponseObserverProxy _imageResponseObserverProxy;
|
||||
#endif // RN_FABRIC_ENABLED
|
||||
}
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
using namespace facebook::react;
|
||||
@@ -56,6 +57,10 @@ using namespace facebook::react;
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
static const auto defaultProps = std::make_shared<const RNSVGImageProps>();
|
||||
_props = defaultProps;
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
_imageResponseObserverProxy = RCTImageResponseObserverProxy(self);
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -70,7 +75,6 @@ using namespace facebook::react;
|
||||
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
||||
{
|
||||
const auto &newProps = *std::static_pointer_cast<const RNSVGImageProps>(props);
|
||||
const auto &oldImageProps = *std::static_pointer_cast<const RNSVGImageProps>(oldProps);
|
||||
|
||||
self.x = [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.x)];
|
||||
self.y = [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.y)];
|
||||
@@ -80,15 +84,6 @@ using namespace facebook::react;
|
||||
if (RCTNSStringFromStringNilIfEmpty(newProps.width)) {
|
||||
self.imagewidth = [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.width)];
|
||||
}
|
||||
|
||||
if (oldProps == nullptr || oldImageProps.src != newProps.src) {
|
||||
// TODO: make it the same as in e.g. slider
|
||||
NSURLRequest *request = NSURLRequestFromImageSource(newProps.src);
|
||||
CGSize size = RCTCGSizeFromSize(newProps.src.size);
|
||||
CGFloat scale = newProps.src.scale;
|
||||
RCTImageSource *imageSource = [[RCTImageSource alloc] initWithURLRequest:request size:size scale:scale];
|
||||
[self setImageSrc:imageSource request:request];
|
||||
}
|
||||
self.align = RCTNSStringFromStringNilIfEmpty(newProps.align);
|
||||
self.meetOrSlice = intToRNSVGVBMOS(newProps.meetOrSlice);
|
||||
|
||||
@@ -96,9 +91,68 @@ using namespace facebook::react;
|
||||
_props = std::static_pointer_cast<RNSVGImageProps const>(props);
|
||||
}
|
||||
|
||||
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
|
||||
{
|
||||
RCTAssert(state, @"`state` must not be null.");
|
||||
RCTAssert(
|
||||
std::dynamic_pointer_cast<RNSVGImageShadowNode::ConcreteState const>(state),
|
||||
@"`state` must be a pointer to `RNSVGImageShadowNode::ConcreteState`.");
|
||||
|
||||
auto oldImageState = std::static_pointer_cast<RNSVGImageShadowNode::ConcreteState const>(_state);
|
||||
auto newImageState = std::static_pointer_cast<RNSVGImageShadowNode::ConcreteState const>(state);
|
||||
|
||||
[self _setStateAndResubscribeImageResponseObserver:newImageState];
|
||||
}
|
||||
|
||||
- (void)_setStateAndResubscribeImageResponseObserver:(RNSVGImageShadowNode::ConcreteState::Shared const &)state
|
||||
{
|
||||
if (_state) {
|
||||
auto &observerCoordinator = _state->getData().getImageRequest().getObserverCoordinator();
|
||||
observerCoordinator.removeObserver(_imageResponseObserverProxy);
|
||||
}
|
||||
|
||||
_state = state;
|
||||
|
||||
if (_state) {
|
||||
auto &observerCoordinator = _state->getData().getImageRequest().getObserverCoordinator();
|
||||
observerCoordinator.addObserver(_imageResponseObserverProxy);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - RCTImageResponseDelegate
|
||||
|
||||
- (void)didReceiveImage:(UIImage *)image metadata:(id)metadata fromObserver:(void const *)observer
|
||||
{
|
||||
if (!_eventEmitter || !_state) {
|
||||
// Notifications are delivered asynchronously and might arrive after the view is already recycled.
|
||||
// In the future, we should incorporate an `EventEmitter` into a separate object owned by `ImageRequest` or `State`.
|
||||
// See for more info: T46311063.
|
||||
return;
|
||||
}
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self->_image = CGImageRetain(image.CGImage);
|
||||
self->_imageSize = CGSizeMake(CGImageGetWidth(self->_image), CGImageGetHeight(self->_image));
|
||||
[self invalidate];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)didReceiveProgress:(float)progress fromObserver:(void const *)observer
|
||||
{
|
||||
}
|
||||
|
||||
- (void)didReceiveFailureFromObserver:(void const *)observer
|
||||
{
|
||||
if (_image) {
|
||||
CGImageRelease(_image);
|
||||
}
|
||||
_image = nil;
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
{
|
||||
[super prepareForRecycle];
|
||||
[self _setStateAndResubscribeImageResponseObserver:nullptr];
|
||||
|
||||
_x = nil;
|
||||
_y = nil;
|
||||
_imageheight = nil;
|
||||
@@ -116,8 +170,10 @@ using namespace facebook::react;
|
||||
}
|
||||
#endif // RN_FABRIC_ENABLED
|
||||
|
||||
- (void)setImageSrc:(RCTImageSource *)src request:(NSURLRequest *)request
|
||||
- (void)setSrc:(RCTImageSource *)src
|
||||
{
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
#else
|
||||
if (src == _src) {
|
||||
return;
|
||||
}
|
||||
@@ -136,24 +192,16 @@ using namespace facebook::react;
|
||||
_reloadImageCancellationBlock = nil;
|
||||
}
|
||||
|
||||
_reloadImageCancellationBlock = [[
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
[RCTBridge currentBridge]
|
||||
#else
|
||||
self.bridge
|
||||
#endif // RN_FABRIC_ENABLED
|
||||
moduleForName:@"ImageLoader"] loadImageWithURLRequest:request callback:^(NSError *error, UIImage *image) {
|
||||
_reloadImageCancellationBlock = [[self.bridge moduleForName:@"ImageLoader"]
|
||||
loadImageWithURLRequest:src.request
|
||||
callback:^(NSError *error, UIImage *image) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self->_image = CGImageRetain(image.CGImage);
|
||||
self->_imageSize = CGSizeMake(CGImageGetWidth(self->_image), CGImageGetHeight(self->_image));
|
||||
[self invalidate];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setSrc:(RCTImageSource *)src
|
||||
{
|
||||
[self setImageSrc:src request:src.request];
|
||||
#endif // RN_FABRIC_ENABLED
|
||||
}
|
||||
|
||||
- (void)setX:(RNSVGLength *)x
|
||||
|
||||
@@ -78,7 +78,7 @@ using namespace facebook::react;
|
||||
if (RCTUIColorFromSharedColor(newProps.color)) {
|
||||
self.tintColor = RCTUIColorFromSharedColor(newProps.color);
|
||||
}
|
||||
_props = std::static_pointer_cast<RNSVGSvgViewProps const>(props);
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)prepareForRecycle
|
||||
|
||||
21
apple/RNSVGRenderableModule.h
Normal file
21
apple/RNSVGRenderableModule.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Horcrux.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
#import <rnsvg/rnsvg.h>
|
||||
#else
|
||||
#import <React/RCTBridge.h>
|
||||
#endif
|
||||
|
||||
@interface RNSVGRenderableModule : NSObject
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
<NativeSvgRenderableModuleSpec>
|
||||
#else
|
||||
<RCTBridgeModule>
|
||||
#endif
|
||||
@end
|
||||
210
apple/RNSVGRenderableModule.mm
Normal file
210
apple/RNSVGRenderableModule.mm
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Horcrux.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RNSVGRenderableModule.h"
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
#import <React/RCTUIManagerUtils.h>
|
||||
#import "RNSVGPathMeasure.h"
|
||||
#import "RNSVGRenderable.h"
|
||||
|
||||
#import "RCTConvert+RNSVG.h"
|
||||
#import "RNSVGCGFCRule.h"
|
||||
|
||||
@implementation RNSVGRenderableModule
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isPointInFill : (nonnull NSNumber *)reactTag options : (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
if (options == nil) {
|
||||
RCTLogError(@"Invalid options given to isPointInFill, got: %@", options);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
id xo = [options objectForKey:@"x"];
|
||||
id yo = [options objectForKey:@"y"];
|
||||
if (![xo isKindOfClass:NSNumber.class] || ![yo isKindOfClass:NSNumber.class]) {
|
||||
RCTLogError(@"Invalid x or y given to isPointInFill");
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGFloat x = (CGFloat)[xo doubleValue];
|
||||
CGFloat y = (CGFloat)[yo doubleValue];
|
||||
CGPoint point = CGPointMake(x, y);
|
||||
RNSVGPlatformView *target = [svg hitTest:point withEvent:nil];
|
||||
BOOL hit = target != nil;
|
||||
return [NSNumber numberWithBool:hit];
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isPointInStroke : (nonnull NSNumber *)reactTag options : (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
if (options == nil) {
|
||||
RCTLogError(@"Invalid options given to isPointInFill, got: %@", options);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
id xo = [options objectForKey:@"x"];
|
||||
id yo = [options objectForKey:@"y"];
|
||||
if (![xo isKindOfClass:NSNumber.class] || ![yo isKindOfClass:NSNumber.class]) {
|
||||
RCTLogError(@"Invalid x or y given to isPointInFill");
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGFloat x = (CGFloat)[xo doubleValue];
|
||||
CGFloat y = (CGFloat)[yo doubleValue];
|
||||
CGPoint point = CGPointMake(x, y);
|
||||
BOOL hit = CGPathContainsPoint(svg.strokePath, nil, point, NO);
|
||||
|
||||
return [NSNumber numberWithBool:hit];
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getTotalLength : (nonnull NSNumber *)reactTag)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return [NSNumber numberWithDouble:0];
|
||||
}
|
||||
|
||||
RNSVGPathMeasure *measure = [[RNSVGPathMeasure alloc] init];
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGPathRef target = [svg getPath:nil];
|
||||
[measure extractPathData:target];
|
||||
|
||||
return [NSNumber numberWithDouble:measure.pathLength];
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getPointAtLength
|
||||
: (nonnull NSNumber *)reactTag options
|
||||
: (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGFloat position = (CGFloat)[[options objectForKey:@"length"] doubleValue];
|
||||
RNSVGPathMeasure *measure = [[RNSVGPathMeasure alloc] init];
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGPathRef target = [svg getPath:nil];
|
||||
[measure extractPathData:target];
|
||||
|
||||
CGFloat x;
|
||||
CGFloat y;
|
||||
CGFloat angle;
|
||||
double midPoint = fmax(0, fmin(position, measure.pathLength));
|
||||
[measure getPosAndTan:&angle midPoint:midPoint x:&x y:&y];
|
||||
|
||||
return @{@"x" : @(x), @"y" : @(y), @"angle" : @(angle)};
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getBBox : (nonnull NSNumber *)reactTag options : (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
BOOL fill = [[options objectForKey:@"fill"] boolValue];
|
||||
BOOL stroke = [[options objectForKey:@"stroke"] boolValue];
|
||||
BOOL markers = [[options objectForKey:@"markers"] boolValue];
|
||||
BOOL clipped = [[options objectForKey:@"clipped"] boolValue];
|
||||
[svg getPath:nil];
|
||||
|
||||
CGRect bounds = CGRectZero;
|
||||
if (fill) {
|
||||
bounds = CGRectUnion(bounds, svg.fillBounds);
|
||||
}
|
||||
if (stroke) {
|
||||
bounds = CGRectUnion(bounds, svg.strokeBounds);
|
||||
}
|
||||
if (markers) {
|
||||
bounds = CGRectUnion(bounds, svg.markerBounds);
|
||||
}
|
||||
if (clipped) {
|
||||
CGPathRef clipPath = [svg getClipPath];
|
||||
CGRect clipBounds = CGPathGetBoundingBox(clipPath);
|
||||
if (clipPath && !CGRectIsEmpty(clipBounds)) {
|
||||
bounds = CGRectIntersection(bounds, clipBounds);
|
||||
}
|
||||
}
|
||||
|
||||
CGPoint origin = bounds.origin;
|
||||
CGSize size = bounds.size;
|
||||
return @{@"x" : @(origin.x), @"y" : @(origin.y), @"width" : @(size.width), @"height" : @(size.height)};
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getCTM : (nonnull NSNumber *)reactTag)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGAffineTransform ctm = svg.ctm;
|
||||
return @{@"a" : @(ctm.a), @"b" : @(ctm.b), @"c" : @(ctm.c), @"d" : @(ctm.d), @"e" : @(ctm.tx), @"f" : @(ctm.ty)};
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getScreenCTM : (nonnull NSNumber *)reactTag)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGAffineTransform ctm = svg.ctm;
|
||||
return @{@"a" : @(ctm.a), @"b" : @(ctm.b), @"c" : @(ctm.c), @"d" : @(ctm.d), @"e" : @(ctm.tx), @"f" : @(ctm.ty)};
|
||||
}
|
||||
|
||||
- (void)getRawResource:(NSString *)name resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
||||
{
|
||||
}
|
||||
|
||||
- (RNSVGPlatformView *)getRenderableView:(NSNumber *)reactTag
|
||||
{
|
||||
__block RNSVGPlatformView *view;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
view = [self.viewRegistry_DEPRECATED viewForReactTag:reactTag];
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
||||
(const facebook::react::ObjCTurboModule::InitParams &)params
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeSvgRenderableModuleSpecJSI>(params);
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
21
apple/RNSVGSvgViewModule.h
Normal file
21
apple/RNSVGSvgViewModule.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Horcrux.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
#import <rnsvg/rnsvg.h>
|
||||
#else
|
||||
#import <React/RCTBridge.h>
|
||||
#endif
|
||||
|
||||
@interface RNSVGSvgViewModule : NSObject
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
<NativeSvgViewModuleSpec>
|
||||
#else
|
||||
<RCTBridgeModule>
|
||||
#endif
|
||||
@end
|
||||
86
apple/RNSVGSvgViewModule.mm
Normal file
86
apple/RNSVGSvgViewModule.mm
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Horcrux.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RNSVGSvgViewModule.h"
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
#import <React/RCTUIManagerUtils.h>
|
||||
#import "RNSVGSvgView.h"
|
||||
|
||||
@implementation RNSVGSvgViewModule
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
- (void)toDataURL:(nonnull NSNumber *)reactTag
|
||||
options:(NSDictionary *)options
|
||||
callback:(RCTResponseSenderBlock)callback
|
||||
attempt:(int)attempt
|
||||
{
|
||||
void (^block)(void) = ^{
|
||||
[self.viewRegistry_DEPRECATED addUIBlock:^(RCTViewRegistry *viewRegistry) {
|
||||
__kindof RNSVGPlatformView *view = [viewRegistry viewForReactTag:reactTag];
|
||||
NSString *b64;
|
||||
if ([view isKindOfClass:[RNSVGSvgView class]]) {
|
||||
RNSVGSvgView *svg = view;
|
||||
if (options == nil) {
|
||||
b64 = [svg getDataURL];
|
||||
} else {
|
||||
id width = [options objectForKey:@"width"];
|
||||
id height = [options objectForKey:@"height"];
|
||||
if (![width isKindOfClass:NSNumber.class] || ![height isKindOfClass:NSNumber.class]) {
|
||||
RCTLogError(@"Invalid width or height given to toDataURL");
|
||||
return;
|
||||
}
|
||||
NSNumber *w = width;
|
||||
NSInteger wi = (NSInteger)[w intValue];
|
||||
NSNumber *h = height;
|
||||
NSInteger hi = (NSInteger)[h intValue];
|
||||
|
||||
CGRect bounds = CGRectMake(0, 0, wi, hi);
|
||||
b64 = [svg getDataURLwithBounds:bounds];
|
||||
}
|
||||
} else {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGSvgView, got: %@", view);
|
||||
return;
|
||||
}
|
||||
if (b64) {
|
||||
callback(@[ b64 ]);
|
||||
} else if (attempt < 1) {
|
||||
[self toDataURL:reactTag options:options callback:callback attempt:(attempt + 1)];
|
||||
} else {
|
||||
callback(@[]);
|
||||
}
|
||||
}];
|
||||
};
|
||||
if (self.bridge) {
|
||||
dispatch_async(RCTGetUIManagerQueue(), block);
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), block);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(toDataURL
|
||||
: (nonnull NSNumber *)reactTag options
|
||||
: (NSDictionary *)options callback
|
||||
: (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[self toDataURL:reactTag options:options callback:callback attempt:0];
|
||||
}
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
||||
(const facebook::react::ObjCTurboModule::InitParams &)params
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeSvgViewModuleSpecJSI>(params);
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
@@ -8,6 +8,7 @@
|
||||
@property NSString *text;
|
||||
@property NSTextAlignment textAlignment;
|
||||
#else
|
||||
#import <UIKit/UIKit.h>
|
||||
@interface RNSVGTopAlignedLabel : UILabel
|
||||
#endif
|
||||
@end
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* This source code is licensed under the MIT-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef CF_ENUM(int32_t, RNSVGCGFCRule) {
|
||||
kRNSVGCGFCRuleEvenodd,
|
||||
|
||||
@@ -38,177 +38,4 @@ RCT_EXPORT_VIEW_PROPERTY(strokeMiterlimit, CGFloat)
|
||||
RCT_EXPORT_VIEW_PROPERTY(vectorEffect, int)
|
||||
RCT_EXPORT_VIEW_PROPERTY(propList, NSArray<NSString *>)
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isPointInFill : (nonnull NSNumber *)reactTag options : (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
if (options == nil) {
|
||||
RCTLogError(@"Invalid options given to isPointInFill, got: %@", options);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
id xo = [options objectForKey:@"x"];
|
||||
id yo = [options objectForKey:@"y"];
|
||||
if (![xo isKindOfClass:NSNumber.class] || ![yo isKindOfClass:NSNumber.class]) {
|
||||
RCTLogError(@"Invalid x or y given to isPointInFill");
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGFloat x = (CGFloat)[xo doubleValue];
|
||||
CGFloat y = (CGFloat)[yo doubleValue];
|
||||
CGPoint point = CGPointMake(x, y);
|
||||
RNSVGPlatformView *target = [svg hitTest:point withEvent:nil];
|
||||
BOOL hit = target != nil;
|
||||
return [NSNumber numberWithBool:hit];
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(isPointInStroke : (nonnull NSNumber *)reactTag options : (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
if (options == nil) {
|
||||
RCTLogError(@"Invalid options given to isPointInFill, got: %@", options);
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
id xo = [options objectForKey:@"x"];
|
||||
id yo = [options objectForKey:@"y"];
|
||||
if (![xo isKindOfClass:NSNumber.class] || ![yo isKindOfClass:NSNumber.class]) {
|
||||
RCTLogError(@"Invalid x or y given to isPointInFill");
|
||||
return [NSNumber numberWithBool:false];
|
||||
}
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGFloat x = (CGFloat)[xo doubleValue];
|
||||
CGFloat y = (CGFloat)[yo doubleValue];
|
||||
CGPoint point = CGPointMake(x, y);
|
||||
BOOL hit = CGPathContainsPoint(svg.strokePath, nil, point, NO);
|
||||
|
||||
return [NSNumber numberWithBool:hit];
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getTotalLength : (nonnull NSNumber *)reactTag)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return [NSNumber numberWithDouble:0];
|
||||
}
|
||||
|
||||
RNSVGPathMeasure *measure = [[RNSVGPathMeasure alloc] init];
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGPathRef target = [svg getPath:nil];
|
||||
[measure extractPathData:target];
|
||||
|
||||
return [NSNumber numberWithDouble:measure.pathLength];
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getPointAtLength
|
||||
: (nonnull NSNumber *)reactTag options
|
||||
: (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
CGFloat position = (CGFloat)[[options objectForKey:@"length"] doubleValue];
|
||||
RNSVGPathMeasure *measure = [[RNSVGPathMeasure alloc] init];
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGPathRef target = [svg getPath:nil];
|
||||
[measure extractPathData:target];
|
||||
|
||||
CGFloat x;
|
||||
CGFloat y;
|
||||
CGFloat angle;
|
||||
double midPoint = fmax(0, fmin(position, measure.pathLength));
|
||||
[measure getPosAndTan:&angle midPoint:midPoint x:&x y:&y];
|
||||
|
||||
return @{@"x" : @(x), @"y" : @(y), @"angle" : @(angle)};
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getBBox : (nonnull NSNumber *)reactTag options : (NSDictionary *)options)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
BOOL fill = [[options objectForKey:@"fill"] boolValue];
|
||||
BOOL stroke = [[options objectForKey:@"stroke"] boolValue];
|
||||
BOOL markers = [[options objectForKey:@"markers"] boolValue];
|
||||
BOOL clipped = [[options objectForKey:@"clipped"] boolValue];
|
||||
[svg getPath:nil];
|
||||
|
||||
CGRect bounds = CGRectZero;
|
||||
if (fill) {
|
||||
bounds = CGRectUnion(bounds, svg.fillBounds);
|
||||
}
|
||||
if (stroke) {
|
||||
bounds = CGRectUnion(bounds, svg.strokeBounds);
|
||||
}
|
||||
if (markers) {
|
||||
bounds = CGRectUnion(bounds, svg.markerBounds);
|
||||
}
|
||||
if (clipped) {
|
||||
CGPathRef clipPath = [svg getClipPath];
|
||||
CGRect clipBounds = CGPathGetBoundingBox(clipPath);
|
||||
if (clipPath && !CGRectIsEmpty(clipBounds)) {
|
||||
bounds = CGRectIntersection(bounds, clipBounds);
|
||||
}
|
||||
}
|
||||
|
||||
CGPoint origin = bounds.origin;
|
||||
CGSize size = bounds.size;
|
||||
return @{@"x" : @(origin.x), @"y" : @(origin.y), @"width" : @(size.width), @"height" : @(size.height)};
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getCTM : (nonnull NSNumber *)reactTag)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGAffineTransform ctm = svg.ctm;
|
||||
return @{@"a" : @(ctm.a), @"b" : @(ctm.b), @"c" : @(ctm.c), @"d" : @(ctm.d), @"e" : @(ctm.tx), @"f" : @(ctm.ty)};
|
||||
}
|
||||
|
||||
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getScreenCTM : (nonnull NSNumber *)reactTag)
|
||||
{
|
||||
RNSVGPlatformView *view = [self getRenderableView:reactTag];
|
||||
|
||||
if (![view isKindOfClass:[RNSVGRenderable class]]) {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGRenderable, got: %@", view);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RNSVGRenderable *svg = (RNSVGRenderable *)view;
|
||||
CGAffineTransform ctm = svg.ctm;
|
||||
return @{@"a" : @(ctm.a), @"b" : @(ctm.b), @"c" : @(ctm.c), @"d" : @(ctm.d), @"e" : @(ctm.tx), @"f" : @(ctm.ty)};
|
||||
}
|
||||
|
||||
- (RNSVGPlatformView *)getRenderableView:(NSNumber *)reactTag
|
||||
{
|
||||
__block RNSVGPlatformView *view;
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
view = [self.bridge.uiManager viewForReactTag:reactTag];
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
*/
|
||||
|
||||
#import "RNSVGSvgViewManager.h"
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTUIManager.h>
|
||||
#import <React/RCTUIManagerUtils.h>
|
||||
#import "RNSVGSvgView.h"
|
||||
|
||||
@implementation RNSVGSvgViewManager
|
||||
@@ -32,58 +29,4 @@ RCT_EXPORT_VIEW_PROPERTY(meetOrSlice, RNSVGVBMOS)
|
||||
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)
|
||||
RCT_REMAP_VIEW_PROPERTY(color, tintColor, UIColor)
|
||||
|
||||
- (void)toDataURL:(nonnull NSNumber *)reactTag
|
||||
options:(NSDictionary *)options
|
||||
callback:(RCTResponseSenderBlock)callback
|
||||
attempt:(int)attempt
|
||||
{
|
||||
[self.bridge.uiManager
|
||||
addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, RNSVGPlatformView *> *viewRegistry) {
|
||||
__kindof RNSVGPlatformView *view = [uiManager viewForReactTag:reactTag];
|
||||
NSString *b64;
|
||||
if ([view isKindOfClass:[RNSVGSvgView class]]) {
|
||||
RNSVGSvgView *svg = view;
|
||||
if (options == nil) {
|
||||
b64 = [svg getDataURL];
|
||||
} else {
|
||||
id width = [options objectForKey:@"width"];
|
||||
id height = [options objectForKey:@"height"];
|
||||
if (![width isKindOfClass:NSNumber.class] || ![height isKindOfClass:NSNumber.class]) {
|
||||
RCTLogError(@"Invalid width or height given to toDataURL");
|
||||
return;
|
||||
}
|
||||
NSNumber *w = width;
|
||||
NSInteger wi = (NSInteger)[w intValue];
|
||||
NSNumber *h = height;
|
||||
NSInteger hi = (NSInteger)[h intValue];
|
||||
|
||||
CGRect bounds = CGRectMake(0, 0, wi, hi);
|
||||
b64 = [svg getDataURLwithBounds:bounds];
|
||||
}
|
||||
} else {
|
||||
RCTLogError(@"Invalid svg returned from registry, expecting RNSVGSvgView, got: %@", view);
|
||||
return;
|
||||
}
|
||||
if (b64) {
|
||||
callback(@[ b64 ]);
|
||||
} else if (attempt < 1) {
|
||||
void (^retryBlock)(void) = ^{
|
||||
[self toDataURL:reactTag options:options callback:callback attempt:(attempt + 1)];
|
||||
};
|
||||
|
||||
RCTExecuteOnUIManagerQueue(retryBlock);
|
||||
} else {
|
||||
callback(@[]);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(toDataURL
|
||||
: (nonnull NSNumber *)reactTag options
|
||||
: (NSDictionary *)options callback
|
||||
: (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
[self toDataURL:reactTag options:options callback:callback attempt:0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -32,7 +32,6 @@ RCT_CUSTOM_VIEW_PROPERTY(x, id, RNSVGText)
|
||||
{
|
||||
view.positionX = [RCTConvert RNSVGLengthArray:json];
|
||||
}
|
||||
|
||||
RCT_CUSTOM_VIEW_PROPERTY(y, id, RNSVGText)
|
||||
{
|
||||
view.positionY = [RCTConvert RNSVGLengthArray:json];
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
module.exports = {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: [
|
||||
'@react-native/babel-plugin-codegen',
|
||||
]
|
||||
};
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
||||
#include <react/renderer/imagemanager/ImageManager.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
#include "RNSVGImageShadowNode.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Descriptor for <RNSVGImage> component.
|
||||
*/
|
||||
class RNSVGImageComponentDescriptor final
|
||||
: public ConcreteComponentDescriptor<RNSVGImageShadowNode> {
|
||||
public:
|
||||
RNSVGImageComponentDescriptor(ComponentDescriptorParameters const ¶meters)
|
||||
: ConcreteComponentDescriptor(parameters),
|
||||
imageManager_(std::make_shared<ImageManager>(contextContainer_)){};
|
||||
|
||||
void adopt(ShadowNode::Unshared const &shadowNode) const override {
|
||||
ConcreteComponentDescriptor::adopt(shadowNode);
|
||||
|
||||
auto imageShadowNode =
|
||||
std::static_pointer_cast<RNSVGImageShadowNode>(shadowNode);
|
||||
|
||||
// `RNSVGImageShadowNode` uses `ImageManager` to initiate image loading and
|
||||
// communicate the loading state and results to mounting layer.
|
||||
imageShadowNode->setImageManager(imageManager_);
|
||||
}
|
||||
|
||||
private:
|
||||
const SharedImageManager imageManager_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
|
||||
#include <react/renderer/core/LayoutContext.h>
|
||||
|
||||
#include "RNSVGImageShadowNode.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
const char RNSVGImageComponentName[] = "RNSVGImage";
|
||||
|
||||
void RNSVGImageShadowNode::setImageManager(
|
||||
const SharedImageManager &imageManager) {
|
||||
ensureUnsealed();
|
||||
imageManager_ = imageManager;
|
||||
}
|
||||
|
||||
ImageSource RNSVGImageShadowNode::getImageSource() const {
|
||||
auto source = getConcreteProps().src;
|
||||
|
||||
auto layoutMetrics = getLayoutMetrics();
|
||||
auto size = layoutMetrics.getContentFrame().size;
|
||||
auto scale = layoutMetrics.pointScaleFactor;
|
||||
source.size = size;
|
||||
source.scale = scale;
|
||||
return source;
|
||||
}
|
||||
|
||||
void RNSVGImageShadowNode::updateStateIfNeeded() {
|
||||
ensureUnsealed();
|
||||
|
||||
auto imageSource = getImageSource();
|
||||
auto const ¤tState = getStateData();
|
||||
bool hasSameImageSource = currentState.getImageSource() == imageSource;
|
||||
|
||||
if (hasSameImageSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto state = RNSVGImageState{
|
||||
imageSource,
|
||||
imageManager_->requestImage(imageSource, getSurfaceId()),
|
||||
};
|
||||
setStateData(std::move(state));
|
||||
}
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void RNSVGImageShadowNode::layout(LayoutContext layoutContext) {
|
||||
updateStateIfNeeded();
|
||||
ConcreteViewShadowNode::layout(layoutContext);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
#include <react/renderer/components/rnsvg/EventEmitters.h>
|
||||
#include <react/renderer/components/rnsvg/Props.h>
|
||||
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
||||
#include <react/renderer/imagemanager/ImageManager.h>
|
||||
#include <react/renderer/imagemanager/primitives.h>
|
||||
|
||||
#include "RNSVGImageState.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
JSI_EXPORT extern const char RNSVGImageComponentName[];
|
||||
|
||||
/*
|
||||
* `ShadowNode` for <RNSVGImage> component.
|
||||
*/
|
||||
class JSI_EXPORT RNSVGImageShadowNode final : public ConcreteViewShadowNode<
|
||||
RNSVGImageComponentName,
|
||||
RNSVGImageProps,
|
||||
ViewEventEmitter,
|
||||
RNSVGImageState> {
|
||||
public:
|
||||
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
||||
|
||||
static ShadowNodeTraits BaseTraits() {
|
||||
auto traits = ConcreteViewShadowNode::BaseTraits();
|
||||
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
|
||||
return traits;
|
||||
}
|
||||
|
||||
/*
|
||||
* Associates a shared `ImageManager` with the node.
|
||||
*/
|
||||
void setImageManager(const SharedImageManager &imageManager);
|
||||
|
||||
static RNSVGImageState initialStateData(
|
||||
ShadowNodeFragment const &fragment,
|
||||
ShadowNodeFamilyFragment const &familyFragment,
|
||||
ComponentDescriptor const &componentDescriptor) {
|
||||
auto imageSource = ImageSource{ImageSource::Type::Invalid};
|
||||
return {imageSource, {imageSource, nullptr}};
|
||||
}
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void layout(LayoutContext layoutContext) override;
|
||||
|
||||
private:
|
||||
ImageSource getImageSource() const;
|
||||
|
||||
SharedImageManager imageManager_;
|
||||
|
||||
void updateStateIfNeeded();
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "RNSVGImageState.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ImageSource RNSVGImageState::getImageSource() const {
|
||||
return imageSource_;
|
||||
}
|
||||
|
||||
ImageRequest const &RNSVGImageState::getImageRequest() const {
|
||||
return *imageRequest_;
|
||||
}
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
64
common/cpp/react/renderer/components/rnsvg/RNSVGImageState.h
Normal file
64
common/cpp/react/renderer/components/rnsvg/RNSVGImageState.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
#include <react/renderer/imagemanager/ImageRequest.h>
|
||||
#include <react/renderer/imagemanager/primitives.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <react/renderer/mapbuffer/MapBuffer.h>
|
||||
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* State for <Image> component.
|
||||
*/
|
||||
class JSI_EXPORT RNSVGImageState final {
|
||||
public:
|
||||
RNSVGImageState(ImageSource const &imageSource, ImageRequest imageRequest)
|
||||
: imageSource_(imageSource),
|
||||
imageRequest_(
|
||||
std::make_shared<ImageRequest>(std::move(imageRequest))){};
|
||||
|
||||
/*
|
||||
* Returns stored ImageSource object.
|
||||
*/
|
||||
ImageSource getImageSource() const;
|
||||
|
||||
/*
|
||||
* Exposes for reading stored `ImageRequest` object.
|
||||
* `ImageRequest` object cannot be copied or moved from `ImageLocalData`.
|
||||
*/
|
||||
ImageRequest const &getImageRequest() const;
|
||||
|
||||
#ifdef ANDROID
|
||||
RNSVGImageState(RNSVGImageState const &previousState, folly::dynamic data){};
|
||||
|
||||
/*
|
||||
* Empty implementation for Android because it doesn't use this class.
|
||||
*/
|
||||
folly::dynamic getDynamic() const {
|
||||
return {};
|
||||
};
|
||||
|
||||
MapBuffer getMapBuffer() const {
|
||||
return MapBufferBuilder::EMPTY();
|
||||
};
|
||||
#endif
|
||||
|
||||
private:
|
||||
ImageSource imageSource_;
|
||||
std::shared_ptr<ImageRequest> imageRequest_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
26
package.json
26
package.json
@@ -16,12 +16,14 @@
|
||||
"__tests__",
|
||||
"android",
|
||||
"apple",
|
||||
"common",
|
||||
"elements",
|
||||
"lib",
|
||||
"src",
|
||||
"RNSVG.podspec",
|
||||
"!android/build",
|
||||
"windows"
|
||||
"windows",
|
||||
"react-native-config.js"
|
||||
],
|
||||
"@react-native-community/bob": {
|
||||
"source": "src",
|
||||
@@ -48,7 +50,7 @@
|
||||
"flow": "flow src",
|
||||
"flowtyped": "flow-typed install",
|
||||
"format": "yarn format-js && yarn format-ios && yarn format-java",
|
||||
"format-ios": "find apple/ -iname *.h -o -iname *.m -o -iname *.cpp -o -iname *.mm | xargs clang-format -i",
|
||||
"format-ios": "find apple/ common/ -iname *.h -o -iname *.m -o -iname *.cpp -o -iname *.mm | xargs clang-format -i",
|
||||
"format-java": "node ./scripts/format-java.js",
|
||||
"format-js": "prettier --write README.md CONTRIBUTING.md CODE_OF_CONDUCT.md USAGE.md './src/**/*.{ts,tsx}' './Example/**/*.{ts,tsx}'",
|
||||
"jest": "jest",
|
||||
@@ -56,7 +58,7 @@
|
||||
"peg": "pegjs -o src/lib/extract/transform.js ./src/lib/extract/transform.peg",
|
||||
"prepare": "npm run bob && husky install",
|
||||
"release": "npm login && release-it",
|
||||
"test": "npm run lint && npm run tsc && npm run jest",
|
||||
"test": "npm run lint && npm run tsc",
|
||||
"tsc": "tsc --noEmit"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -72,8 +74,12 @@
|
||||
"@babel/plugin-syntax-flow": "^7.17.12",
|
||||
"@babel/plugin-transform-react-jsx": "^7.17.12",
|
||||
"@react-native-community/bob": "^0.9.7",
|
||||
"@react-native-community/cli": "^9.0.0",
|
||||
"@react-native-community/cli-platform-android": "^9.0.0",
|
||||
"@react-native-community/cli-platform-ios": "^9.0.0",
|
||||
"@react-native-community/eslint-config": "^3.0.2",
|
||||
"@react-native-community/eslint-plugin": "^1.2.0",
|
||||
"@react-native/babel-plugin-codegen": "^0.71.0",
|
||||
"@types/css-tree": "^1.0.3",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "*",
|
||||
@@ -102,6 +108,11 @@
|
||||
"ts-node": "^10.8.0",
|
||||
"typescript": "^4.7.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"@react-native-community/cli-platform-android": "^9.0.0",
|
||||
"@react-native-community/cli": "^9.0.0",
|
||||
"@react-native-community/cli-platform-ios": "^9.0.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"{src,Example}/**/*.{js,ts,tsx}": "yarn format-js",
|
||||
"src/**/*.{js,ts,tsx}": "yarn lint",
|
||||
@@ -110,12 +121,11 @@
|
||||
},
|
||||
"nativePackage": true,
|
||||
"codegenConfig": {
|
||||
"libraries": [
|
||||
{
|
||||
"name": "rnsvg",
|
||||
"type": "components",
|
||||
"jsSrcsDir": "./src/fabric"
|
||||
"type": "all",
|
||||
"jsSrcsDir": "./src/fabric",
|
||||
"android": {
|
||||
"javaPackageName": "com.horcrux.rnsvg"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
42
react-native.config.js
Normal file
42
react-native.config.js
Normal file
@@ -0,0 +1,42 @@
|
||||
let supportsCodegenConfig = false;
|
||||
try {
|
||||
const rnCliAndroidVersion =
|
||||
require('@react-native-community/cli-platform-android/package.json').version;
|
||||
const [major] = rnCliAndroidVersion.split('.');
|
||||
supportsCodegenConfig = major >= 9;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
dependency: {
|
||||
platforms: {
|
||||
android: supportsCodegenConfig ? {
|
||||
componentDescriptors: [
|
||||
"RNSVGCircleComponentDescriptor",
|
||||
"RNSVGClipPathComponentDescriptor",
|
||||
"RNSVGDefsComponentDescriptor",
|
||||
"RNSVGEllipseComponentDescriptor",
|
||||
"RNSVGForeignObjectComponentDescriptor",
|
||||
"RNSVGGroupComponentDescriptor",
|
||||
"RNSVGImageComponentDescriptor",
|
||||
"RNSVGLinearGradientComponentDescriptor",
|
||||
"RNSVGLineComponentDescriptor",
|
||||
"RNSVGMarkerComponentDescriptor",
|
||||
"RNSVGMaskComponentDescriptor",
|
||||
"RNSVGPathComponentDescriptor",
|
||||
"RNSVGPatternComponentDescriptor",
|
||||
"RNSVGRadialGradientComponentDescriptor",
|
||||
"RNSVGRectComponentDescriptor",
|
||||
"RNSVGSvgViewAndroidComponentDescriptor",
|
||||
"RNSVGSymbolComponentDescriptor",
|
||||
"RNSVGTextComponentDescriptor",
|
||||
"RNSVGTextPathComponentDescriptor",
|
||||
"RNSVGTSpanComponentDescriptor",
|
||||
"RNSVGUseComponentDescriptor"
|
||||
],
|
||||
cmakeListsPath: "../android/src/main/jni/CMakeLists.txt"
|
||||
} : {},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,16 +1,10 @@
|
||||
import React, { useState, useEffect, Component } from 'react';
|
||||
import {
|
||||
NativeModules,
|
||||
Platform,
|
||||
Image,
|
||||
ImageSourcePropType,
|
||||
} from 'react-native';
|
||||
import { Platform, Image, ImageSourcePropType } from 'react-native';
|
||||
|
||||
import { fetchText } from './xml';
|
||||
import { SvgCss, SvgWithCss } from './css';
|
||||
import { SvgProps } from './elements/Svg';
|
||||
|
||||
const { getRawResource } = NativeModules.RNSVGRenderableManager || {};
|
||||
import type { Spec } from './fabric/NativeSvgRenderableModule';
|
||||
|
||||
export function getUriFromSource(source: ImageSourcePropType) {
|
||||
const resolvedAssetSource = Image.resolveAssetSource(source);
|
||||
@@ -28,7 +22,9 @@ export function isUriAnAndroidResourceIdentifier(uri?: string) {
|
||||
|
||||
export async function loadAndroidRawResource(uri: string) {
|
||||
try {
|
||||
return await getRawResource(uri);
|
||||
const RNSVGRenderableModule: Spec =
|
||||
require('./fabric/NativeSvgRenderableModule').default;
|
||||
return await RNSVGRenderableModule.getRawResource(uri);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
'Error in RawResourceUtils while trying to natively load an Android raw resource: ',
|
||||
@@ -60,7 +56,7 @@ export type LocalState = { xml: string | null };
|
||||
|
||||
export function LocalSvg(props: LocalProps) {
|
||||
const { asset, ...rest } = props;
|
||||
const [xml, setXml] = useState(null);
|
||||
const [xml, setXml] = useState<string | null>(null);
|
||||
useEffect(() => {
|
||||
loadLocalRawResource(asset).then(setXml);
|
||||
}, [asset]);
|
||||
|
||||
@@ -49,13 +49,14 @@ import {
|
||||
RNSVGPattern,
|
||||
RNSVGRadialGradient,
|
||||
RNSVGRect,
|
||||
RNSVGSvg,
|
||||
RNSVGSvgAndroid,
|
||||
RNSVGSvgIOS,
|
||||
RNSVGSymbol,
|
||||
RNSVGText,
|
||||
RNSVGTextPath,
|
||||
RNSVGTSpan,
|
||||
RNSVGUse,
|
||||
} from './elements/NativeComponents';
|
||||
} from './fabric';
|
||||
|
||||
export type { RectProps } from './elements/Rect';
|
||||
export type { CircleProps } from './elements/Circle';
|
||||
@@ -144,7 +145,8 @@ export {
|
||||
RNSVGEllipse,
|
||||
RNSVGCircle,
|
||||
RNSVGRect,
|
||||
RNSVGSvg,
|
||||
RNSVGSvgAndroid,
|
||||
RNSVGSvgIOS,
|
||||
RNSVGForeignObject,
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ import React from 'react';
|
||||
import { extract, stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGCircle } from './NativeComponents';
|
||||
import { RNSVGCircle } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface CircleProps extends CommonPathProps {
|
||||
cx?: NumberProp;
|
||||
@@ -28,6 +29,11 @@ export default class Circle extends Shape<CircleProps> {
|
||||
...stringifyPropsForFabric({ cx, cy, r }),
|
||||
};
|
||||
|
||||
return <RNSVGCircle ref={this.refMethod} {...circleProps} />;
|
||||
return (
|
||||
<RNSVGCircle
|
||||
ref={(ref) => this.refMethod(ref as (Circle & NativeMethods) | null)}
|
||||
{...circleProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import { extract } from '../lib/extract/extractProps';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGClipPath } from './NativeComponents';
|
||||
import { RNSVGClipPath } from '../ReactNativeSVG';
|
||||
|
||||
export interface ClipPathProps {
|
||||
children?: ReactNode;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import { RNSVGDefs } from './NativeComponents';
|
||||
import { RNSVGDefs } from '../ReactNativeSVG';
|
||||
|
||||
export default class Defs extends Component<React.PropsWithChildren<{}>> {
|
||||
static displayName = 'Defs';
|
||||
|
||||
@@ -2,7 +2,8 @@ import React from 'react';
|
||||
import { extract, stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGEllipse } from './NativeComponents';
|
||||
import { RNSVGEllipse } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface EllipseProps extends CommonPathProps {
|
||||
cx?: NumberProp;
|
||||
@@ -29,6 +30,11 @@ export default class Ellipse extends Shape<EllipseProps> {
|
||||
...extract(this, props),
|
||||
...stringifyPropsForFabric({ cx, cy, rx, ry }),
|
||||
};
|
||||
return <RNSVGEllipse ref={this.refMethod} {...ellipseProps} />;
|
||||
return (
|
||||
<RNSVGEllipse
|
||||
ref={(ref) => this.refMethod(ref as (Ellipse & NativeMethods) | null)}
|
||||
{...ellipseProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
} from '../lib/extract/extractProps';
|
||||
import { NumberProp } from '../lib/extract/types';
|
||||
import G from './G';
|
||||
import { RNSVGForeignObject } from './NativeComponents';
|
||||
import { RNSVGForeignObject } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface ForeignObjectProps {
|
||||
children?: ReactNode;
|
||||
@@ -31,7 +32,9 @@ export default class ForeignObject extends G<ForeignObjectProps> {
|
||||
const foreignObjectProps = stringifyPropsForFabric({ x, y, width, height });
|
||||
return (
|
||||
<RNSVGForeignObject
|
||||
ref={this.refMethod}
|
||||
ref={(ref) =>
|
||||
this.refMethod(ref as (ForeignObject & NativeMethods) | null)
|
||||
}
|
||||
{...withoutXY(this, props)}
|
||||
{...foreignObjectProps}
|
||||
>
|
||||
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
TransformProps,
|
||||
} from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGGroup } from './NativeComponents';
|
||||
import { RNSVGGroup } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface GProps extends CommonPathProps, FontProps {
|
||||
children?: ReactNode;
|
||||
@@ -40,7 +41,10 @@ export default class G<P> extends Shape<GProps & P> {
|
||||
extractedProps.font = font;
|
||||
}
|
||||
return (
|
||||
<RNSVGGroup ref={this.refMethod} {...extractedProps}>
|
||||
<RNSVGGroup
|
||||
ref={(ref) => this.refMethod(ref as (G<P> & NativeMethods) | null)}
|
||||
{...extractedProps}
|
||||
>
|
||||
{props.children}
|
||||
</RNSVGGroup>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Image, ImageProps as RNImageProps } from 'react-native';
|
||||
import { Image, ImageProps as RNImageProps, NativeMethods } from 'react-native';
|
||||
import { alignEnum, meetOrSliceTypes } from '../lib/extract/extractViewBox';
|
||||
import {
|
||||
stringifyPropsForFabric,
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
TouchableProps,
|
||||
} from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGImage } from './NativeComponents';
|
||||
import { RNSVGImage } from '../ReactNativeSVG';
|
||||
|
||||
const spacesRegExp = /\s+/;
|
||||
|
||||
@@ -82,7 +82,7 @@ export default class SvgImage extends Shape<ImageProps> {
|
||||
};
|
||||
return (
|
||||
<RNSVGImage
|
||||
ref={this.refMethod}
|
||||
ref={(ref) => this.refMethod(ref as (SvgImage & NativeMethods) | null)}
|
||||
{...withoutXY(this, props)}
|
||||
{...imageProps}
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,8 @@ import React from 'react';
|
||||
import { extract, stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGLine } from './NativeComponents';
|
||||
import { RNSVGLine } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface LineProps extends CommonPathProps {
|
||||
opacity?: NumberProp;
|
||||
@@ -29,6 +30,11 @@ export default class Line extends Shape<LineProps> {
|
||||
...extract(this, props),
|
||||
...stringifyPropsForFabric({ x1, y1, x2, y2 }),
|
||||
};
|
||||
return <RNSVGLine ref={this.refMethod} {...lineProps} />;
|
||||
return (
|
||||
<RNSVGLine
|
||||
ref={(ref) => this.refMethod(ref as (Line & NativeMethods) | null)}
|
||||
{...lineProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ import React, { ReactElement } from 'react';
|
||||
import extractGradient from '../lib/extract/extractGradient';
|
||||
import { NumberProp, TransformProps, Units } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGLinearGradient } from './NativeComponents';
|
||||
import { RNSVGLinearGradient } from '../ReactNativeSVG';
|
||||
import { stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface LinearGradientProps {
|
||||
children?: ReactElement[];
|
||||
@@ -32,7 +33,9 @@ export default class LinearGradient extends Shape<LinearGradientProps> {
|
||||
const linearGradientProps = stringifyPropsForFabric({ x1, y1, x2, y2 });
|
||||
return (
|
||||
<RNSVGLinearGradient
|
||||
ref={this.refMethod}
|
||||
ref={(ref) =>
|
||||
this.refMethod(ref as (LinearGradient & NativeMethods) | null)
|
||||
}
|
||||
{...linearGradientProps}
|
||||
{...extractGradient(props, this)}
|
||||
/>
|
||||
|
||||
@@ -2,8 +2,9 @@ import React, { ReactNode } from 'react';
|
||||
import extractViewBox from '../lib/extract/extractViewBox';
|
||||
import { NumberProp } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGMarker } from './NativeComponents';
|
||||
import { RNSVGMarker } from '../ReactNativeSVG';
|
||||
import { stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export type MarkerUnits = 'strokeWidth' | 'userSpaceOnUse';
|
||||
|
||||
@@ -60,7 +61,7 @@ export default class Marker extends Shape<MarkerProps> {
|
||||
|
||||
return (
|
||||
<RNSVGMarker
|
||||
ref={this.refMethod}
|
||||
ref={(ref) => this.refMethod(ref as (Marker & NativeMethods) | null)}
|
||||
{...markerProps}
|
||||
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
||||
>
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import units from '../lib/units';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGMask } from './NativeComponents';
|
||||
import { RNSVGMask } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export type TMaskUnits = 'userSpaceOnUse' | 'objectBoundingBox';
|
||||
|
||||
@@ -48,7 +49,7 @@ export default class Mask extends Shape<MaskProps> {
|
||||
};
|
||||
return (
|
||||
<RNSVGMask
|
||||
ref={this.refMethod}
|
||||
ref={(ref) => this.refMethod(ref as (Mask & NativeMethods) | null)}
|
||||
{...withoutXY(this, props)}
|
||||
{...strigifiedMaskProps}
|
||||
{...maskProps}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { requireNativeComponent as rnc } from 'react-native';
|
||||
import React from 'react';
|
||||
|
||||
declare module 'react-native' {
|
||||
function requireNativeComponent(
|
||||
viewName: string,
|
||||
): // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
React.ComponentType<React.PropsWithChildren<any>>;
|
||||
}
|
||||
|
||||
export const RNSVGSvg = rnc('RNSVGSvgView');
|
||||
export const RNSVGCircle = rnc('RNSVGCircle');
|
||||
export const RNSVGClipPath = rnc('RNSVGClipPath');
|
||||
export const RNSVGDefs = rnc('RNSVGDefs');
|
||||
export const RNSVGEllipse = rnc('RNSVGEllipse');
|
||||
export const RNSVGForeignObject = rnc('RNSVGForeignObject');
|
||||
export const RNSVGGroup = rnc('RNSVGGroup');
|
||||
export const RNSVGImage = rnc('RNSVGImage');
|
||||
export const RNSVGLine = rnc('RNSVGLine');
|
||||
export const RNSVGLinearGradient = rnc('RNSVGLinearGradient');
|
||||
export const RNSVGMarker = rnc('RNSVGMarker');
|
||||
export const RNSVGMask = rnc('RNSVGMask');
|
||||
export const RNSVGPath = rnc('RNSVGPath');
|
||||
export const RNSVGPattern = rnc('RNSVGPattern');
|
||||
export const RNSVGRadialGradient = rnc('RNSVGRadialGradient');
|
||||
export const RNSVGRect = rnc('RNSVGRect');
|
||||
export const RNSVGSymbol = rnc('RNSVGSymbol');
|
||||
export const RNSVGText = rnc('RNSVGText');
|
||||
export const RNSVGTextPath = rnc('RNSVGTextPath');
|
||||
export const RNSVGTSpan = rnc('RNSVGTSpan');
|
||||
export const RNSVGUse = rnc('RNSVGUse');
|
||||
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import { extract } from '../lib/extract/extractProps';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGPath } from './NativeComponents';
|
||||
import { RNSVGPath } from '../ReactNativeSVG';
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface PathProps extends CommonPathProps {
|
||||
d?: string;
|
||||
@@ -16,6 +17,12 @@ export default class Path extends Shape<PathProps> {
|
||||
const { props } = this;
|
||||
const { d } = props;
|
||||
const pathProps = { ...extract(this, props), d };
|
||||
return <RNSVGPath ref={this.refMethod} {...pathProps} />;
|
||||
|
||||
return (
|
||||
<RNSVGPath
|
||||
ref={(ref) => this.refMethod(ref as (Path & NativeMethods) | null)}
|
||||
{...pathProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ import extractViewBox from '../lib/extract/extractViewBox';
|
||||
import { NumberProp, TransformProps, Units } from '../lib/extract/types';
|
||||
import units from '../lib/units';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGPattern } from './NativeComponents';
|
||||
import { RNSVGPattern } from '../ReactNativeSVG';
|
||||
import { stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface PatternProps extends TransformProps {
|
||||
children?: ReactNode;
|
||||
@@ -63,7 +64,7 @@ export default class Pattern extends Shape<PatternProps> {
|
||||
};
|
||||
return (
|
||||
<RNSVGPattern
|
||||
ref={this.refMethod}
|
||||
ref={(ref) => this.refMethod(ref as (Pattern & NativeMethods) | null)}
|
||||
{...strigifiedPatternProps}
|
||||
{...patternProps}
|
||||
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
||||
|
||||
@@ -2,8 +2,9 @@ import React, { ReactElement } from 'react';
|
||||
import extractGradient from '../lib/extract/extractGradient';
|
||||
import { NumberProp, TransformProps, Units } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGRadialGradient } from './NativeComponents';
|
||||
import { RNSVGRadialGradient } from '../ReactNativeSVG';
|
||||
import { stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface RadialGradientProps {
|
||||
children?: ReactElement[];
|
||||
@@ -41,7 +42,9 @@ export default class RadialGradient extends Shape<RadialGradientProps> {
|
||||
});
|
||||
return (
|
||||
<RNSVGRadialGradient
|
||||
ref={this.refMethod}
|
||||
ref={(ref) =>
|
||||
this.refMethod(ref as (RadialGradient & NativeMethods) | null)
|
||||
}
|
||||
{...radialGradientProps}
|
||||
{...extractGradient(props, this)}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
} from '../lib/extract/extractProps';
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGRect } from './NativeComponents';
|
||||
import { RNSVGRect } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface RectProps extends CommonPathProps {
|
||||
x?: NumberProp;
|
||||
@@ -33,7 +34,7 @@ export default class Rect extends Shape<RectProps> {
|
||||
const rectProps = stringifyPropsForFabric({ x, y, width, height, rx, ry });
|
||||
return (
|
||||
<RNSVGRect
|
||||
ref={this.refMethod}
|
||||
ref={(ref) => this.refMethod(ref as (Rect & NativeMethods) | null)}
|
||||
{...withoutXY(this, props)}
|
||||
{...rectProps}
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Component } from 'react';
|
||||
import SvgTouchableMixin from '../lib/SvgTouchableMixin';
|
||||
import { NativeModules, findNodeHandle, NativeMethods } from 'react-native';
|
||||
import { findNodeHandle, NativeMethods } from 'react-native';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
TransformProps,
|
||||
} from '../lib/extract/types';
|
||||
const { RNSVGRenderableManager } = NativeModules;
|
||||
import type { Spec } from '../fabric/NativeSvgRenderableModule';
|
||||
|
||||
export interface SVGBoundingBoxOptions {
|
||||
fill?: boolean;
|
||||
@@ -242,27 +242,33 @@ export default class Shape<P> extends Component<P> {
|
||||
) => {
|
||||
this.root = instance;
|
||||
};
|
||||
// Hack to make Animated work with Shape components.
|
||||
getNativeScrollRef(): (Shape<P> & NativeMethods) | null {
|
||||
return this.root;
|
||||
}
|
||||
setNativeProps = (
|
||||
props: Object & {
|
||||
matrix?: ColumnMajorTransformMatrix;
|
||||
} & TransformProps,
|
||||
) => {
|
||||
this.root && this.root.setNativeProps(props);
|
||||
this.root?.setNativeProps(props);
|
||||
};
|
||||
/*
|
||||
* The following native methods are experimental and likely broken in some
|
||||
* ways. If you have a use case for these, please open an issue with a
|
||||
* representative example / reproduction.
|
||||
* */
|
||||
getBBox = (options?: SVGBoundingBoxOptions): SVGRect => {
|
||||
getBBox = (options?: SVGBoundingBoxOptions): SVGRect | undefined => {
|
||||
const {
|
||||
fill = true,
|
||||
stroke = true,
|
||||
markers = true,
|
||||
clipped = true,
|
||||
} = options || {};
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
return RNSVGRenderableManager.getBBox(handle, {
|
||||
const handle = findNodeHandle(this.root);
|
||||
const RNSVGRenderableModule =
|
||||
require('../fabric/NativeSvgRenderableModule').default;
|
||||
return RNSVGRenderableModule.getBBox(handle, {
|
||||
fill,
|
||||
stroke,
|
||||
markers,
|
||||
@@ -270,29 +276,41 @@ export default class Shape<P> extends Component<P> {
|
||||
});
|
||||
};
|
||||
getCTM = (): SVGMatrix => {
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
return new SVGMatrix(RNSVGRenderableManager.getCTM(handle));
|
||||
const handle = findNodeHandle(this.root);
|
||||
const RNSVGRenderableModule: Spec =
|
||||
require('../fabric/NativeSvgRenderableModule').default;
|
||||
return new SVGMatrix(RNSVGRenderableModule.getCTM(handle));
|
||||
};
|
||||
getScreenCTM = (): SVGMatrix => {
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
return new SVGMatrix(RNSVGRenderableManager.getScreenCTM(handle));
|
||||
const handle = findNodeHandle(this.root);
|
||||
const RNSVGRenderableModule: Spec =
|
||||
require('../fabric/NativeSvgRenderableModule').default;
|
||||
return new SVGMatrix(RNSVGRenderableModule.getScreenCTM(handle));
|
||||
};
|
||||
isPointInFill = (options: DOMPointInit): boolean => {
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
return RNSVGRenderableManager.isPointInFill(handle, options);
|
||||
isPointInFill = (options: DOMPointInit): boolean | undefined => {
|
||||
const handle = findNodeHandle(this.root);
|
||||
const RNSVGRenderableModule: Spec =
|
||||
require('../fabric/NativeSvgRenderableModule').default;
|
||||
return RNSVGRenderableModule.isPointInFill(handle, options);
|
||||
};
|
||||
isPointInStroke = (options: DOMPointInit): boolean => {
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
return RNSVGRenderableManager.isPointInStroke(handle, options);
|
||||
isPointInStroke = (options: DOMPointInit): boolean | undefined => {
|
||||
const handle = findNodeHandle(this.root);
|
||||
const RNSVGRenderableModule: Spec =
|
||||
require('../fabric/NativeSvgRenderableModule').default;
|
||||
return RNSVGRenderableModule.isPointInStroke(handle, options);
|
||||
};
|
||||
getTotalLength = (): number => {
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
return RNSVGRenderableManager.getTotalLength(handle);
|
||||
getTotalLength = (): number | undefined => {
|
||||
const handle = findNodeHandle(this.root);
|
||||
const RNSVGRenderableModule: Spec =
|
||||
require('../fabric/NativeSvgRenderableModule').default;
|
||||
return RNSVGRenderableModule.getTotalLength(handle);
|
||||
};
|
||||
getPointAtLength = (length: number): SVGPoint => {
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
const handle = findNodeHandle(this.root);
|
||||
const RNSVGRenderableModule: Spec =
|
||||
require('../fabric/NativeSvgRenderableModule').default;
|
||||
return new SVGPoint(
|
||||
RNSVGRenderableManager.getPointAtLength(handle, { length }),
|
||||
RNSVGRenderableModule.getPointAtLength(handle, { length }),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
MeasureInWindowOnSuccessCallback,
|
||||
MeasureLayoutOnSuccessCallback,
|
||||
MeasureOnSuccessCallback,
|
||||
NativeModules,
|
||||
NativeMethods,
|
||||
Platform,
|
||||
StyleProp,
|
||||
StyleSheet,
|
||||
ViewProps,
|
||||
@@ -20,9 +21,8 @@ import extractResponder from '../lib/extract/extractResponder';
|
||||
import extractViewBox from '../lib/extract/extractViewBox';
|
||||
import Shape from './Shape';
|
||||
import G, { GProps } from './G';
|
||||
import { RNSVGSvg } from './NativeComponents';
|
||||
|
||||
const RNSVGSvgViewManager = NativeModules.RNSVGSvgViewManager;
|
||||
import { RNSVGSvgAndroid, RNSVGSvgIOS } from '../ReactNativeSVG';
|
||||
import type { Spec } from '../fabric/NativeSvgViewModule';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
svg: {
|
||||
@@ -91,7 +91,9 @@ export default class Svg extends Shape<SvgProps> {
|
||||
return;
|
||||
}
|
||||
const handle = findNodeHandle(this.root as Component);
|
||||
RNSVGSvgViewManager.toDataURL(handle, options, callback);
|
||||
const RNSVGSvgViewModule: Spec =
|
||||
require('../fabric/NativeSvgViewModule').default;
|
||||
RNSVGSvgViewModule.toDataURL(handle, options, callback);
|
||||
};
|
||||
|
||||
render() {
|
||||
@@ -116,7 +118,6 @@ export default class Svg extends Shape<SvgProps> {
|
||||
|
||||
// Inherited G properties
|
||||
font,
|
||||
transform,
|
||||
fill,
|
||||
fillOpacity,
|
||||
fillRule,
|
||||
@@ -181,18 +182,24 @@ export default class Svg extends Shape<SvgProps> {
|
||||
props.onLayout = onLayout;
|
||||
}
|
||||
|
||||
// transform should not be passed down since it is already used in svgView
|
||||
// and would be doubled in G causing double transformations
|
||||
const gStyle = Object.assign({}, style) as ViewStyle;
|
||||
gStyle.transform = undefined;
|
||||
|
||||
const RNSVGSvg = Platform.OS === 'android' ? RNSVGSvgAndroid : RNSVGSvgIOS;
|
||||
|
||||
return (
|
||||
<RNSVGSvg
|
||||
{...props}
|
||||
ref={this.refMethod}
|
||||
ref={(ref) => this.refMethod(ref as (Svg & NativeMethods) | null)}
|
||||
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
||||
>
|
||||
<G
|
||||
{...{
|
||||
children,
|
||||
style,
|
||||
style: gStyle,
|
||||
font,
|
||||
transform,
|
||||
fill,
|
||||
fillOpacity,
|
||||
fillRule,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import extractViewBox from '../lib/extract/extractViewBox';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGSymbol } from './NativeComponents';
|
||||
import { RNSVGSymbol } from '../ReactNativeSVG';
|
||||
import { NumberProp } from '../lib/extract/types';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface SymbolProps {
|
||||
children?: ReactNode;
|
||||
@@ -21,7 +22,7 @@ export default class Symbol extends Shape<SymbolProps> {
|
||||
const symbolProps = { name: id };
|
||||
return (
|
||||
<RNSVGSymbol
|
||||
ref={this.refMethod}
|
||||
ref={(ref) => this.refMethod(ref as (Symbol & NativeMethods) | null)}
|
||||
{...symbolProps}
|
||||
{...extractViewBox(props)}
|
||||
>
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
NumberProp,
|
||||
TransformProps,
|
||||
} from '../lib/extract/types';
|
||||
import { RNSVGTSpan } from './NativeComponents';
|
||||
import { RNSVGTSpan } from '../ReactNativeSVG';
|
||||
|
||||
export interface TSpanProps extends CommonPathProps, FontProps {
|
||||
children?: TextChild;
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { pickNotNil } from '../lib/util';
|
||||
import Shape from './Shape';
|
||||
import './TSpan';
|
||||
import { RNSVGText } from './NativeComponents';
|
||||
import { RNSVGText } from '../ReactNativeSVG';
|
||||
|
||||
export interface TextProps extends TextSpecificProps {
|
||||
children?: ReactNode;
|
||||
|
||||
@@ -14,7 +14,7 @@ import extractText, { TextChild } from '../lib/extract/extractText';
|
||||
import { idPattern, pickNotNil } from '../lib/util';
|
||||
import Shape from './Shape';
|
||||
import TSpan from './TSpan';
|
||||
import { RNSVGTextPath } from './NativeComponents';
|
||||
import { RNSVGTextPath } from '../ReactNativeSVG';
|
||||
|
||||
export interface TextPathProps extends TextSpecificProps {
|
||||
children?: TextChild;
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import { idPattern } from '../lib/util';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGUse } from './NativeComponents';
|
||||
import { RNSVGUse } from '../ReactNativeSVG';
|
||||
import { NativeMethods } from 'react-native';
|
||||
|
||||
export interface UseProps extends CommonPathProps {
|
||||
children?: ReactNode;
|
||||
@@ -59,7 +60,11 @@ export default class Use extends Shape<UseProps> {
|
||||
height,
|
||||
});
|
||||
return (
|
||||
<RNSVGUse ref={this.refMethod} {...withoutXY(this, props)} {...useProps}>
|
||||
<RNSVGUse
|
||||
ref={(ref) => this.refMethod(ref as (Use & NativeMethods) | null)}
|
||||
{...withoutXY(this, props)}
|
||||
{...useProps}
|
||||
>
|
||||
{children}
|
||||
</RNSVGUse>
|
||||
);
|
||||
|
||||
77
src/fabric/AndroidSvgViewNativeComponent.ts
Normal file
77
src/fabric/AndroidSvgViewNativeComponent.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
|
||||
import type { ColorValue } from 'react-native';
|
||||
import type {
|
||||
Double,
|
||||
Float,
|
||||
Int32,
|
||||
} from 'react-native/Libraries/Types/CodegenTypes';
|
||||
import type { ViewProps } from './utils';
|
||||
|
||||
type NativeBackgroundProp = Readonly<{
|
||||
type?: string;
|
||||
color?: Float;
|
||||
borderless?: boolean;
|
||||
rippleRadius?: Float;
|
||||
}>;
|
||||
|
||||
type HitSlop = Readonly<{
|
||||
left?: Float;
|
||||
top?: Float;
|
||||
right?: Float;
|
||||
bottom?: Float;
|
||||
}>;
|
||||
|
||||
interface NativeProps extends ViewProps {
|
||||
bbWidth?: string;
|
||||
bbHeight?: string;
|
||||
minX?: Float;
|
||||
minY?: Float;
|
||||
vbWidth?: Float;
|
||||
vbHeight?: Float;
|
||||
align?: string;
|
||||
meetOrSlice?: Int32;
|
||||
tintColor?: ColorValue;
|
||||
color?: ColorValue;
|
||||
pointerEvents?: string;
|
||||
|
||||
// props needed for Android SvgView
|
||||
hasTVPreferredFocus?: boolean;
|
||||
borderTopEndRadius?: Float;
|
||||
borderBottomStartRadius?: Float;
|
||||
borderBottomColor?: ColorValue;
|
||||
nextFocusDown?: Int32;
|
||||
borderRightColor?: ColorValue;
|
||||
nextFocusRight?: Int32;
|
||||
borderLeftColor?: ColorValue;
|
||||
borderColor?: ColorValue;
|
||||
removeClippedSubviews?: boolean;
|
||||
nextFocusForward?: Int32;
|
||||
nextFocusUp?: Int32;
|
||||
accessible?: boolean;
|
||||
borderStartColor?: ColorValue;
|
||||
borderBottomEndRadius?: Float;
|
||||
borderEndColor?: ColorValue;
|
||||
focusable?: boolean;
|
||||
nativeBackgroundAndroid?: NativeBackgroundProp; // maybe there should a value accepted by codegen for this?
|
||||
borderTopStartRadius?: Float;
|
||||
nativeForegroundAndroid?: NativeBackgroundProp; // maybe there should a value accepted by codegen for this?
|
||||
backfaceVisibility?: string;
|
||||
borderStyle?: string;
|
||||
needsOffscreenAlphaCompositing?: boolean;
|
||||
hitSlop?: HitSlop;
|
||||
borderTopColor?: ColorValue;
|
||||
nextFocusLeft?: Int32;
|
||||
// TODO: those props are present in the `ReactPropGroup` but are not supported
|
||||
// (https://github.com/facebook/react-native/blob/35556dba600fbb28e0f41340a74b6c4a59bc6018/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java#L613)
|
||||
// and static view config validator says that they are missing.
|
||||
// We pass them as doubles although they should be floats, and cast them to floats again on the native side.
|
||||
borderTopRightRadius?: Double;
|
||||
borderBottomRightRadius?: Double;
|
||||
borderRadius?: Double;
|
||||
borderBottomLeftRadius?: Double;
|
||||
borderTopLeftRadius?: Double;
|
||||
}
|
||||
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGSvgViewAndroid', {
|
||||
excludedPlatforms: ['iOS'],
|
||||
});
|
||||
@@ -4,17 +4,19 @@ import type { Float, Int32 } from 'react-native/Libraries/Types/CodegenTypes';
|
||||
import type { ViewProps } from './utils';
|
||||
|
||||
interface NativeProps extends ViewProps {
|
||||
bbWidth: string;
|
||||
bbHeight: string;
|
||||
minX: Float;
|
||||
minY: Float;
|
||||
vbWidth: Float;
|
||||
vbHeight: Float;
|
||||
align: string;
|
||||
meetOrSlice: Int32;
|
||||
tintColor: ColorValue;
|
||||
color: ColorValue;
|
||||
bbWidth?: string;
|
||||
bbHeight?: string;
|
||||
minX?: Float;
|
||||
minY?: Float;
|
||||
vbWidth?: Float;
|
||||
vbHeight?: Float;
|
||||
align?: string;
|
||||
meetOrSlice?: Int32;
|
||||
tintColor?: ColorValue;
|
||||
color?: ColorValue;
|
||||
pointerEvents?: string;
|
||||
}
|
||||
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGSvgView');
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGSvgView', {
|
||||
excludedPlatforms: ['android'],
|
||||
});
|
||||
@@ -56,9 +56,11 @@ interface NativeProps
|
||||
y?: string;
|
||||
width?: string;
|
||||
height?: string;
|
||||
src?: ImageSource;
|
||||
src?: ImageSource | null;
|
||||
align?: string;
|
||||
meetOrSlice?: Int32;
|
||||
}
|
||||
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGImage');
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGImage', {
|
||||
interfaceOnly: true,
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ interface NativeProps extends ViewProps, SvgNodeCommonProps {
|
||||
y2?: string;
|
||||
gradient?: ReadonlyArray<Float>;
|
||||
gradientUnits?: Int32;
|
||||
gradientTransform?: ReadonlyArray<Float>;
|
||||
gradientTransform?: ReadonlyArray<Float> | null;
|
||||
}
|
||||
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGLinearGradient');
|
||||
|
||||
36
src/fabric/NativeSvgRenderableModule.ts
Normal file
36
src/fabric/NativeSvgRenderableModule.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { TurboModuleRegistry, TurboModule } from 'react-native';
|
||||
import { Int32, Float } from 'react-native/Libraries/Types/CodegenTypes';
|
||||
|
||||
type Rect = {
|
||||
x: Float;
|
||||
y: Float;
|
||||
width: Float;
|
||||
height: Float;
|
||||
};
|
||||
|
||||
type Matrix = {
|
||||
a: Float;
|
||||
b: Float;
|
||||
c: Float;
|
||||
d: Float;
|
||||
e: Float;
|
||||
f: Float;
|
||||
};
|
||||
|
||||
type Point = {
|
||||
x: Float;
|
||||
y: Float;
|
||||
};
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
isPointInFill(tag: Int32 | null, options?: Object): boolean;
|
||||
isPointInStroke(tag: Int32 | null, options?: Object): boolean;
|
||||
getTotalLength(tag: Int32 | null): Float;
|
||||
getPointAtLength(tag: Int32 | null, options?: Object): Point;
|
||||
getBBox(tag: Int32 | null, options?: Object): Rect;
|
||||
getCTM(tag: Int32 | null): Matrix;
|
||||
getScreenCTM(tag: Int32 | null): Matrix;
|
||||
getRawResource(name: string): Promise<string>;
|
||||
}
|
||||
|
||||
export default TurboModuleRegistry.getEnforcing<Spec>('RNSVGRenderableModule');
|
||||
12
src/fabric/NativeSvgViewModule.ts
Normal file
12
src/fabric/NativeSvgViewModule.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { TurboModuleRegistry, TurboModule } from 'react-native';
|
||||
import { Int32 } from 'react-native/Libraries/Types/CodegenTypes';
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
toDataURL(
|
||||
tag: Int32 | null,
|
||||
options?: Object,
|
||||
callback?: (base64: string) => void,
|
||||
): void;
|
||||
}
|
||||
|
||||
export default TurboModuleRegistry.getEnforcing<Spec>('RNSVGSvgViewModule');
|
||||
@@ -10,7 +10,7 @@ import type { ViewProps } from './utils';
|
||||
interface SvgNodeCommonProps {
|
||||
name?: string;
|
||||
opacity?: WithDefault<Float, 1.0>;
|
||||
matrix?: ReadonlyArray<Float>;
|
||||
matrix?: ReadonlyArray<Float> | null;
|
||||
mask?: string;
|
||||
markerStart?: string;
|
||||
markerMid?: string;
|
||||
@@ -78,7 +78,7 @@ interface NativeProps
|
||||
width?: string;
|
||||
patternUnits?: Int32;
|
||||
patternContentUnits?: Int32;
|
||||
patternTransform?: ReadonlyArray<Float>;
|
||||
patternTransform?: ReadonlyArray<Float> | null;
|
||||
minX?: Float;
|
||||
minY?: Float;
|
||||
vbWidth?: Float;
|
||||
|
||||
@@ -30,7 +30,7 @@ interface NativeProps extends ViewProps, SvgNodeCommonProps {
|
||||
ry?: string;
|
||||
gradient?: ReadonlyArray<Float>;
|
||||
gradientUnits?: Int32;
|
||||
gradientTransform?: ReadonlyArray<Float>;
|
||||
gradientTransform?: ReadonlyArray<Float> | null;
|
||||
}
|
||||
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGRadialGradient');
|
||||
|
||||
@@ -13,7 +13,8 @@ import RNSVGPath from './PathNativeComponent';
|
||||
import RNSVGPattern from './PatternNativeComponent';
|
||||
import RNSVGRadialGradient from './RadialGradientNativeComponent';
|
||||
import RNSVGRect from './RectNativeComponent';
|
||||
import RNSVGSvg from './SvgViewNativeComponent';
|
||||
import RNSVGSvgAndroid from './AndroidSvgViewNativeComponent';
|
||||
import RNSVGSvgIOS from './IOSSvgViewNativeComponent';
|
||||
import RNSVGSymbol from './SymbolNativeComponent';
|
||||
import RNSVGText from './TextNativeComponent';
|
||||
import RNSVGTextPath from './TextPathNativeComponent';
|
||||
@@ -36,7 +37,8 @@ export {
|
||||
RNSVGPattern,
|
||||
RNSVGRadialGradient,
|
||||
RNSVGRect,
|
||||
RNSVGSvg,
|
||||
RNSVGSvgAndroid,
|
||||
RNSVGSvgIOS,
|
||||
RNSVGSymbol,
|
||||
RNSVGText,
|
||||
RNSVGTextPath,
|
||||
|
||||
Reference in New Issue
Block a user