From 6a080f42e77a41308c00bc9467b2328840e369ee Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 11:56:31 +0200 Subject: [PATCH 01/10] feat: introduce FeOffset component --- react-native.config.js | 1 + src/ReactNativeSVG.ts | 5 ++++ src/elements/filters/FeOffset.tsx | 35 +++++++++++++++++++++++++++ src/fabric/FeOffsetNativeComponent.ts | 23 ++++++++++++++++++ src/fabric/index.ts | 2 ++ src/lib/extract/extractFilter.ts | 13 ++++++++++ src/xml.tsx | 2 ++ 7 files changed, 81 insertions(+) create mode 100644 src/elements/filters/FeOffset.tsx create mode 100644 src/fabric/FeOffsetNativeComponent.ts diff --git a/react-native.config.js b/react-native.config.js index 3d2f58f8f..3351fc6be 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -18,6 +18,7 @@ module.exports = { 'RNSVGClipPathComponentDescriptor', 'RNSVGDefsComponentDescriptor', 'RNSVGFeColorMatrixComponentDescriptor', + 'RNSVGFeOffsetComponentDescriptor', 'RNSVGFilterComponentDescriptor', 'RNSVGEllipseComponentDescriptor', 'RNSVGForeignObjectComponentDescriptor', diff --git a/src/ReactNativeSVG.ts b/src/ReactNativeSVG.ts index e7dc7d1e0..fca87c96e 100644 --- a/src/ReactNativeSVG.ts +++ b/src/ReactNativeSVG.ts @@ -25,6 +25,7 @@ import Marker from './elements/Marker'; import ForeignObject from './elements/ForeignObject'; import Filter from './elements/filters/Filter'; import FeColorMatrix from './elements/filters/FeColorMatrix'; +import FeOffset from './elements/filters/FeOffset'; import { parse, @@ -71,6 +72,7 @@ import { RNSVGUse, RNSVGFilter, RNSVGFeColorMatrix, + RNSVGFeOffset, } from './fabric'; export { @@ -109,6 +111,7 @@ export type { MarkerProps } from './elements/Marker'; export type { ForeignObjectProps } from './elements/ForeignObject'; export type { FilterProps } from './elements/filters/Filter'; export type { FeColorMatrixProps } from './elements/filters/FeColorMatrix'; +export type { FeOffsetProps } from './elements/filters/FeOffset'; export type { FilterPrimitiveCommonProps } from './elements/filters/FilterPrimitive'; export * from './lib/extract/types'; @@ -149,6 +152,7 @@ export { Shape, Filter, FeColorMatrix, + FeOffset, RNSVGMarker, RNSVGMask, RNSVGPattern, @@ -173,6 +177,7 @@ export { RNSVGForeignObject, RNSVGFilter, RNSVGFeColorMatrix, + RNSVGFeOffset, }; export type { diff --git a/src/elements/filters/FeOffset.tsx b/src/elements/filters/FeOffset.tsx new file mode 100644 index 000000000..74babd668 --- /dev/null +++ b/src/elements/filters/FeOffset.tsx @@ -0,0 +1,35 @@ +import * as React from 'react'; +import { NativeMethods } from 'react-native'; +import RNSVGFeOffset from '../../fabric/FeOffsetNativeComponent'; +import { + extractFeOffset, + extractFilter, +} from '../../lib/extract/extractFilter'; +import { NumberProp } from '../../lib/extract/types'; +import FilterPrimitive from './FilterPrimitive'; + +export interface FeOffsetProps { + in?: string; + dx?: NumberProp; + dy?: NumberProp; +} + +export default class FeOffset extends FilterPrimitive { + static displayName = 'FeOffset'; + + static defaultProps = { + ...this.defaultPrimitiveProps, + dx: 0, + dy: 0, + }; + + render() { + return ( + this.refMethod(ref as (FeOffset & NativeMethods) | null)} + {...extractFilter(this.props)} + {...extractFeOffset(this.props)} + /> + ); + } +} diff --git a/src/fabric/FeOffsetNativeComponent.ts b/src/fabric/FeOffsetNativeComponent.ts new file mode 100644 index 000000000..db975b379 --- /dev/null +++ b/src/fabric/FeOffsetNativeComponent.ts @@ -0,0 +1,23 @@ +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import type { ViewProps } from './utils'; + +import { NumberProp } from '../lib/extract/types'; +import type { UnsafeMixed } from './codegenUtils'; + +interface FilterPrimitiveStandardAttributes { + x?: UnsafeMixed; + y?: UnsafeMixed; + width?: UnsafeMixed; + height?: UnsafeMixed; + result?: string; +} + +export interface NativeProps + extends ViewProps, + FilterPrimitiveStandardAttributes { + in1?: string; + dx?: UnsafeMixed; + dy?: UnsafeMixed; +} + +export default codegenNativeComponent('RNSVGFeOffset'); diff --git a/src/fabric/index.ts b/src/fabric/index.ts index e7f395049..c5e7c290c 100644 --- a/src/fabric/index.ts +++ b/src/fabric/index.ts @@ -22,6 +22,7 @@ import RNSVGTSpan from './TSpanNativeComponent'; import RNSVGUse from './UseNativeComponent'; import RNSVGFilter from './FilterNativeComponent'; import RNSVGFeColorMatrix from './FeColorMatrixNativeComponent'; +import RNSVGFeOffset from './FeOffsetNativeComponent'; export { RNSVGCircle, @@ -48,4 +49,5 @@ export { RNSVGUse, RNSVGFilter, RNSVGFeColorMatrix, + RNSVGFeOffset, }; diff --git a/src/lib/extract/extractFilter.ts b/src/lib/extract/extractFilter.ts index 63a8e4bc3..db7ed1559 100644 --- a/src/lib/extract/extractFilter.ts +++ b/src/lib/extract/extractFilter.ts @@ -1,5 +1,7 @@ import { FeColorMatrixProps as FeColorMatrixComponentProps } from '../../elements/filters/FeColorMatrix'; import { NativeProps as FeColorMatrixNativeProps } from '../../fabric/FeColorMatrixNativeComponent'; +import { FeOffsetProps as FeOffsetComponentProps } from '../../elements/filters/FeOffset'; +import { NativeProps as FeOffsetNativeProps } from '../../fabric/FeOffsetNativeComponent'; import { NumberProp } from './types'; const spaceReg = /\s+/; @@ -53,3 +55,14 @@ export const extractFeColorMatrix = ( return extracted; }; + +export const extractFeOffset = ( + props: FeOffsetComponentProps +): FeOffsetNativeProps => { + const extracted: FeOffsetNativeProps = {}; + + if (props.dx) extracted.dx = props.dx; + if (props.dy) extracted.dy = props.dy; + + return extracted; +}; diff --git a/src/xml.tsx b/src/xml.tsx index 77e49c9a2..3c6d9dc13 100644 --- a/src/xml.tsx +++ b/src/xml.tsx @@ -27,6 +27,7 @@ import Mask from './elements/Mask'; import Marker from './elements/Marker'; import Filter from './elements/filters/Filter'; import FeColorMatrix from './elements/filters/FeColorMatrix'; +import FeOffset from './elements/filters/FeOffset'; export const tags: { [tag: string]: ComponentType } = { svg: Svg, @@ -54,6 +55,7 @@ export const tags: { [tag: string]: ComponentType } = { marker: Marker, filter: Filter, feColorMatrix: FeColorMatrix, + feOffset: FeOffset, }; function missingTag() { From f3f762449c6e2237f0dad8f05e966fad21d0d0ac Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 11:57:32 +0200 Subject: [PATCH 02/10] feat: implement FeOffset on apple --- apple/Filters/RNSVGFeOffset.h | 9 ++ apple/Filters/RNSVGFeOffset.mm | 126 +++++++++++++++++++++ apple/ViewManagers/RNSVGFeOffsetManager.h | 5 + apple/ViewManagers/RNSVGFeOffsetManager.mm | 17 +++ 4 files changed, 157 insertions(+) create mode 100644 apple/Filters/RNSVGFeOffset.h create mode 100644 apple/Filters/RNSVGFeOffset.mm create mode 100644 apple/ViewManagers/RNSVGFeOffsetManager.h create mode 100644 apple/ViewManagers/RNSVGFeOffsetManager.mm diff --git a/apple/Filters/RNSVGFeOffset.h b/apple/Filters/RNSVGFeOffset.h new file mode 100644 index 000000000..a41805d6f --- /dev/null +++ b/apple/Filters/RNSVGFeOffset.h @@ -0,0 +1,9 @@ +#import "RNSVGFilterPrimitive.h" + +@interface RNSVGFeOffset : RNSVGFilterPrimitive + +@property (nonatomic, strong) NSString *in1; +@property (nonatomic, strong) RNSVGLength *dx; +@property (nonatomic, strong) RNSVGLength *dy; + +@end diff --git a/apple/Filters/RNSVGFeOffset.mm b/apple/Filters/RNSVGFeOffset.mm new file mode 100644 index 000000000..a550b6c18 --- /dev/null +++ b/apple/Filters/RNSVGFeOffset.mm @@ -0,0 +1,126 @@ +#import "RNSVGFeOffset.h" + +#ifdef RCT_NEW_ARCH_ENABLED +#import +#import +#import +#import +#import "RNSVGFabricConversions.h" +#endif // RCT_NEW_ARCH_ENABLED + +@implementation RNSVGFeOffset + +#ifdef RCT_NEW_ARCH_ENABLED +using namespace facebook::react; + +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + } + return self; +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps +{ + const auto &newProps = static_cast(*props); + + self.in1 = RCTNSStringFromStringNilIfEmpty(newProps.in1); + id dx = RNSVGConvertFollyDynamicToId(newProps.dx); + if (dx != nil) { + self.dx = [RCTConvert RNSVGLength:dx]; + } + id dy = RNSVGConvertFollyDynamicToId(newProps.dy); + if (dy != nil) { + self.dy = [RCTConvert RNSVGLength:dy]; + } + + setCommonFilterProps(newProps, self); + _props = std::static_pointer_cast(props); +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + _in1 = nil; + _dx = nil; + _dy = nil; +} +#endif // RCT_NEW_ARCH_ENABLED + +- (void)setIn1:(NSString *)in1 +{ + if ([in1 isEqualToString:_in1]) { + return; + } + + _in1 = in1; + [self invalidate]; +} + +- (void)setDx:(RNSVGLength *)dx +{ + if ([dx isEqualTo:_dx]) { + return; + } + + _dx = dx; + [self invalidate]; +} + +- (void)setDy:(RNSVGLength *)dy +{ + if ([dy isEqualTo:_dy]) { + return; + } + + _dy = dy; + [self invalidate]; +} + +- (CIImage *)applyFilter:(NSMutableDictionary *)results + previousFilterResult:(CIImage *)previous + ctm:(CGAffineTransform)ctm +{ + CIImage *inResults = self.in1 ? [results objectForKey:self.in1] : nil; + CIImage *inputImage = inResults ? inResults : previous; + + if (!inputImage) { + return nil; + } + + CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform"]; + [filter setDefaults]; + [filter setValue:inputImage forKey:@"inputImage"]; + + CGFloat dx = [self relativeOnWidth:self.dx]; + CGFloat dy = [self relativeOnWidth:self.dy]; + + // reset ctm translation + CGAffineTransform contextTransform = CGAffineTransformConcat(ctm, CGAffineTransformMakeTranslation(-ctm.tx, -ctm.ty)); + + CGPoint translate = CGPointMake(dx, dy); + translate = CGPointApplyAffineTransform(translate, contextTransform); + CGAffineTransform transform = CGAffineTransformMakeTranslation(translate.x, translate.y); + + [filter setValue:[NSValue valueWithCGAffineTransform:transform] forKey:@"inputTransform"]; + + return [filter valueForKey:@"outputImage"]; +} + +#ifdef RCT_NEW_ARCH_ENABLED +Class RNSVGFeOffsetCls(void) +{ + return RNSVGFeOffset.class; +} +#endif // RCT_NEW_ARCH_ENABLED + +@end diff --git a/apple/ViewManagers/RNSVGFeOffsetManager.h b/apple/ViewManagers/RNSVGFeOffsetManager.h new file mode 100644 index 000000000..b9b9ba432 --- /dev/null +++ b/apple/ViewManagers/RNSVGFeOffsetManager.h @@ -0,0 +1,5 @@ +#import "RNSVGFilterPrimitiveManager.h" + +@interface RNSVGFeOffsetManager : RNSVGFilterPrimitiveManager + +@end diff --git a/apple/ViewManagers/RNSVGFeOffsetManager.mm b/apple/ViewManagers/RNSVGFeOffsetManager.mm new file mode 100644 index 000000000..801f81d32 --- /dev/null +++ b/apple/ViewManagers/RNSVGFeOffsetManager.mm @@ -0,0 +1,17 @@ +#import "RNSVGFeOffsetManager.h" +#import "RNSVGFeOffset.h" + +@implementation RNSVGFeOffsetManager + +RCT_EXPORT_MODULE() + +- (RNSVGFeOffset *)node +{ + return [RNSVGFeOffset new]; +} + +RCT_EXPORT_VIEW_PROPERTY(in1, NSString) +RCT_EXPORT_VIEW_PROPERTY(dx, RNSVGLength *) +RCT_EXPORT_VIEW_PROPERTY(dy, RNSVGLength *) + +@end From 2df41dcb8f39210f197bbf2152d5f565fc5b1537 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 11:58:58 +0200 Subject: [PATCH 03/10] feat: add ctm to applyFilter function if needed --- apple/Filters/RNSVGFilter.mm | 2 +- apple/Filters/RNSVGFilterPrimitive.h | 3 +++ apple/Filters/RNSVGFilterPrimitive.mm | 7 +++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/apple/Filters/RNSVGFilter.mm b/apple/Filters/RNSVGFilter.mm index c5c7570f4..07b6ac650 100644 --- a/apple/Filters/RNSVGFilter.mm +++ b/apple/Filters/RNSVGFilter.mm @@ -97,7 +97,7 @@ - (CIImage *)applyFilter:(CIImage *)img for (RNSVGNode *node in self.subviews) { if ([node isKindOfClass:[RNSVGFilterPrimitive class]]) { currentFilter = (RNSVGFilterPrimitive *)node; - result = [currentFilter applyFilter:resultsMap previousFilterResult:result]; + result = [currentFilter applyFilter:resultsMap previousFilterResult:result ctm:ctm]; if (currentFilter.result) { [resultsMap setObject:result forKey:currentFilter.result]; } diff --git a/apple/Filters/RNSVGFilterPrimitive.h b/apple/Filters/RNSVGFilterPrimitive.h index 7d45e2cf1..2adeecf44 100644 --- a/apple/Filters/RNSVGFilterPrimitive.h +++ b/apple/Filters/RNSVGFilterPrimitive.h @@ -9,6 +9,9 @@ @property (nonatomic, strong) NSString *result; - (CIImage *)applyFilter:(NSMutableDictionary *)results previousFilterResult:(CIImage *)previous; +- (CIImage *)applyFilter:(NSMutableDictionary *)results + previousFilterResult:(CIImage *)previous + ctm:(CGAffineTransform)ctm; - (CIImage *)cropResult:(CIImage *)result; @end diff --git a/apple/Filters/RNSVGFilterPrimitive.mm b/apple/Filters/RNSVGFilterPrimitive.mm index 3dcc4f837..6c547c81a 100644 --- a/apple/Filters/RNSVGFilterPrimitive.mm +++ b/apple/Filters/RNSVGFilterPrimitive.mm @@ -93,6 +93,13 @@ - (CIImage *)applyFilter:(NSMutableDictionary *)results p return previous; } +- (CIImage *)applyFilter:(NSMutableDictionary *)results + previousFilterResult:(CIImage *)previous + ctm:(CGAffineTransform)ctm +{ + return [self applyFilter:results previousFilterResult:previous]; +} + - (CIImage *)cropResult:(CIImage *)result { CIFilter *filter = [CIFilter filterWithName:@"CICrop"]; From ea062b7b523c753e5cda8ac003711742c6c7a47d Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 12:13:41 +0200 Subject: [PATCH 04/10] feat: implement FeOffset on android --- .../java/com/horcrux/svg/FeOffsetView.java | 50 +++++++++++++++++ .../horcrux/svg/RenderableViewManager.java | 55 +++++++++++++++++++ .../main/java/com/horcrux/svg/SvgPackage.java | 9 +++ 3 files changed, 114 insertions(+) create mode 100644 android/src/main/java/com/horcrux/svg/FeOffsetView.java diff --git a/android/src/main/java/com/horcrux/svg/FeOffsetView.java b/android/src/main/java/com/horcrux/svg/FeOffsetView.java new file mode 100644 index 000000000..c583c5c4a --- /dev/null +++ b/android/src/main/java/com/horcrux/svg/FeOffsetView.java @@ -0,0 +1,50 @@ +package com.horcrux.svg; + +import android.annotation.SuppressLint; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import com.facebook.react.bridge.Dynamic; +import com.facebook.react.bridge.ReactContext; +import java.util.HashMap; + +@SuppressLint("ViewConstructor") +class FeOffsetView extends FilterPrimitiveView { + String mIn1; + SVGLength mDx; + SVGLength mDy; + + public FeOffsetView(ReactContext reactContext) { + super(reactContext); + } + + public void setIn1(String in1) { + this.mIn1 = in1; + invalidate(); + } + + public void setDx(Dynamic dx) { + mDx = SVGLength.from(dx); + invalidate(); + } + + public void setDy(Dynamic dy) { + mDy = SVGLength.from(dy); + invalidate(); + } + + @Override + public Bitmap applyFilter(HashMap resultsMap, Bitmap prevResult) { + Bitmap source = getSource(resultsMap, prevResult, this.mIn1); + Bitmap result = + Bitmap.createBitmap(prevResult.getWidth(), prevResult.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(result); + + float dx = this.mDx != null ? (float) this.relativeOnWidth(this.mDx) : 0; + float dy = this.mDy != null ? (float) this.relativeOnHeight(this.mDy) : 0; + + canvas.drawBitmap(source, dx, dy, new Paint()); + + return result; + } +} diff --git a/android/src/main/java/com/horcrux/svg/RenderableViewManager.java b/android/src/main/java/com/horcrux/svg/RenderableViewManager.java index bf9de5d33..77f44151c 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableViewManager.java +++ b/android/src/main/java/com/horcrux/svg/RenderableViewManager.java @@ -105,6 +105,8 @@ import com.facebook.react.viewmanagers.RNSVGEllipseManagerInterface; import com.facebook.react.viewmanagers.RNSVGFeColorMatrixManagerDelegate; import com.facebook.react.viewmanagers.RNSVGFeColorMatrixManagerInterface; +import com.facebook.react.viewmanagers.RNSVGFeOffsetManagerDelegate; +import com.facebook.react.viewmanagers.RNSVGFeOffsetManagerInterface; import com.facebook.react.viewmanagers.RNSVGFilterManagerDelegate; import com.facebook.react.viewmanagers.RNSVGFilterManagerInterface; import com.facebook.react.viewmanagers.RNSVGForeignObjectManagerDelegate; @@ -584,6 +586,7 @@ protected enum SVGClass { RNSVGMask, RNSVGFilter, RNSVGFeColorMatrix, + RNSVGFeOffset, RNSVGMarker, RNSVGForeignObject, } @@ -632,6 +635,8 @@ protected VirtualView createViewInstance(@Nonnull ThemedReactContext reactContex return new FilterView(reactContext); case RNSVGFeColorMatrix: return new FeColorMatrixView(reactContext); + case RNSVGFeOffset: + return new FeOffsetView(reactContext); case RNSVGMarker: return new MarkerView(reactContext); case RNSVGForeignObject: @@ -1387,6 +1392,56 @@ public void setValues(FeColorMatrixView node, @Nullable ReadableArray values) { } } + static class FeOffsetManager extends VirtualViewManager + implements RNSVGFeOffsetManagerInterface { + FeOffsetManager() { + super(SVGClass.RNSVGFeOffset); + mDelegate = new RNSVGFeOffsetManagerDelegate(this); + } + + public static final String REACT_CLASS = "RNSVGFeOffset"; + + @ReactProp(name = "x") + public void setX(FeOffsetView node, Dynamic x) { + node.setX(x); + } + + @ReactProp(name = "y") + public void setY(FeOffsetView node, Dynamic y) { + node.setY(y); + } + + @ReactProp(name = "width") + public void setWidth(FeOffsetView node, Dynamic width) { + node.setWidth(width); + } + + @ReactProp(name = "height") + public void setHeight(FeOffsetView node, Dynamic height) { + node.setHeight(height); + } + + @ReactProp(name = "result") + public void setResult(FeOffsetView node, String result) { + node.setResult(result); + } + + @ReactProp(name = "in1") + public void setIn1(FeOffsetView node, String in1) { + node.setIn1(in1); + } + + @ReactProp(name = "dx") + public void setDx(FeOffsetView node, Dynamic dx) { + node.setDx(dx); + } + + @ReactProp(name = "dy") + public void setDy(FeOffsetView node, Dynamic dy) { + node.setDy(dy); + } + } + static class ForeignObjectManager extends GroupViewManagerAbstract implements RNSVGForeignObjectManagerInterface { ForeignObjectManager() { diff --git a/android/src/main/java/com/horcrux/svg/SvgPackage.java b/android/src/main/java/com/horcrux/svg/SvgPackage.java index bab495487..b2a05228b 100644 --- a/android/src/main/java/com/horcrux/svg/SvgPackage.java +++ b/android/src/main/java/com/horcrux/svg/SvgPackage.java @@ -223,6 +223,15 @@ public NativeModule get() { return new FeColorMatrixManager(); } })); + specs.put( + FeOffsetManager.REACT_CLASS, + ModuleSpec.viewManagerSpec( + new Provider() { + @Override + public NativeModule get() { + return new FeOffsetManager(); + } + })); specs.put( ForeignObjectManager.REACT_CLASS, ModuleSpec.viewManagerSpec( From 18777282caf51259d6be220b987be9646e1cff52 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 12:13:55 +0200 Subject: [PATCH 05/10] chore: codegen --- .../RNSVGFeOffsetManagerDelegate.java | 53 +++++++++++++++++++ .../RNSVGFeOffsetManagerInterface.java | 25 +++++++++ 2 files changed, 78 insertions(+) create mode 100644 android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerDelegate.java create mode 100644 android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerInterface.java diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerDelegate.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerDelegate.java new file mode 100644 index 000000000..6458442d0 --- /dev/null +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerDelegate.java @@ -0,0 +1,53 @@ +/** +* 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.DynamicFromObject; +import com.facebook.react.uimanager.BaseViewManagerDelegate; +import com.facebook.react.uimanager.BaseViewManagerInterface; + +public class RNSVGFeOffsetManagerDelegate & RNSVGFeOffsetManagerInterface> extends BaseViewManagerDelegate { + public RNSVGFeOffsetManagerDelegate(U viewManager) { + super(viewManager); + } + @Override + public void setProperty(T view, String propName, @Nullable Object value) { + switch (propName) { + case "x": + mViewManager.setX(view, new DynamicFromObject(value)); + break; + case "y": + mViewManager.setY(view, new DynamicFromObject(value)); + break; + case "width": + mViewManager.setWidth(view, new DynamicFromObject(value)); + break; + case "height": + mViewManager.setHeight(view, new DynamicFromObject(value)); + break; + case "result": + mViewManager.setResult(view, value == null ? null : (String) value); + break; + case "in1": + mViewManager.setIn1(view, value == null ? null : (String) value); + break; + case "dx": + mViewManager.setDx(view, new DynamicFromObject(value)); + break; + case "dy": + mViewManager.setDy(view, new DynamicFromObject(value)); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerInterface.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerInterface.java new file mode 100644 index 000000000..adf76fd02 --- /dev/null +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeOffsetManagerInterface.java @@ -0,0 +1,25 @@ +/** +* 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.Dynamic; + +public interface RNSVGFeOffsetManagerInterface { + void setX(T view, Dynamic value); + void setY(T view, Dynamic value); + void setWidth(T view, Dynamic value); + void setHeight(T view, Dynamic value); + void setResult(T view, @Nullable String value); + void setIn1(T view, @Nullable String value); + void setDx(T view, Dynamic value); + void setDy(T view, Dynamic value); +} From ba0f859dffd6a685cfa71dc7e89d8c0319f3b980 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 12:14:21 +0200 Subject: [PATCH 06/10] docs: add FeOffset example --- .../src/examples/Filters/FeOffset.tsx | 47 +++++++++++++++++++ .../src/examples/Filters/examples.tsx | 3 +- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 apps/examples/src/examples/Filters/FeOffset.tsx diff --git a/apps/examples/src/examples/Filters/FeOffset.tsx b/apps/examples/src/examples/Filters/FeOffset.tsx new file mode 100644 index 000000000..a1dcbc06d --- /dev/null +++ b/apps/examples/src/examples/Filters/FeOffset.tsx @@ -0,0 +1,47 @@ +import React, {Component} from 'react'; +import {FeOffset, Filter, Rect, Svg} from 'react-native-svg'; + +class ReferenceExample extends Component { + static title = 'Offset'; + render() { + return ( + + + + + + + + + + ); + } +} + +const icon = ( + + + + + + + +); + +const samples = [ReferenceExample]; +export {icon, samples}; diff --git a/apps/examples/src/examples/Filters/examples.tsx b/apps/examples/src/examples/Filters/examples.tsx index 4d239a51a..70c03f4af 100644 --- a/apps/examples/src/examples/Filters/examples.tsx +++ b/apps/examples/src/examples/Filters/examples.tsx @@ -1,3 +1,4 @@ import * as FeColorMatrix from './FeColorMatrix'; +import * as FeOffset from './FeOffset'; import * as ReanimatedFeColorMatrix from './ReanimatedFeColorMatrix'; -export {FeColorMatrix, ReanimatedFeColorMatrix}; +export {FeColorMatrix, FeOffset, ReanimatedFeColorMatrix}; From a41e525deccea7dd50da67a5965b6f391f69df08 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 12:15:17 +0200 Subject: [PATCH 07/10] docs: add FeOffset to supported filters --- USAGE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/USAGE.md b/USAGE.md index 4735fb8c2..74535e8bd 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1260,6 +1260,7 @@ Filter effects are a way of processing an element’s rendering before it is dis Currently supported\* filters are: - FeColorMatrix +- FeOffset \*_More filters are coming soon_ From e66d91e68d663d7c193d4752d91b23add0966d1b Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 15:04:07 +0200 Subject: [PATCH 08/10] fix: rename StandardAttributes to CommonProps --- src/fabric/FeOffsetNativeComponent.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/fabric/FeOffsetNativeComponent.ts b/src/fabric/FeOffsetNativeComponent.ts index db975b379..403845ee9 100644 --- a/src/fabric/FeOffsetNativeComponent.ts +++ b/src/fabric/FeOffsetNativeComponent.ts @@ -4,7 +4,7 @@ import type { ViewProps } from './utils'; import { NumberProp } from '../lib/extract/types'; import type { UnsafeMixed } from './codegenUtils'; -interface FilterPrimitiveStandardAttributes { +interface FilterPrimitiveCommonProps { x?: UnsafeMixed; y?: UnsafeMixed; width?: UnsafeMixed; @@ -12,9 +12,7 @@ interface FilterPrimitiveStandardAttributes { result?: string; } -export interface NativeProps - extends ViewProps, - FilterPrimitiveStandardAttributes { +export interface NativeProps extends ViewProps, FilterPrimitiveCommonProps { in1?: string; dx?: UnsafeMixed; dy?: UnsafeMixed; From a1d3a3567afe6acb1aba109d9c1c54680548d9ec Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Tue, 23 Jul 2024 15:54:23 +0200 Subject: [PATCH 09/10] fix: add in prop to extracted and apply codestyle --- src/lib/extract/extractFilter.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/lib/extract/extractFilter.ts b/src/lib/extract/extractFilter.ts index db7ed1559..4d821ef3e 100644 --- a/src/lib/extract/extractFilter.ts +++ b/src/lib/extract/extractFilter.ts @@ -51,7 +51,9 @@ export const extractFeColorMatrix = ( console.warn('Invalid value for FeColorMatrix `values` prop'); } } - if (props.type) extracted.type = props.type; + if (props.type) { + extracted.type = props.type; + } return extracted; }; @@ -61,8 +63,15 @@ export const extractFeOffset = ( ): FeOffsetNativeProps => { const extracted: FeOffsetNativeProps = {}; - if (props.dx) extracted.dx = props.dx; - if (props.dy) extracted.dy = props.dy; + if (props.in) { + extracted.in1 = props.in; + } + if (props.dx) { + extracted.dx = props.dx; + } + if (props.dy) { + extracted.dy = props.dy; + } return extracted; }; From 3a9a2884bfb5266a186665168e07a8da4899697a Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 25 Jul 2024 10:27:33 +0200 Subject: [PATCH 10/10] feat: add feOffset to filterImage types --- src/filter-image/types.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/filter-image/types.ts b/src/filter-image/types.ts index e95139e62..252e2ebdf 100644 --- a/src/filter-image/types.ts +++ b/src/filter-image/types.ts @@ -1,7 +1,10 @@ import { FilterPrimitiveCommonProps } from '../elements/filters/FilterPrimitive'; -import { FeColorMatrixProps } from '../index'; +import { FeColorMatrixProps, FeOffsetProps } from '../index'; -export type FilterElement = ({ name: 'feColorMatrix' } & FeColorMatrixProps) & +export type FilterElement = ( + | ({ name: 'feColorMatrix' } & FeColorMatrixProps) + | ({ name: 'feOffset' } & FeOffsetProps) +) & FilterPrimitiveCommonProps; export type Filters = Array;