diff --git a/USAGE.md b/USAGE.md index f4cd86bf4..3590bb986 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1261,6 +1261,7 @@ Currently supported\* filters are: - FeColorMatrix - FeGaussianBlur +- FeOffset \*_More filters are coming soon_ 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 35af96bc8..7cafa69b1 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableViewManager.java +++ b/android/src/main/java/com/horcrux/svg/RenderableViewManager.java @@ -107,6 +107,8 @@ import com.facebook.react.viewmanagers.RNSVGFeColorMatrixManagerInterface; import com.facebook.react.viewmanagers.RNSVGFeGaussianBlurManagerDelegate; import com.facebook.react.viewmanagers.RNSVGFeGaussianBlurManagerInterface; +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; @@ -587,6 +589,7 @@ protected enum SVGClass { RNSVGFilter, RNSVGFeColorMatrix, RNSVGFeGaussianBlur, + RNSVGFeOffset, RNSVGMarker, RNSVGForeignObject, } @@ -637,6 +640,8 @@ protected VirtualView createViewInstance(@Nonnull ThemedReactContext reactContex return new FeColorMatrixView(reactContext); case RNSVGFeGaussianBlur: return new FeGaussianBlurView(reactContext); + case RNSVGFeOffset: + return new FeOffsetView(reactContext); case RNSVGMarker: return new MarkerView(reactContext); case RNSVGForeignObject: @@ -1447,6 +1452,56 @@ public void setEdgeMode(FeGaussianBlurView node, String edgeMode) { } } + 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 d33f275f4..e6e91e1af 100644 --- a/android/src/main/java/com/horcrux/svg/SvgPackage.java +++ b/android/src/main/java/com/horcrux/svg/SvgPackage.java @@ -232,6 +232,15 @@ public NativeModule get() { return new FeGaussianBlurManager(); } })); + specs.put( + FeOffsetManager.REACT_CLASS, + ModuleSpec.viewManagerSpec( + new Provider() { + @Override + public NativeModule get() { + return new FeOffsetManager(); + } + })); specs.put( ForeignObjectManager.REACT_CLASS, ModuleSpec.viewManagerSpec( 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); +} 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/Filters/RNSVGFilter.mm b/apple/Filters/RNSVGFilter.mm index 5257e5bde..2acccd51f 100644 --- a/apple/Filters/RNSVGFilter.mm +++ b/apple/Filters/RNSVGFilter.mm @@ -99,7 +99,8 @@ - (CIImage *)applyFilter:(CIImage *)img if ([node isKindOfClass:[RNSVGFilterPrimitive class]]) { currentFilter = (RNSVGFilterPrimitive *)node; CGImageRef cgResult = [[RNSVGRenderUtils sharedCIContext] createCGImage:[currentFilter applyFilter:resultsMap - previousFilterResult:result] + previousFilterResult:result + ctm:ctm] fromRect:[result extent]]; result = [CIImage imageWithCGImage:cgResult]; CGImageRelease(cgResult); 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"]; 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 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 71071acbc..065780f19 100644 --- a/apps/examples/src/examples/Filters/examples.tsx +++ b/apps/examples/src/examples/Filters/examples.tsx @@ -1,4 +1,5 @@ import * as FeColorMatrix from './FeColorMatrix'; import * as FeGaussianBlur from './FeGaussianBlur'; +import * as FeOffset from './FeOffset'; import * as ReanimatedFeColorMatrix from './ReanimatedFeColorMatrix'; -export {FeColorMatrix, FeGaussianBlur, ReanimatedFeColorMatrix}; +export {FeColorMatrix, FeGaussianBlur, FeOffset, ReanimatedFeColorMatrix}; diff --git a/react-native.config.js b/react-native.config.js index f4c94a1f2..eeec98f13 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -19,6 +19,7 @@ module.exports = { 'RNSVGDefsComponentDescriptor', 'RNSVGFeColorMatrixComponentDescriptor', 'RNSVGFeGaussianBlurComponentDescriptor', + 'RNSVGFeOffsetComponentDescriptor', 'RNSVGFilterComponentDescriptor', 'RNSVGEllipseComponentDescriptor', 'RNSVGForeignObjectComponentDescriptor', diff --git a/src/ReactNativeSVG.ts b/src/ReactNativeSVG.ts index c86002ac9..89aea0bf7 100644 --- a/src/ReactNativeSVG.ts +++ b/src/ReactNativeSVG.ts @@ -26,6 +26,7 @@ import ForeignObject from './elements/ForeignObject'; import Filter from './elements/filters/Filter'; import FeColorMatrix from './elements/filters/FeColorMatrix'; import FeGaussianBlur from './elements/filters/FeGaussianBlur'; +import FeOffset from './elements/filters/FeOffset'; import { parse, @@ -73,6 +74,7 @@ import { RNSVGFilter, RNSVGFeColorMatrix, RNSVGFeGaussianBlur, + RNSVGFeOffset, } from './fabric'; export { @@ -112,6 +114,7 @@ export type { ForeignObjectProps } from './elements/ForeignObject'; export type { FilterProps } from './elements/filters/Filter'; export type { FeColorMatrixProps } from './elements/filters/FeColorMatrix'; export type { FeGaussianBlurProps } from './elements/filters/FeGaussianBlur'; +export type { FeOffsetProps } from './elements/filters/FeOffset'; export type { FilterPrimitiveCommonProps } from './elements/filters/FilterPrimitive'; export * from './lib/extract/types'; @@ -153,6 +156,7 @@ export { Filter, FeColorMatrix, FeGaussianBlur, + FeOffset, RNSVGMarker, RNSVGMask, RNSVGPattern, @@ -178,6 +182,7 @@ export { RNSVGFilter, RNSVGFeColorMatrix, RNSVGFeGaussianBlur, + 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..403845ee9 --- /dev/null +++ b/src/fabric/FeOffsetNativeComponent.ts @@ -0,0 +1,21 @@ +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 FilterPrimitiveCommonProps { + x?: UnsafeMixed; + y?: UnsafeMixed; + width?: UnsafeMixed; + height?: UnsafeMixed; + result?: string; +} + +export interface NativeProps extends ViewProps, FilterPrimitiveCommonProps { + in1?: string; + dx?: UnsafeMixed; + dy?: UnsafeMixed; +} + +export default codegenNativeComponent('RNSVGFeOffset'); diff --git a/src/fabric/index.ts b/src/fabric/index.ts index 40e53e645..779597cc1 100644 --- a/src/fabric/index.ts +++ b/src/fabric/index.ts @@ -23,6 +23,7 @@ import RNSVGUse from './UseNativeComponent'; import RNSVGFilter from './FilterNativeComponent'; import RNSVGFeColorMatrix from './FeColorMatrixNativeComponent'; import RNSVGFeGaussianBlur from './FeGaussianBlurNativeComponent'; +import RNSVGFeOffset from './FeOffsetNativeComponent'; export { RNSVGCircle, @@ -50,4 +51,5 @@ export { RNSVGFilter, RNSVGFeColorMatrix, RNSVGFeGaussianBlur, + RNSVGFeOffset, }; diff --git a/src/filter-image/types.ts b/src/filter-image/types.ts index fb3a21a7e..7c6a65461 100644 --- a/src/filter-image/types.ts +++ b/src/filter-image/types.ts @@ -1,9 +1,14 @@ import { FilterPrimitiveCommonProps } from '../elements/filters/FilterPrimitive'; -import { FeColorMatrixProps, FeGaussianBlurProps } from '../index'; +import { + FeColorMatrixProps, + FeGaussianBlurProps, + FeOffsetProps, +} from '../index'; export type FilterElement = ( | ({ name: 'feColorMatrix' } & FeColorMatrixProps) | ({ name: 'feGaussianBlur' } & FeGaussianBlurProps) + | ({ name: 'feOffset' } & FeOffsetProps) ) & FilterPrimitiveCommonProps; diff --git a/src/lib/extract/extractFilter.ts b/src/lib/extract/extractFilter.ts index 7867bbdb4..1d51544d9 100644 --- a/src/lib/extract/extractFilter.ts +++ b/src/lib/extract/extractFilter.ts @@ -1,7 +1,9 @@ import { FeColorMatrixProps as FeColorMatrixComponentProps } from '../../elements/filters/FeColorMatrix'; -import { FeGaussianBlurProps as FeGaussianBlurComponentProps } from '../../elements/filters/FeGaussianBlur'; import { NativeProps as FeColorMatrixNativeProps } from '../../fabric/FeColorMatrixNativeComponent'; +import { FeGaussianBlurProps as FeGaussianBlurComponentProps } from '../../elements/filters/FeGaussianBlur'; import { NativeProps as FeGaussianBlurNativeProps } from '../../fabric/FeGaussianBlurNativeComponent'; +import { FeOffsetProps as FeOffsetComponentProps } from '../../elements/filters/FeOffset'; +import { NativeProps as FeOffsetNativeProps } from '../../fabric/FeOffsetNativeComponent'; import { NumberProp } from './types'; const spaceReg = /\s+/; @@ -51,7 +53,27 @@ 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; +}; + +export const extractFeOffset = ( + props: FeOffsetComponentProps +): FeOffsetNativeProps => { + const extracted: FeOffsetNativeProps = {}; + + if (props.in) { + extracted.in1 = props.in; + } + 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 42c3caeb6..901d97e95 100644 --- a/src/xml.tsx +++ b/src/xml.tsx @@ -28,6 +28,7 @@ import Marker from './elements/Marker'; import Filter from './elements/filters/Filter'; import FeColorMatrix from './elements/filters/FeColorMatrix'; import FeGaussianBlur from './elements/filters/FeGaussianBlur'; +import FeOffset from './elements/filters/FeOffset'; export const tags: { [tag: string]: ComponentType } = { svg: Svg, @@ -56,6 +57,7 @@ export const tags: { [tag: string]: ComponentType } = { filter: Filter, feColorMatrix: FeColorMatrix, feGaussianBlur: FeGaussianBlur, + feOffset: FeOffset, }; function missingTag() {