From 430175bf544f635b23c377841401fb4ff3150c81 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Wed, 28 Aug 2024 15:26:09 +0200 Subject: [PATCH 01/17] feat: create FeComposite fabric --- src/ReactNativeSVG.ts | 2 ++ src/elements/filters/FeComposite.tsx | 21 ++++++++++++-- src/fabric/FeCompositeNativeComponent.ts | 36 ++++++++++++++++++++++++ src/fabric/index.ts | 2 ++ src/lib/extract/extractFilter.ts | 20 +++++++++++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/fabric/FeCompositeNativeComponent.ts diff --git a/src/ReactNativeSVG.ts b/src/ReactNativeSVG.ts index 4aca02df4..67d8ba3d9 100644 --- a/src/ReactNativeSVG.ts +++ b/src/ReactNativeSVG.ts @@ -26,6 +26,7 @@ import { RNSVGDefs, RNSVGEllipse, RNSVGFeColorMatrix, + RNSVGFeComposite, RNSVGFeGaussianBlur, RNSVGFeMerge, RNSVGFeOffset, @@ -125,6 +126,7 @@ export { RNSVGDefs, RNSVGEllipse, RNSVGFeColorMatrix, + RNSVGFeComposite, RNSVGFeGaussianBlur, RNSVGFeMerge, RNSVGFeOffset, diff --git a/src/elements/filters/FeComposite.tsx b/src/elements/filters/FeComposite.tsx index 324a2c601..45f479f04 100644 --- a/src/elements/filters/FeComposite.tsx +++ b/src/elements/filters/FeComposite.tsx @@ -1,3 +1,9 @@ +import { NativeMethods, Platform } from 'react-native'; +import RNSVGFeComposite from '../../fabric/FeCompositeNativeComponent'; +import { + extractFeComposite, + extractFilter, +} from '../../lib/extract/extractFilter'; import { NumberProp } from '../../lib/extract/types'; import { warnUnimplementedFilter } from '../../lib/util'; import FilterPrimitive from './FilterPrimitive'; @@ -28,7 +34,18 @@ export default class FeComposite extends FilterPrimitive { }; render() { - warnUnimplementedFilter(); - return null; + if (Platform.OS === 'android') { + warnUnimplementedFilter(); + return null; + } + return ( + + this.refMethod(ref as (FeComposite & NativeMethods) | null) + } + {...extractFilter(this.props)} + {...extractFeComposite(this.props)} + /> + ); } } diff --git a/src/fabric/FeCompositeNativeComponent.ts b/src/fabric/FeCompositeNativeComponent.ts new file mode 100644 index 000000000..583a6cce3 --- /dev/null +++ b/src/fabric/FeCompositeNativeComponent.ts @@ -0,0 +1,36 @@ +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import type { ViewProps } from './utils'; + +import { NumberProp } from '../lib/extract/types'; +import type { UnsafeMixed } from './codegenUtils'; +import { Float, WithDefault } from 'react-native/Libraries/Types/CodegenTypes'; + +type FeCompositeOperator = + | 'over' + | 'in' + | 'out' + | 'atop' + | 'xor' + | 'arithmetic'; + +interface FilterPrimitiveCommonProps { + x?: UnsafeMixed; + y?: UnsafeMixed; + width?: UnsafeMixed; + height?: UnsafeMixed; + result?: string; +} + +export interface NativeProps extends ViewProps, FilterPrimitiveCommonProps { + in1?: string; + in2?: string; + operator1?: WithDefault; + k1?: Float; + k2?: Float; + k3?: Float; + k4?: Float; +} + +export default codegenNativeComponent('RNSVGFeComposite', { + excludedPlatforms: ['android'], +}); diff --git a/src/fabric/index.ts b/src/fabric/index.ts index 8cdbb4f77..e8c184fdf 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 RNSVGFeComposite from './FeCompositeNativeComponent'; import RNSVGFeGaussianBlur from './FeGaussianBlurNativeComponent'; import RNSVGFeMerge from './FeMergeNativeComponent'; import RNSVGFeOffset from './FeOffsetNativeComponent'; @@ -51,6 +52,7 @@ export { RNSVGUse, RNSVGFilter, RNSVGFeColorMatrix, + RNSVGFeComposite, RNSVGFeGaussianBlur, RNSVGFeMerge, RNSVGFeOffset, diff --git a/src/lib/extract/extractFilter.ts b/src/lib/extract/extractFilter.ts index 672194542..5125efa72 100644 --- a/src/lib/extract/extractFilter.ts +++ b/src/lib/extract/extractFilter.ts @@ -1,8 +1,10 @@ import React from 'react'; import { FeColorMatrixProps as FeColorMatrixComponentProps } from '../../elements/filters/FeColorMatrix'; +import { FeCompositeProps as FeCompositeComponentProps } from '../../elements/filters/FeComposite'; import { FeGaussianBlurProps as FeGaussianBlurComponentProps } from '../../elements/filters/FeGaussianBlur'; import { FeMergeProps as FeMergeComponentProps } from '../../elements/filters/FeMerge'; import { NativeProps as FeColorMatrixNativeProps } from '../../fabric/FeColorMatrixNativeComponent'; +import { NativeProps as FeCompositeNativeProps } from '../../fabric/FeCompositeNativeComponent'; import { NativeProps as FeGaussianBlurNativeProps } from '../../fabric/FeGaussianBlurNativeComponent'; import { NativeProps as FeMergeNativeProps } from '../../fabric/FeMergeNativeComponent'; import { NumberProp } from './types'; @@ -67,6 +69,24 @@ export const extractFeColorMatrix = ( return extracted; }; +export const extractFeComposite = ( + props: FeCompositeComponentProps +): FeCompositeNativeProps => { + const extracted: FeCompositeNativeProps = { + in1: props.in || '', + in2: props.in2 || '', + operator1: props.operator || 'over', + }; + + (['k1', 'k2', 'k3', 'k4'] as const).forEach((key) => { + if (props[key] !== undefined) { + extracted[key] = Number(props[key]) || 0; + } + }); + + return extracted; +}; + export const extractFeGaussianBlur = ( props: FeGaussianBlurComponentProps ): FeGaussianBlurNativeProps => { From 21ef4c06cdc2b61ca921fb80c90f6915c8f62443 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Wed, 28 Aug 2024 15:30:31 +0200 Subject: [PATCH 02/17] feat: implement ios composite filters --- apple/Filters/RNSVGCompositeOperator.h | 9 + apple/Filters/RNSVGFeComposite.h | 14 ++ apple/Filters/RNSVGFeComposite.mm | 203 ++++++++++++++++++ apple/Utils/RNSVGConvert.h | 2 + apple/Utils/RNSVGConvert.mm | 18 ++ apple/ViewManagers/RNSVGFeCompositeManager.h | 5 + apple/ViewManagers/RNSVGFeCompositeManager.mm | 22 ++ 7 files changed, 273 insertions(+) create mode 100644 apple/Filters/RNSVGCompositeOperator.h create mode 100644 apple/Filters/RNSVGFeComposite.h create mode 100644 apple/Filters/RNSVGFeComposite.mm create mode 100644 apple/ViewManagers/RNSVGFeCompositeManager.h create mode 100644 apple/ViewManagers/RNSVGFeCompositeManager.mm diff --git a/apple/Filters/RNSVGCompositeOperator.h b/apple/Filters/RNSVGCompositeOperator.h new file mode 100644 index 000000000..62f2dc40e --- /dev/null +++ b/apple/Filters/RNSVGCompositeOperator.h @@ -0,0 +1,9 @@ +typedef CF_ENUM(int32_t, RNSVGCompositeOperator) { + SVG_FECOMPOSITE_OPERATOR_UNKNOWN, + SVG_FECOMPOSITE_OPERATOR_OVER, + SVG_FECOMPOSITE_OPERATOR_IN, + SVG_FECOMPOSITE_OPERATOR_OUT, + SVG_FECOMPOSITE_OPERATOR_ATOP, + SVG_FECOMPOSITE_OPERATOR_XOR, + SVG_FECOMPOSITE_OPERATOR_ARITHMETIC +}; diff --git a/apple/Filters/RNSVGFeComposite.h b/apple/Filters/RNSVGFeComposite.h new file mode 100644 index 000000000..5b00681bd --- /dev/null +++ b/apple/Filters/RNSVGFeComposite.h @@ -0,0 +1,14 @@ +#import "RNSVGCompositeOperator.h" +#import "RNSVGFilterPrimitive.h" + +@interface RNSVGFeComposite : RNSVGFilterPrimitive + +@property (nonatomic, strong) NSString *in1; +@property (nonatomic, strong) NSString *in2; +@property (nonatomic, assign) RNSVGCompositeOperator operator1; +@property (nonatomic, strong) NSNumber *k1; +@property (nonatomic, strong) NSNumber *k2; +@property (nonatomic, strong) NSNumber *k3; +@property (nonatomic, strong) NSNumber *k4; + +@end diff --git a/apple/Filters/RNSVGFeComposite.mm b/apple/Filters/RNSVGFeComposite.mm new file mode 100644 index 000000000..3a302bd7a --- /dev/null +++ b/apple/Filters/RNSVGFeComposite.mm @@ -0,0 +1,203 @@ +#import "RNSVGFeComposite.h" + +#ifdef RCT_NEW_ARCH_ENABLED +#import +#import +#import +#import +#import "RNSVGArithmeticFilter.h" +#import "RNSVGCompositeXor.h" +#import "RNSVGConvert.h" +#import "RNSVGFabricConversions.h" +#endif // RCT_NEW_ARCH_ENABLED + +static CIColorKernel *thresholdKernel; + +@implementation RNSVGFeComposite + +#ifdef RCT_NEW_ARCH_ENABLED +using namespace facebook::react; + +// Needed because of this: https://github.com/facebook/react-native/pull/37274 ++ (void)load +{ + [super load]; +} + +- (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); + self.in2 = RCTNSStringFromStringNilIfEmpty(newProps.in2); + self.k1 = [NSNumber numberWithFloat:newProps.k1]; + self.k2 = [NSNumber numberWithFloat:newProps.k2]; + self.k3 = [NSNumber numberWithFloat:newProps.k3]; + self.k4 = [NSNumber numberWithFloat:newProps.k4]; + self.operator1 = [RNSVGConvert RNSVGRNSVGCompositeOperatorFromCppEquivalent:newProps.operator1]; + + setCommonFilterProps(newProps, self); + _props = std::static_pointer_cast(props); +} + +- (void)prepareForRecycle +{ + [super prepareForRecycle]; + _in1 = nil; + _in2 = nil; + _k1 = nil; + _k2 = nil; + _k3 = nil; + _k4 = nil; + _operator1 = RNSVGCompositeOperator::SVG_FECOMPOSITE_OPERATOR_UNKNOWN; +} +#endif // RCT_NEW_ARCH_ENABLED + +- (void)setIn1:(NSString *)in1 +{ + if ([in1 isEqualToString:_in1]) { + return; + } + + _in1 = in1; + [self invalidate]; +} + +- (void)setIn2:(NSString *)in2 +{ + if ([in2 isEqualToString:_in2]) { + return; + } + + _in2 = in2; + [self invalidate]; +} + +- (void)setK1:(NSNumber *)k1 +{ + if (k1 == _k1) { + return; + } + + _k1 = k1; + [self invalidate]; +} + +- (void)setK2:(NSNumber *)k2 +{ + if (k2 == _k2) { + return; + } + + _k2 = k2; + [self invalidate]; +} + +- (void)setK3:(NSNumber *)k3 +{ + if (k3 == _k3) { + return; + } + + _k3 = k3; + [self invalidate]; +} + +- (void)setK4:(NSNumber *)k4 +{ + if (k4 == _k4) { + return; + } + + _k4 = k4; + [self invalidate]; +} + +- (void)setOperator1:(RNSVGCompositeOperator)operator1 +{ + if (operator1 == _operator1) { + return; + } + + _operator1 = operator1; + [self invalidate]; +} + +- (CIImage *)applyFilter:(NSMutableDictionary *)results previousFilterResult:(CIImage *)previous +{ + CIImage *inResults1 = self.in1 ? [results objectForKey:self.in1] : nil; + CIImage *inResults2 = self.in2 ? [results objectForKey:self.in2] : nil; + CIImage *inputImage1 = inResults1 ? inResults1 : previous; + CIImage *inputImage2 = inResults2 ? inResults2 : previous; + + CIFilter *filter = nil; + + switch (self.operator1) { + case SVG_FECOMPOSITE_OPERATOR_OVER: + filter = [CIFilter filterWithName:@"CISourceOverCompositing"]; + break; + case SVG_FECOMPOSITE_OPERATOR_IN: + filter = [CIFilter filterWithName:@"CISourceInCompositing"]; + break; + case SVG_FECOMPOSITE_OPERATOR_OUT: + filter = [CIFilter filterWithName:@"CISourceOutCompositing"]; + break; + case SVG_FECOMPOSITE_OPERATOR_ATOP: + filter = [CIFilter filterWithName:@"CISourceAtopCompositing"]; + break; + case SVG_FECOMPOSITE_OPERATOR_XOR: + [RNSVGCompositeXor class]; + filter = [[RNSVGCompositeXor alloc] init]; + break; + case SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: + [RNSVGArithmeticFilter class]; + filter = [[RNSVGArithmeticFilter alloc] init]; + break; + default: + return nil; + } + + [filter setDefaults]; + + if (self.operator1 == SVG_FECOMPOSITE_OPERATOR_XOR) { + [filter setValue:inputImage1 forKey:@"inputImage1"]; + [filter setValue:inputImage2 forKey:@"inputImage2"]; + } else if (self.operator1 == SVG_FECOMPOSITE_OPERATOR_ARITHMETIC) { + [filter setValue:inputImage1 forKey:@"inputImage1"]; + [filter setValue:inputImage2 forKey:@"inputImage2"]; + [filter setValue:(self.k1 != nil ? self.k1 : 0) forKey:@"inputK1"]; + [filter setValue:(self.k2 != nil ? self.k2 : 0) forKey:@"inputK2"]; + [filter setValue:(self.k3 != nil ? self.k3 : 0) forKey:@"inputK3"]; + [filter setValue:(self.k4 != nil ? self.k4 : 0) forKey:@"inputK4"]; + } else { + [filter setValue:inputImage1 forKey:@"inputImage"]; + [filter setValue:inputImage2 forKey:@"inputBackgroundImage"]; + } + + return [filter valueForKey:@"outputImage"]; +} + +#ifdef RCT_NEW_ARCH_ENABLED +Class RNSVGFeCompositeCls(void) +{ + return RNSVGFeComposite.class; +} +#endif // RCT_NEW_ARCH_ENABLED + +@end diff --git a/apple/Utils/RNSVGConvert.h b/apple/Utils/RNSVGConvert.h index ee83027b4..6a2649ac5 100644 --- a/apple/Utils/RNSVGConvert.h +++ b/apple/Utils/RNSVGConvert.h @@ -1,6 +1,7 @@ #ifdef RCT_NEW_ARCH_ENABLED #import #import "RNSVGColorMatrixType.h" +#import "RNSVGCompositeOperator.h" #import "RNSVGEdgeMode.h" #import "RNSVGUnits.h" @@ -11,6 +12,7 @@ namespace react = facebook::react; + (RNSVGUnits)RNSVGUnitsFromFilterUnitsCppEquivalent:(react::RNSVGFilterFilterUnits)svgUnits; + (RNSVGUnits)RNSVGUnitsFromPrimitiveUnitsCppEquivalent:(react::RNSVGFilterPrimitiveUnits)svgUnits; + (RNSVGColorMatrixType)RNSVGColorMatrixTypeFromCppEquivalent:(react::RNSVGFeColorMatrixType)type; ++ (RNSVGCompositeOperator)RNSVGRNSVGCompositeOperatorFromCppEquivalent:(react::RNSVGFeCompositeOperator1)operator1; + (RNSVGEdgeMode)RNSVGEdgeModeFromCppEquivalent:(react::RNSVGFeGaussianBlurEdgeMode)edgeMode; @end diff --git a/apple/Utils/RNSVGConvert.mm b/apple/Utils/RNSVGConvert.mm index b557ff543..fee2f04a0 100644 --- a/apple/Utils/RNSVGConvert.mm +++ b/apple/Utils/RNSVGConvert.mm @@ -37,6 +37,24 @@ + (RNSVGColorMatrixType)RNSVGColorMatrixTypeFromCppEquivalent:(react::RNSVGFeCol } } ++ (RNSVGCompositeOperator)RNSVGRNSVGCompositeOperatorFromCppEquivalent:(react::RNSVGFeCompositeOperator1)operator1 +{ + switch (operator1) { + case react::RNSVGFeCompositeOperator1::Over: + return SVG_FECOMPOSITE_OPERATOR_OVER; + case react::RNSVGFeCompositeOperator1::In: + return SVG_FECOMPOSITE_OPERATOR_IN; + case react::RNSVGFeCompositeOperator1::Out: + return SVG_FECOMPOSITE_OPERATOR_OUT; + case react::RNSVGFeCompositeOperator1::Atop: + return SVG_FECOMPOSITE_OPERATOR_ATOP; + case react::RNSVGFeCompositeOperator1::Xor: + return SVG_FECOMPOSITE_OPERATOR_XOR; + case react::RNSVGFeCompositeOperator1::Arithmetic: + return SVG_FECOMPOSITE_OPERATOR_ARITHMETIC; + } +} + + (RNSVGEdgeMode)RNSVGEdgeModeFromCppEquivalent:(react::RNSVGFeGaussianBlurEdgeMode)edgeMode { switch (edgeMode) { diff --git a/apple/ViewManagers/RNSVGFeCompositeManager.h b/apple/ViewManagers/RNSVGFeCompositeManager.h new file mode 100644 index 000000000..761115a98 --- /dev/null +++ b/apple/ViewManagers/RNSVGFeCompositeManager.h @@ -0,0 +1,5 @@ +#import "RNSVGFilterPrimitiveManager.h" + +@interface RNSVGFeCompositeManager : RNSVGFilterPrimitiveManager + +@end diff --git a/apple/ViewManagers/RNSVGFeCompositeManager.mm b/apple/ViewManagers/RNSVGFeCompositeManager.mm new file mode 100644 index 000000000..52903ef7b --- /dev/null +++ b/apple/ViewManagers/RNSVGFeCompositeManager.mm @@ -0,0 +1,22 @@ +#import "RNSVGFeCompositeManager.h" +#import "RNSVGCompositeOperator.h" +#import "RNSVGFeComposite.h" + +@implementation RNSVGFeCompositeManager + +RCT_EXPORT_MODULE() + +- (RNSVGFeComposite *)node +{ + return [RNSVGFeComposite new]; +} + +RCT_EXPORT_VIEW_PROPERTY(in1, NSString) +RCT_EXPORT_VIEW_PROPERTY(in2, NSString) +RCT_EXPORT_VIEW_PROPERTY(type, RNSVGCompositeOperator) +RCT_EXPORT_VIEW_PROPERTY(k1, NSNumber *) +RCT_EXPORT_VIEW_PROPERTY(k2, NSNumber *) +RCT_EXPORT_VIEW_PROPERTY(k3, NSNumber *) +RCT_EXPORT_VIEW_PROPERTY(k4, NSNumber *) + +@end From da1a6ffca24c5ef7f256339c0b07f853b891fb35 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Wed, 28 Aug 2024 15:33:06 +0200 Subject: [PATCH 03/17] feat: setup custom CoreImage Kernels using Metal --- RNSVG.podspec | 6 ++++-- package.json | 3 ++- scripts/metal.js | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 scripts/metal.js diff --git a/RNSVG.podspec b/RNSVG.podspec index 878dfb426..8b3fde414 100644 --- a/RNSVG.podspec +++ b/RNSVG.podspec @@ -12,13 +12,15 @@ Pod::Spec.new do |s| s.homepage = package['homepage'] s.authors = 'Horcrux Chen' s.source = { :git => 'https://github.com/react-native-community/react-native-svg.git', :tag => "v#{s.version}" } - s.source_files = 'apple/**/*.{h,m,mm}' + s.source_files = 'apple/**/*.{h,m,mm,metal}' s.ios.exclude_files = '**/*.macos.{h,m,mm}' s.tvos.exclude_files = '**/*.macos.{h,m,mm}' s.visionos.exclude_files = '**/*.macos.{h,m,mm}' if s.respond_to?(:visionos) s.osx.exclude_files = '**/*.ios.{h,m,mm}' - s.requires_arc = true + s.requires_arc = true s.platforms = { :osx => "10.14", :ios => "12.4", :tvos => "12.4", :visionos => "1.0" } + + s.resource_bundles = {'RNSVGFilters' => ['apple/**/*.{metallib}']} if fabric_enabled install_modules_dependencies(s) diff --git a/package.json b/package.json index 4e6694a6f..98d8fa155 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,8 @@ "e2e": "jest e2e", "generateE2eReferences": "ts-node e2e/generateReferences.ts", "check-archs-consistency": "node ./scripts/codegen-check-consistency.js", - "sync-archs": "node ./scripts/codegen-sync-archs.js" + "sync-archs": "node ./scripts/codegen-sync-archs.js", + "metal-to-ci": "node ./scripts/metal.js" }, "peerDependencies": { "react": "*", diff --git a/scripts/metal.js b/scripts/metal.js new file mode 100644 index 000000000..1fff924fa --- /dev/null +++ b/scripts/metal.js @@ -0,0 +1,49 @@ +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +const ROOT_DIR = path.resolve(__dirname, '..'); +const FILTERS_DIR = path.resolve(ROOT_DIR, 'apple/Filters/MetalCI'); + +function exec(command) { + execSync(command); +} + +function clearGeneratedFiles() { + const files = fs.readdirSync(FILTERS_DIR); + console.log('Removing generated files...'); + files.forEach((file) => { + const filePath = path.join(FILTERS_DIR, file); + const fileExtension = path.extname(file); + if (fileExtension === '.air' || fileExtension === '.metallib') { + exec(`rm -rf ${filePath}`); + } + }); + console.log('Generated files removed.'); +} + +function generateMetallib() { + const files = fs.readdirSync(FILTERS_DIR); + files.forEach((file) => { + const filePath = path.join(FILTERS_DIR, file); + const filePathWithoutExt = path + .join(FILTERS_DIR, file) + .replace('.metal', ''); + const fileName = path.basename(filePath).replace('.metal', ''); + const fileExtension = path.extname(file); + if (fileExtension === '.metal') { + console.log('Compiling Metal file:', fileName + '.metal'); + exec( + `xcrun -sdk iphoneos metal -fcikernel -c ${filePathWithoutExt}.metal -o ${filePathWithoutExt}.air` + ); + console.log(' ├─', fileName + '.air'); + exec( + `xcrun -sdk iphoneos metallib -cikernel ${filePathWithoutExt}.air -o ${filePathWithoutExt}.metallib` + ); + console.log(' └─', fileName + '.metallib'); + } + }); +} + +clearGeneratedFiles(); +generateMetallib(); From 73a46e00ebd46ba30ddc6f9911e4e4719183d6a9 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Wed, 28 Aug 2024 15:34:08 +0200 Subject: [PATCH 04/17] feat: create composite Xor and Arithmetic kernels --- .../Filters/MetalCI/RNSVGArithmeticFilter.air | Bin 0 -> 3856 bytes apple/Filters/MetalCI/RNSVGArithmeticFilter.h | 10 ++ .../MetalCI/RNSVGArithmeticFilter.metal | 27 ++++ .../MetalCI/RNSVGArithmeticFilter.metallib | Bin 0 -> 3991 bytes .../Filters/MetalCI/RNSVGArithmeticFilter.mm | 123 ++++++++++++++++++ apple/Filters/MetalCI/RNSVGCompositeXor.air | Bin 0 -> 3392 bytes apple/Filters/MetalCI/RNSVGCompositeXor.h | 6 + apple/Filters/MetalCI/RNSVGCompositeXor.metal | 21 +++ .../MetalCI/RNSVGCompositeXor.metallib | Bin 0 -> 3504 bytes apple/Filters/MetalCI/RNSVGCompositeXor.mm | 93 +++++++++++++ 10 files changed, 280 insertions(+) create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.air create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.h create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.metal create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.metallib create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.mm create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.air create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.h create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.metal create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.metallib create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.mm diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.air b/apple/Filters/MetalCI/RNSVGArithmeticFilter.air new file mode 100644 index 0000000000000000000000000000000000000000..13fb99360993c99efdc95193f5d5be064d3ce139 GIT binary patch literal 3856 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 P(~=eccU;DE`EmI#@%S_+ literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.h b/apple/Filters/MetalCI/RNSVGArithmeticFilter.h new file mode 100644 index 000000000..1f8f88c6b --- /dev/null +++ b/apple/Filters/MetalCI/RNSVGArithmeticFilter.h @@ -0,0 +1,10 @@ +@interface RNSVGArithmeticFilter : CIFilter { + CIImage *inputImage1; + CIImage *inputImage2; + NSNumber *inputK1; + NSNumber *inputK2; + NSNumber *inputK3; + NSNumber *inputK4; +} + +@end diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.metal b/apple/Filters/MetalCI/RNSVGArithmeticFilter.metal new file mode 100644 index 000000000..91d8364b5 --- /dev/null +++ b/apple/Filters/MetalCI/RNSVGArithmeticFilter.metal @@ -0,0 +1,27 @@ +// +// RNSVGArithmeticFilter.metal +// RNSVG +// +// Created by Jakub Grzywacz on 28/08/2024. +// + +#include +using namespace metal; +#include + + +extern "C" float4 arithmeticComposite(coreimage::sample_t in1, coreimage::sample_t in2, float k1, float k2, float k3, float k4) +{ +// float4 res = k1 * in1 * in2 + k2 * in1 + k3 * in2 + k4; +// +// return res; + float4 arithmeticResult; + arithmeticResult.rgb = k1 * in1.rgb * in2.rgb + k2 * in1.rgb + k3 * in2.rgb + k4; + arithmeticResult.a = k1 * in1.a * in2.a + k2 * in1.a + k3 * in2.a + k4; + + // Clamp results between [0..1] + arithmeticResult.rgb = clamp(arithmeticResult.rgb, 0.0, 1.0); + arithmeticResult.a = clamp(arithmeticResult.a, 0.0, 1.0); + + return arithmeticResult; +} diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.metallib b/apple/Filters/MetalCI/RNSVGArithmeticFilter.metallib new file mode 100644 index 0000000000000000000000000000000000000000..bc3fc3c9f4adab751d1a1288752884ef45e071c9 GIT binary patch literal 3991 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 literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.mm b/apple/Filters/MetalCI/RNSVGArithmeticFilter.mm new file mode 100644 index 000000000..1b8f37bb1 --- /dev/null +++ b/apple/Filters/MetalCI/RNSVGArithmeticFilter.mm @@ -0,0 +1,123 @@ +#import "RNSVGArithmeticFilter.h" + +static CIColorKernel *arithmeticFilter = nil; + +@implementation RNSVGArithmeticFilter + +- (id)init +{ + if (arithmeticFilter == nil) { + NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]]; + NSURL *bundleUrl = [frameworkBundle.resourceURL URLByAppendingPathComponent:@"RNSVGFilters.bundle"]; + NSBundle *bundle = [NSBundle bundleWithURL:bundleUrl]; + NSURL *url = [bundle URLForResource:@"RNSVGArithmeticFilter" withExtension:@"metallib"]; + NSLog(@"%@", url); + if (url != nil) { + NSError *error = nil; + NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error]; + + if (error) { + NSLog(@"%@", error); + @throw [NSException exceptionWithName:@"KernelInitializationException" + reason:error.localizedDescription + userInfo:nil]; + } + + @try { + arithmeticFilter = [CIColorKernel kernelWithFunctionName:@"arithmeticComposite" + fromMetalLibraryData:data + error:&error]; + if (error) { + NSLog(@"%@", error); + @throw [NSException exceptionWithName:@"KernelInitializationException" + reason:error.localizedDescription + userInfo:nil]; + } + } @catch (NSException *exception) { + NSLog(@"%@", exception); + } + } + } + return [super init]; +} + +- (NSDictionary *)customAttributes +{ + // CIImage *inputImage1; + // CIImage *inputImage2; + // NSNumber *inputK1; + // NSNumber *inputK2; + // NSNumber *inputK3; + // NSNumber *inputK4; + return @{ + @"inputImage1" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"CIImage", + kCIAttributeDisplayName : @"in1", + kCIAttributeType : kCIAttributeTypeImage + }, + @"inputImage2" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"CIImage", + kCIAttributeDisplayName : @"in2", + kCIAttributeType : kCIAttributeTypeImage + }, + @"inputK1" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"NSNumber", + kCIAttributeDisplayName : @"k1", + kCIAttributeType : kCIAttributeTypeScalar + }, + @"inputK2" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"NSNumber", + kCIAttributeDisplayName : @"k2", + kCIAttributeType : kCIAttributeTypeScalar + }, + @"inputK3" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"NSNumber", + kCIAttributeDisplayName : @"k3", + kCIAttributeType : kCIAttributeTypeScalar + }, + @"inputK4" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"NSNumber", + kCIAttributeDisplayName : @"k4", + kCIAttributeType : kCIAttributeTypeScalar + }, + }; +} + +- (CIImage *)outputImage +{ + CISampler *in1 = [CISampler samplerWithImage:inputImage1]; + CISampler *in2 = [CISampler samplerWithImage:inputImage2]; + + return [arithmeticFilter applyWithExtent:inputImage1.extent + roiCallback:^CGRect(int index, CGRect rect) { + return rect; + } + arguments:@[ in1, in2, inputK1, inputK2, inputK3, inputK4 ]]; +} + ++ (void)initialize +{ + [CIFilter + registerFilterName:@"arithmeticComposite" + constructor:(id)self + classAttributes:@{ + kCIAttributeFilterDisplayName : @"RNSVG Arithmetic Composite", + kCIAttributeFilterCategories : + @[ kCICategoryColorAdjustment, kCICategoryStillImage, kCICategoryInterlaced, kCICategoryNonSquarePixels ] + }]; +} + ++ (CIFilter *)filterWithName:(NSString *)name +{ + CIFilter *filter; + filter = [[self alloc] init]; + return filter; +} + +@end diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.air b/apple/Filters/MetalCI/RNSVGCompositeXor.air new file mode 100644 index 0000000000000000000000000000000000000000..34806711ffe57c178b96dbf1ab884b438fe9320a GIT binary patch literal 3392 zcmcIne^gub75|0@c`1aK&@vlJ5?>nX(v}~O1Ziks0zsOdQcswj2Y0%WM+haBz~d$S zNIEqk(1%Cd(#k9zyK}F|~+Vv11*vRH>sKM_CU}Pq+I8scqfA z`=0mxb?<%md++^zzn^#C#lf{n2udncT{1%dfl_K7ym&7V2%yzSnGC-?VHEQ4pSJnmYc;8o&JhxYC13rJZtps!^iYk*F{2 zws0dFZP{v}M_zI;u69&%G?g}&chhf+^rfAOO}b5?++PgrK0uF*g5D=+gi@f_ua~T% zYs!&kb4H(BvjLj4A48g*FS>78dvrNh>DOcG_1PVpA6$+k$PIAnu;m!P}S`X3!Fk|sVCY)0(MP7`r1iQ z)qI3>GvMjcLgTRLJfc4bdo;>u|Nn}TjnKrSjSaL|L?=MJw?o|VIa#y67)H>)#92u1 z0I{_`$oa{3o4|wnU~_lS#1UIL!Z^vLUmh3FhsoAr(q|(*O9NMkY7Ud_@QjPE_(|W= zgNYDFIoTQ}VE|J%P5Ky;50fx}>1`Tpw{vZGaAmitvdQ@3TU6O(w`sP?JYc|0+ibGi z7m|6Gtl~jNPD1Ol$(m_w{CDlR_`00*(xi_jTR?cJ1u@==efh2hF)Mz{cT0=4A(Ah~ z$~hXxXL;(HrtlJ=4M!klcqX*==O20>{?X$vM*i`}V&+Gm{WEs-M#8WE^5Ny&M{gWF z6tVl>QT^`sS1+HRdhD^T7}xrhqvF*oj<3G?F!TM$9Q(zFmIwZLCU!FU@pJDl=&xtB zz4p!mv(J*iz+Q?F^5d-paIiGUbz?aQg%a={CqmV$;dZ7}gnCxpv+Z=e`K9%`K&ejn zVqj&^nqcFdBSumXc{*c93u)(1q(X~Q*=JH)kf~CC%4qY zu_U+n1ui6THnLSmwk{@s+BUyXEfJa(0^cWi`vRHQ=BaDb)V~I)Ifkei?N`q9<4XZ8 z0LYj|ITBEfvEuU~bHS*&pl_)?5i$0fjopN)H2zvT%U{7b&5*k zfO+fTpebt2_|_4d(AG}2_f=Lbgk(4Z>PMEKNu#@XiZv_X;7w(lnlWa@xihk^g|Bb?QCjnv)8kHwcF`))bXs#k;OGR z8$Ax5b@JIRw!OO6(dx82s%u*6>Og*lYHw`gAt+2F{obu>2dE_ZdU)6Ld2IBsRtv2IVbi}lo3I~u>o!=YIAxw_8bv9HLK za9|kia(LJVx^+2zv_a444cWQ(ZlQHcj5fDC##Y5I9nZA?$$jyEM6q19Gu2)Eom@s&-w8K4?eWb3~n{KA!b!g zusv8eLgH<35TGy})_AQ%Z0N8`w34@ACf7>t&+V`(U`AEz$W^`6wW{97V4&_B`T_Q!a*jnQc3`t8`?1)pIXPU!aj!+2x$|8|rmGiG zeBzF$-D&&w26xyuf9(rCzhj^KxpW64A$`GJlaq57c2A6sP0g0Cnxzj77Z{smExx*9n;0R>xzx*KsG4t3H4|g z$-0uobGh;o{ir-uD(+g8>B~k9``pK`hp&LPIK+C%Q_pLv; zXrJ%Cj}pO)sU^otjB*v|JI~NNT@*1fc{*kLxwwiq7cvJs^H!(qysOl*%lce*Mo|*; z)x@i4&4i^a@8j}P=7Wys5;c{gCSANa>*P}mu%6BVnZF&+wd}HOlmPMX^8H?^^tGzD zku)MoEi>HT*OIv+_VFr_)Vvg@W_mf-*HiNKo#+jmx-At4fXz=jbS7ne#Is;PVAG+=JyY jY^~hyn;-(9m7kZjgbG>CCU@?Z?7VE||BETh)* +using namespace metal; +#include + +// Porter-Duff XOR composition +extern "C" float4 compositeXor(coreimage::sample_t in1, coreimage::sample_t in2) +{ + float4 result; + + result.rgb = in1.rgb * (1.0 - in2.a) + in2.rgb * (1.0 - in1.a); + result.a = in1.a + in2.a - 2.0 * in1.a * in2.a; + + return result; +} diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.metallib b/apple/Filters/MetalCI/RNSVGCompositeXor.metallib new file mode 100644 index 0000000000000000000000000000000000000000..c92f817f83c2a92f4c3fa86c6ac552ee1d0d0aaa GIT binary patch literal 3504 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 Md4+l0;(Xlx4^iiIg8%>k literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.mm b/apple/Filters/MetalCI/RNSVGCompositeXor.mm new file mode 100644 index 000000000..948022577 --- /dev/null +++ b/apple/Filters/MetalCI/RNSVGCompositeXor.mm @@ -0,0 +1,93 @@ +#import "RNSVGCompositeXor.h" + +static CIColorKernel *compositeXor = nil; + +@implementation RNSVGCompositeXor + +- (id)init +{ + if (compositeXor == nil) { + NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]]; + NSURL *bundleUrl = [frameworkBundle.resourceURL URLByAppendingPathComponent:@"RNSVGFilters.bundle"]; + NSBundle *bundle = [NSBundle bundleWithURL:bundleUrl]; + NSURL *url = [bundle URLForResource:@"RNSVGCompositeXor" withExtension:@"metallib"]; + NSLog(@"%@", url); + if (url != nil) { + NSError *error = nil; + NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error]; + + if (error) { + NSLog(@"%@", error); + @throw [NSException exceptionWithName:@"KernelInitializationException" + reason:error.localizedDescription + userInfo:nil]; + } + + @try { + compositeXor = [CIColorKernel kernelWithFunctionName:@"compositeXor" fromMetalLibraryData:data error:&error]; + if (error) { + NSLog(@"%@", error); + @throw [NSException exceptionWithName:@"KernelInitializationException" + reason:error.localizedDescription + userInfo:nil]; + } + } @catch (NSException *exception) { + NSLog(@"%@", exception); + } + } + } + return [super init]; +} + +- (NSDictionary *)customAttributes +{ + // CIImage *inputImage1; + // CIImage *inputImage2; + return @{ + @"inputImage1" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"CIImage", + kCIAttributeDisplayName : @"in1", + kCIAttributeType : kCIAttributeTypeImage + }, + @"inputImage2" : @{ + kCIAttributeIdentity : @0, + kCIAttributeClass : @"CIImage", + kCIAttributeDisplayName : @"in2", + kCIAttributeType : kCIAttributeTypeImage + }, + }; +} + +- (CIImage *)outputImage +{ + CISampler *in1 = [CISampler samplerWithImage:inputImage1]; + CISampler *in2 = [CISampler samplerWithImage:inputImage2]; + + return [compositeXor applyWithExtent:inputImage1.extent + roiCallback:^CGRect(int index, CGRect rect) { + return rect; + } + arguments:@[ in1, in2 ]]; +} + ++ (void)initialize +{ + [CIFilter + registerFilterName:@"compositeXor" + constructor:(id)self + classAttributes:@{ + kCIAttributeFilterDisplayName : @"RNSVG Composite XOR", + kCIAttributeFilterCategories : + @[ kCICategoryColorAdjustment, kCICategoryStillImage, kCICategoryInterlaced, kCICategoryNonSquarePixels ] + }]; +} + ++ (CIFilter *)filterWithName:(NSString *)name +{ + CIFilter *filter; + filter = [[self alloc] init]; + return filter; +} + +@end From a622190db4d5aee67614b2f89ef03d823b2e7e1d Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 30 Aug 2024 10:31:10 +0200 Subject: [PATCH 05/17] feat: implement FeComposite on Android --- .../java/com/horcrux/svg/FeCompositeView.java | 132 ++++++++++++++++++ .../com/horcrux/svg/FilterProperties.java | 37 +++++ .../horcrux/svg/RenderableViewManager.java | 50 +++++++ .../main/java/com/horcrux/svg/SvgPackage.java | 9 ++ react-native.config.js | 1 + src/elements/filters/FeComposite.tsx | 7 +- src/fabric/FeCompositeNativeComponent.ts | 4 +- 7 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 android/src/main/java/com/horcrux/svg/FeCompositeView.java diff --git a/android/src/main/java/com/horcrux/svg/FeCompositeView.java b/android/src/main/java/com/horcrux/svg/FeCompositeView.java new file mode 100644 index 000000000..eee8514d1 --- /dev/null +++ b/android/src/main/java/com/horcrux/svg/FeCompositeView.java @@ -0,0 +1,132 @@ +package com.horcrux.svg; + +import android.annotation.SuppressLint; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import com.facebook.react.bridge.ReactContext; +import java.util.HashMap; + +@SuppressLint("ViewConstructor") +class FeCompositeView extends FilterPrimitiveView { + String mIn1; + String mIn2; + float mK1; + float mK2; + float mK3; + float mK4; + FilterProperties.FeCompositeOperator mOperator; + + public FeCompositeView(ReactContext reactContext) { + super(reactContext); + } + + public void setIn1(String in1) { + this.mIn1 = in1; + invalidate(); + } + + public void setIn2(String in2) { + this.mIn2 = in2; + invalidate(); + } + + public void setK1(Float value) { + this.mK1 = value; + invalidate(); + } + + public void setK2(Float value) { + this.mK2 = value; + invalidate(); + } + + public void setK3(Float value) { + this.mK3 = value; + invalidate(); + } + + public void setK4(Float value) { + this.mK4 = value; + invalidate(); + } + + public void setOperator(String operator) { + this.mOperator = FilterProperties.FeCompositeOperator.getEnum(operator); + invalidate(); + } + + @Override + public Bitmap applyFilter(HashMap resultsMap, Bitmap prevResult) { + Bitmap in1 = getSource(resultsMap, prevResult, this.mIn1); + Bitmap in2 = getSource(resultsMap, prevResult, this.mIn2); + Bitmap result = Bitmap.createBitmap(in1.getWidth(), in1.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(result); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + canvas.drawBitmap(in1, 0, 0, paint); + + switch (this.mOperator) { + case OVER -> { + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER)); + } + case IN -> { + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + } + case OUT -> { + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + } + case ATOP -> { + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)); + } + case XOR -> { + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); + } + case ARITHMETIC -> { + // result = k1*i1*i2 + k2*i1 + k3*i2 + k4 + int nPixels = result.getWidth() * result.getHeight(); + int[] pixels1 = new int[nPixels]; + int[] pixels2 = new int[nPixels]; + result.getPixels( + pixels1, 0, result.getWidth(), 0, 0, result.getWidth(), result.getHeight()); + + for (int i = 0; i < nPixels; i++) { + int color1 = pixels1[i]; + int color2 = pixels2[i]; + + int r1 = (color1 >> 16) & 0xFF; + int g1 = (color1 >> 8) & 0xFF; + int b1 = color1 & 0xFF; + int a1 = (color1 >>> 24); + int r2 = (color2 >> 16) & 0xFF; + int g2 = (color2 >> 8) & 0xFF; + int b2 = color2 & 0xFF; + int a2 = (color2 >>> 24); + + int rResult = (int) (mK1 * r1 * r2 + mK2 * r1 + mK3 * r2 + mK4); + int gResult = (int) (mK1 * g1 * g2 + mK2 * g1 + mK3 * g2 + mK4); + int bResult = (int) (mK1 * b1 * b2 + mK2 * b1 + mK3 * b2 + mK4); + int aResult = (int) (mK1 * a1 * a2 + mK2 * a1 + mK3 * a2 + mK4); + + rResult = Math.min(255, Math.max(0, rResult)); + gResult = Math.min(255, Math.max(0, gResult)); + bResult = Math.min(255, Math.max(0, bResult)); + aResult = Math.min(255, Math.max(0, aResult)); + + int pixel = (aResult << 24) | (rResult << 16) | (gResult << 8) | bResult; + pixels1[i] = pixel; + } + + result.setPixels( + pixels1, 0, result.getWidth(), 0, 0, result.getWidth(), result.getHeight()); + } + } + + if (this.mOperator != FilterProperties.FeCompositeOperator.ARITHMETIC) { + canvas.drawBitmap(in2, 0, 0, paint); + } + + return result; + } +} diff --git a/android/src/main/java/com/horcrux/svg/FilterProperties.java b/android/src/main/java/com/horcrux/svg/FilterProperties.java index 73d3b647b..f6391ec5b 100644 --- a/android/src/main/java/com/horcrux/svg/FilterProperties.java +++ b/android/src/main/java/com/horcrux/svg/FilterProperties.java @@ -107,4 +107,41 @@ public String toString() { return type; } } + + enum FeCompositeOperator { + OVER("over"), + IN("in"), + OUT("out"), + ATOP("atop"), + XOR("xor"), + ARITHMETIC("arithmetic"), + ; + + private final String type; + + FeCompositeOperator(String type) { + this.type = type; + } + + static FeCompositeOperator getEnum(String strVal) { + if (!typeToEnum.containsKey(strVal)) { + throw new IllegalArgumentException("Unknown String Value: " + strVal); + } + return typeToEnum.get(strVal); + } + + private static final Map typeToEnum = new HashMap<>(); + + static { + for (final FeCompositeOperator en : FeCompositeOperator.values()) { + typeToEnum.put(en.type, en); + } + } + + @Nonnull + @Override + public String toString() { + return type; + } + } } diff --git a/android/src/main/java/com/horcrux/svg/RenderableViewManager.java b/android/src/main/java/com/horcrux/svg/RenderableViewManager.java index 29600925f..e67c8a5b7 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.RNSVGFeCompositeManagerDelegate; +import com.facebook.react.viewmanagers.RNSVGFeCompositeManagerInterface; import com.facebook.react.viewmanagers.RNSVGFeGaussianBlurManagerDelegate; import com.facebook.react.viewmanagers.RNSVGFeGaussianBlurManagerInterface; import com.facebook.react.viewmanagers.RNSVGFeMergeManagerDelegate; @@ -590,6 +592,7 @@ protected enum SVGClass { RNSVGMask, RNSVGFilter, RNSVGFeColorMatrix, + RNSVGFeComposite, RNSVGFeGaussianBlur, RNSVGFeMerge, RNSVGFeOffset, @@ -641,6 +644,8 @@ protected VirtualView createViewInstance(@Nonnull ThemedReactContext reactContex return new FilterView(reactContext); case RNSVGFeColorMatrix: return new FeColorMatrixView(reactContext); + case RNSVGFeComposite: + return new FeCompositeView(reactContext); case RNSVGFeGaussianBlur: return new FeGaussianBlurView(reactContext); case RNSVGFeMerge: @@ -1605,6 +1610,51 @@ public void setValues(FeColorMatrixView node, @Nullable ReadableArray values) { } } + static class FeCompositeManager extends FilterPrimitiveManager + implements RNSVGFeCompositeManagerInterface { + FeCompositeManager() { + super(SVGClass.RNSVGFeComposite); + mDelegate = new RNSVGFeCompositeManagerDelegate(this); + } + + public static final String REACT_CLASS = "RNSVGFeComposite"; + + @ReactProp(name = "in1") + public void setIn1(FeCompositeView node, String in1) { + node.setIn1(in1); + } + + @ReactProp(name = "in2") + public void setIn2(FeCompositeView node, String in2) { + node.setIn2(in2); + } + + @ReactProp(name = "operator1") + public void setOperator1(FeCompositeView node, String operator) { + node.setOperator(operator); + } + + @ReactProp(name = "k1") + public void setK1(FeCompositeView node, float value) { + node.setK1(value); + } + + @ReactProp(name = "k2") + public void setK2(FeCompositeView node, float value) { + node.setK2(value); + } + + @ReactProp(name = "k3") + public void setK3(FeCompositeView node, float value) { + node.setK3(value); + } + + @ReactProp(name = "k4") + public void setK4(FeCompositeView node, float value) { + node.setK4(value); + } + } + static class FeGaussianBlurManager extends FilterPrimitiveManager implements RNSVGFeGaussianBlurManagerInterface { FeGaussianBlurManager() { diff --git a/android/src/main/java/com/horcrux/svg/SvgPackage.java b/android/src/main/java/com/horcrux/svg/SvgPackage.java index 21cfa39eb..63e21976c 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( + FeCompositeManager.REACT_CLASS, + ModuleSpec.viewManagerSpec( + new Provider() { + @Override + public NativeModule get() { + return new FeCompositeManager(); + } + })); specs.put( FeGaussianBlurManager.REACT_CLASS, ModuleSpec.viewManagerSpec( diff --git a/react-native.config.js b/react-native.config.js index 28470fcd2..a4fd8d682 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -18,6 +18,7 @@ module.exports = { 'RNSVGClipPathComponentDescriptor', 'RNSVGDefsComponentDescriptor', 'RNSVGFeColorMatrixComponentDescriptor', + 'RNSVGFeCompositeComponentDescriptor', 'RNSVGFeGaussianBlurComponentDescriptor', 'RNSVGFeMergeComponentDescriptor', 'RNSVGFeOffsetComponentDescriptor', diff --git a/src/elements/filters/FeComposite.tsx b/src/elements/filters/FeComposite.tsx index 45f479f04..269650f85 100644 --- a/src/elements/filters/FeComposite.tsx +++ b/src/elements/filters/FeComposite.tsx @@ -1,11 +1,10 @@ -import { NativeMethods, Platform } from 'react-native'; +import { NativeMethods } from 'react-native'; import RNSVGFeComposite from '../../fabric/FeCompositeNativeComponent'; import { extractFeComposite, extractFilter, } from '../../lib/extract/extractFilter'; import { NumberProp } from '../../lib/extract/types'; -import { warnUnimplementedFilter } from '../../lib/util'; import FilterPrimitive from './FilterPrimitive'; type FeCompositeOperator = @@ -34,10 +33,6 @@ export default class FeComposite extends FilterPrimitive { }; render() { - if (Platform.OS === 'android') { - warnUnimplementedFilter(); - return null; - } return ( diff --git a/src/fabric/FeCompositeNativeComponent.ts b/src/fabric/FeCompositeNativeComponent.ts index 583a6cce3..bdf2041ad 100644 --- a/src/fabric/FeCompositeNativeComponent.ts +++ b/src/fabric/FeCompositeNativeComponent.ts @@ -31,6 +31,4 @@ export interface NativeProps extends ViewProps, FilterPrimitiveCommonProps { k4?: Float; } -export default codegenNativeComponent('RNSVGFeComposite', { - excludedPlatforms: ['android'], -}); +export default codegenNativeComponent('RNSVGFeComposite'); From 16d648efbbb61fbf49efe9d126664a805798b653 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 30 Aug 2024 10:33:13 +0200 Subject: [PATCH 06/17] fix: filter bitmap sizes --- .../main/java/com/horcrux/svg/RenderableView.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/horcrux/svg/RenderableView.java b/android/src/main/java/com/horcrux/svg/RenderableView.java index 7ee5e68bc..32830cde0 100644 --- a/android/src/main/java/com/horcrux/svg/RenderableView.java +++ b/android/src/main/java/com/horcrux/svg/RenderableView.java @@ -352,22 +352,28 @@ void render(Canvas canvas, Paint paint, float opacity) { Paint bitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); canvas.saveLayer(null, bitmapPaint); - Rect canvasBounds = this.getSvgView().getCanvasBounds(); + Bitmap backgroundBitmap = this.getSvgView().getCurrentBitmap(); // draw element to self bitmap Bitmap elementBitmap = Bitmap.createBitmap( - canvasBounds.width(), canvasBounds.height(), Bitmap.Config.ARGB_8888); + backgroundBitmap.getWidth(), backgroundBitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas elementCanvas = new Canvas(elementBitmap); + Matrix canvasMatrix = canvas.getMatrix(); + elementCanvas.concat(canvasMatrix); draw(elementCanvas, paint, opacity); // apply filters - Bitmap backgroundBitmap = this.getSvgView().getCurrentBitmap(); elementBitmap = filter.applyFilter( - elementBitmap, backgroundBitmap, elementCanvas.getClipBounds(), canvasBounds); + elementBitmap, + backgroundBitmap, + elementCanvas.getClipBounds(), + this.getSvgView().getCanvasBounds()); + canvasMatrix.invert(canvasMatrix); + canvas.concat(canvasMatrix); // draw bitmap to canvas canvas.drawBitmap(elementBitmap, 0, 0, bitmapPaint); } else { From e27af892af91cfa80b9aa34880524b4421283273 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 30 Aug 2024 10:39:34 +0200 Subject: [PATCH 07/17] docs: add examples for FeComposite --- .../src/examples/Filters/FeComposite.tsx | 259 ++++++++++++++++++ .../src/examples/Filters/examples.tsx | 2 + .../src/examples/Filters/feComposite.png | Bin 0 -> 6839 bytes 3 files changed, 261 insertions(+) create mode 100644 apps/examples/src/examples/Filters/FeComposite.tsx create mode 100644 apps/examples/src/examples/Filters/feComposite.png diff --git a/apps/examples/src/examples/Filters/FeComposite.tsx b/apps/examples/src/examples/Filters/FeComposite.tsx new file mode 100644 index 000000000..f660fac5b --- /dev/null +++ b/apps/examples/src/examples/Filters/FeComposite.tsx @@ -0,0 +1,259 @@ +import React, {Component} from 'react'; +import {Image, Text as RNText} from 'react-native'; +import { + Defs, + FeComposite, + FeOffset, + Filter, + G, + Path, + Rect, + Svg, + Text, + Use, +} from 'react-native-svg'; + +class QuickTestExample extends Component { + static title = 'QuickTestExample'; + render() { + return ( + + + + + + + + ); + } +} + +class ReferenceExample extends Component { + static title = 'Composite'; + render() { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + opacity 1.0 + + + (without feFlood) + + + opacity 0.5 + + + (without feFlood) + + + + + + + over + + + + + + + in + + + + + + + out + + + + + + + atop + + + + + + + xor + + + + + + + arithmetic + + + + + + W3 Reference + + + ); + } +} + +const icon = ( + + + + + + + +); + +const samples = [ReferenceExample, QuickTestExample]; +export {icon, samples}; diff --git a/apps/examples/src/examples/Filters/examples.tsx b/apps/examples/src/examples/Filters/examples.tsx index e71d053ec..809169385 100644 --- a/apps/examples/src/examples/Filters/examples.tsx +++ b/apps/examples/src/examples/Filters/examples.tsx @@ -1,10 +1,12 @@ import * as FeColorMatrix from './FeColorMatrix'; +import * as FeComposite from './FeComposite'; import * as FeGaussianBlur from './FeGaussianBlur'; import * as FeMerge from './FeMerge'; import * as FeOffset from './FeOffset'; import * as ReanimatedFeColorMatrix from './ReanimatedFeColorMatrix'; export { FeColorMatrix, + FeComposite, FeGaussianBlur, FeMerge, FeOffset, diff --git a/apps/examples/src/examples/Filters/feComposite.png b/apps/examples/src/examples/Filters/feComposite.png new file mode 100644 index 0000000000000000000000000000000000000000..a2bf09449392b27a2ed1ef43a8ee7bcadd49eb4c GIT binary patch literal 6839 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�Zk39iNN2W!0vSxoXU0yenu@hIyf}m7lC6B4 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 literal 0 HcmV?d00001 From 708b545f1745f8fe82a0495052480e155f0e370d Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 30 Aug 2024 11:31:12 +0200 Subject: [PATCH 08/17] fix: filters size in example app --- .../src/examples/Filters/FeColorMatrix.tsx | 2 +- .../src/examples/Filters/FeComposite.tsx | 23 +++++++++++-------- .../src/examples/Filters/FeGaussianBlur.tsx | 2 +- .../src/examples/Filters/FeOffset.tsx | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/apps/examples/src/examples/Filters/FeColorMatrix.tsx b/apps/examples/src/examples/Filters/FeColorMatrix.tsx index 5e9052ddf..95aec8928 100644 --- a/apps/examples/src/examples/Filters/FeColorMatrix.tsx +++ b/apps/examples/src/examples/Filters/FeColorMatrix.tsx @@ -108,7 +108,7 @@ class LuminanceToAlphaExample extends Component { const icon = ( - + diff --git a/apps/examples/src/examples/Filters/FeComposite.tsx b/apps/examples/src/examples/Filters/FeComposite.tsx index f660fac5b..057743ec2 100644 --- a/apps/examples/src/examples/Filters/FeComposite.tsx +++ b/apps/examples/src/examples/Filters/FeComposite.tsx @@ -240,17 +240,20 @@ class ReferenceExample extends Component { const icon = ( - - + + - - + ); diff --git a/apps/examples/src/examples/Filters/FeGaussianBlur.tsx b/apps/examples/src/examples/Filters/FeGaussianBlur.tsx index 0659c0e3c..1be36ae8d 100644 --- a/apps/examples/src/examples/Filters/FeGaussianBlur.tsx +++ b/apps/examples/src/examples/Filters/FeGaussianBlur.tsx @@ -72,7 +72,7 @@ class StdDeviation025Example extends Component { const icon = ( - + diff --git a/apps/examples/src/examples/Filters/FeOffset.tsx b/apps/examples/src/examples/Filters/FeOffset.tsx index a1dcbc06d..ea209f8ed 100644 --- a/apps/examples/src/examples/Filters/FeOffset.tsx +++ b/apps/examples/src/examples/Filters/FeOffset.tsx @@ -28,7 +28,7 @@ class ReferenceExample extends Component { const icon = ( - + From 8c905dc9ed608f03d056c2e86f98daa564b16b5d Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 30 Aug 2024 12:16:34 +0200 Subject: [PATCH 09/17] feat: add CoreImage header to comply with macosx --- apple/Filters/MetalCI/RNSVGArithmeticFilter.h | 2 ++ apple/Filters/MetalCI/RNSVGCompositeXor.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.h b/apple/Filters/MetalCI/RNSVGArithmeticFilter.h index 1f8f88c6b..16e90b337 100644 --- a/apple/Filters/MetalCI/RNSVGArithmeticFilter.h +++ b/apple/Filters/MetalCI/RNSVGArithmeticFilter.h @@ -1,3 +1,5 @@ +#import + @interface RNSVGArithmeticFilter : CIFilter { CIImage *inputImage1; CIImage *inputImage2; diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.h b/apple/Filters/MetalCI/RNSVGCompositeXor.h index c2493b417..b6f70b71f 100644 --- a/apple/Filters/MetalCI/RNSVGCompositeXor.h +++ b/apple/Filters/MetalCI/RNSVGCompositeXor.h @@ -1,3 +1,5 @@ +#import + @interface RNSVGCompositeXor : CIFilter { CIImage *inputImage1; CIImage *inputImage2; From cde51c6fd55328b7f41770f63dc02a9ff0bbf5a7 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 30 Aug 2024 12:26:09 +0200 Subject: [PATCH 10/17] chore: add paper view managers --- .../RNSVGFeCompositeManagerDelegate.java | 65 +++++++++++++++++++ .../RNSVGFeCompositeManagerInterface.java | 29 +++++++++ 2 files changed, 94 insertions(+) create mode 100644 android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerDelegate.java create mode 100644 android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerInterface.java diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerDelegate.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerDelegate.java new file mode 100644 index 000000000..d1eb60be1 --- /dev/null +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerDelegate.java @@ -0,0 +1,65 @@ +/** +* 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 RNSVGFeCompositeManagerDelegate & RNSVGFeCompositeManagerInterface> extends BaseViewManagerDelegate { + public RNSVGFeCompositeManagerDelegate(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 "in2": + mViewManager.setIn2(view, value == null ? null : (String) value); + break; + case "operator1": + mViewManager.setOperator1(view, (String) value); + break; + case "k1": + mViewManager.setK1(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "k2": + mViewManager.setK2(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "k3": + mViewManager.setK3(view, value == null ? 0f : ((Double) value).floatValue()); + break; + case "k4": + mViewManager.setK4(view, value == null ? 0f : ((Double) value).floatValue()); + break; + default: + super.setProperty(view, propName, value); + } + } +} diff --git a/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerInterface.java b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerInterface.java new file mode 100644 index 000000000..95c925975 --- /dev/null +++ b/android/src/paper/java/com/facebook/react/viewmanagers/RNSVGFeCompositeManagerInterface.java @@ -0,0 +1,29 @@ +/** +* 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 RNSVGFeCompositeManagerInterface { + 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 setIn2(T view, @Nullable String value); + void setOperator1(T view, @Nullable String value); + void setK1(T view, float value); + void setK2(T view, float value); + void setK3(T view, float value); + void setK4(T view, float value); +} From 56c16800d0a90cbbaa041ebd477f170dadd60382 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 30 Aug 2024 13:19:09 +0200 Subject: [PATCH 11/17] fix: ios paper --- apple/Filters/RNSVGFeComposite.h | 2 ++ apple/Utils/RCTConvert+RNSVG.h | 1 + apple/Utils/RCTConvert+RNSVG.mm | 13 +++++++++++++ apple/ViewManagers/RNSVGFeCompositeManager.mm | 2 +- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apple/Filters/RNSVGFeComposite.h b/apple/Filters/RNSVGFeComposite.h index 5b00681bd..6b22a51c8 100644 --- a/apple/Filters/RNSVGFeComposite.h +++ b/apple/Filters/RNSVGFeComposite.h @@ -1,4 +1,6 @@ +#import "RNSVGArithmeticFilter.h" #import "RNSVGCompositeOperator.h" +#import "RNSVGCompositeXor.h" #import "RNSVGFilterPrimitive.h" @interface RNSVGFeComposite : RNSVGFilterPrimitive diff --git a/apple/Utils/RCTConvert+RNSVG.h b/apple/Utils/RCTConvert+RNSVG.h index d0714ac92..b5fa03375 100644 --- a/apple/Utils/RCTConvert+RNSVG.h +++ b/apple/Utils/RCTConvert+RNSVG.h @@ -12,6 +12,7 @@ #import "RCTConvert+RNSVG.h" #import "RNSVGCGFCRule.h" #import "RNSVGColorMatrixType.h" +#import "RNSVGCompositeOperator.h" #import "RNSVGEdgeMode.h" #import "RNSVGLength.h" #import "RNSVGMaskType.h" diff --git a/apple/Utils/RCTConvert+RNSVG.mm b/apple/Utils/RCTConvert+RNSVG.mm index 863cb7255..9205b19cf 100644 --- a/apple/Utils/RCTConvert+RNSVG.mm +++ b/apple/Utils/RCTConvert+RNSVG.mm @@ -72,6 +72,19 @@ @implementation RCTConvert (RNSVG) SVG_FECOLORMATRIX_TYPE_UNKNOWN, intValue) +RCT_ENUM_CONVERTER( + RNSVGCompositeOperator, + (@{ + @"over" : @(SVG_FECOMPOSITE_OPERATOR_OVER), + @"in" : @(SVG_FECOMPOSITE_OPERATOR_IN), + @"out" : @(SVG_FECOMPOSITE_OPERATOR_OUT), + @"atop" : @(SVG_FECOMPOSITE_OPERATOR_ATOP), + @"xor" : @(SVG_FECOMPOSITE_OPERATOR_XOR), + @"arithmetic" : @(SVG_FECOMPOSITE_OPERATOR_ARITHMETIC), + }), + SVG_FECOMPOSITE_OPERATOR_UNKNOWN, + intValue) + + (RNSVGBrush *)RNSVGBrush:(id)json { if ([json isKindOfClass:[NSNumber class]]) { diff --git a/apple/ViewManagers/RNSVGFeCompositeManager.mm b/apple/ViewManagers/RNSVGFeCompositeManager.mm index 52903ef7b..a2d4c96f2 100644 --- a/apple/ViewManagers/RNSVGFeCompositeManager.mm +++ b/apple/ViewManagers/RNSVGFeCompositeManager.mm @@ -13,7 +13,7 @@ - (RNSVGFeComposite *)node RCT_EXPORT_VIEW_PROPERTY(in1, NSString) RCT_EXPORT_VIEW_PROPERTY(in2, NSString) -RCT_EXPORT_VIEW_PROPERTY(type, RNSVGCompositeOperator) +RCT_EXPORT_VIEW_PROPERTY(operator1, RNSVGCompositeOperator) RCT_EXPORT_VIEW_PROPERTY(k1, NSNumber *) RCT_EXPORT_VIEW_PROPERTY(k2, NSNumber *) RCT_EXPORT_VIEW_PROPERTY(k3, NSNumber *) From e356ddb6dc49f8b4fe6b09a42194be91a5665878 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Wed, 23 Oct 2024 20:05:58 +0200 Subject: [PATCH 12/17] chore: generate metal --- .../RNSVGArithmeticFilter.appletvos.air | Bin 0 -> 3856 bytes .../RNSVGArithmeticFilter.appletvos.metallib | Bin 0 -> 3993 bytes ...air => RNSVGArithmeticFilter.iphoneos.air} | Bin 3856 -> 3856 bytes ...> RNSVGArithmeticFilter.iphoneos.metallib} | Bin 3991 -> 3993 bytes .../MetalCI/RNSVGArithmeticFilter.macosx.air | Bin 0 -> 3856 bytes .../RNSVGArithmeticFilter.macosx.metallib | Bin 0 -> 3993 bytes .../MetalCI/RNSVGArithmeticFilter.metal | 13 +------------ .../MetalCI/RNSVGArithmeticFilter.xros.air | Bin 0 -> 3856 bytes .../RNSVGArithmeticFilter.xros.metallib | Bin 0 -> 3993 bytes .../MetalCI/RNSVGCompositeXor.appletvos.air | Bin 0 -> 3392 bytes .../RNSVGCompositeXor.appletvos.metallib | Bin 0 -> 3509 bytes ...Xor.air => RNSVGCompositeXor.iphoneos.air} | Bin 3392 -> 3392 bytes ...ib => RNSVGCompositeXor.iphoneos.metallib} | Bin 3504 -> 3509 bytes .../MetalCI/RNSVGCompositeXor.macosx.air | Bin 0 -> 3408 bytes .../MetalCI/RNSVGCompositeXor.macosx.metallib | Bin 0 -> 3525 bytes apple/Filters/MetalCI/RNSVGCompositeXor.metal | 10 +--------- .../MetalCI/RNSVGCompositeXor.xros.air | Bin 0 -> 3392 bytes .../MetalCI/RNSVGCompositeXor.xros.metallib | Bin 0 -> 3509 bytes 18 files changed, 2 insertions(+), 21 deletions(-) create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.appletvos.air create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.appletvos.metallib rename apple/Filters/MetalCI/{RNSVGArithmeticFilter.air => RNSVGArithmeticFilter.iphoneos.air} (84%) rename apple/Filters/MetalCI/{RNSVGArithmeticFilter.metallib => RNSVGArithmeticFilter.iphoneos.metallib} (68%) create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.macosx.air create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.macosx.metallib create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.xros.air create mode 100644 apple/Filters/MetalCI/RNSVGArithmeticFilter.xros.metallib create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.appletvos.air create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.appletvos.metallib rename apple/Filters/MetalCI/{RNSVGCompositeXor.air => RNSVGCompositeXor.iphoneos.air} (86%) rename apple/Filters/MetalCI/{RNSVGCompositeXor.metallib => RNSVGCompositeXor.iphoneos.metallib} (81%) create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.macosx.air create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.macosx.metallib create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.xros.air create mode 100644 apple/Filters/MetalCI/RNSVGCompositeXor.xros.metallib diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.appletvos.air b/apple/Filters/MetalCI/RNSVGArithmeticFilter.appletvos.air new file mode 100644 index 0000000000000000000000000000000000000000..0f89836eefe22780dd17570ac02422c018647a4b GIT binary patch literal 3856 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 literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.air b/apple/Filters/MetalCI/RNSVGArithmeticFilter.iphoneos.air similarity index 84% rename from apple/Filters/MetalCI/RNSVGArithmeticFilter.air rename to apple/Filters/MetalCI/RNSVGArithmeticFilter.iphoneos.air index 13fb99360993c99efdc95193f5d5be064d3ce139..abe4386daab5c067acc03306837d18f09a41eb9a 100644 GIT binary patch delta 239 zcmbOrH$jf~-T`rL1|Sdt;x8L{Gg*usR2diqfIJS6Fhj_J39A-yDKM}A*^D581}=%9 zrHv&Fj0!*wRL$mI^#0JH?e z23ZTELE;=hadn`W5D>#?m^e^~A(n@M!4M?RJf$4uoW!Ecl8oHclFVf1{M>^4;>?oN L$+3K!nHU%V$&4%* diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.metallib b/apple/Filters/MetalCI/RNSVGArithmeticFilter.iphoneos.metallib similarity index 68% rename from apple/Filters/MetalCI/RNSVGArithmeticFilter.metallib rename to apple/Filters/MetalCI/RNSVGArithmeticFilter.iphoneos.metallib index bc3fc3c9f4adab751d1a1288752884ef45e071c9..47668d1a33526f6e33dab4a20dad1d85fbe526e4 100644 GIT binary patch delta 378 zcmbO(KT|%+G?=x%H z?2G@qsN($EY2DpL{%&p|5)(IyOgx}1kom{ru%L$BpPhyi16GDUyEyT;2cyeo7e)~l z;}t9nK-V)cfUR%fk_ZY7VPt6l3Mc?E1496#^D2`GdGX2=iPl$pKSAOfpz}% z+RD)6iGMv99X7i$im({ZU||4yhJgX>ng&jZAm0#1mIk1J0uVDW7%)1oGM>Pv0Q4wa z&E{U#FC2`PlbiU|1)YGxqChMR#2_F%c^99&DVzrs`40pPDi9SSAQeCiqCw&uKyh^- eTL_5NC-d=(%S(cI%u}`lDQsad*^NIK=vn{}2vi{e diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.macosx.air b/apple/Filters/MetalCI/RNSVGArithmeticFilter.macosx.air new file mode 100644 index 0000000000000000000000000000000000000000..15b5c064d8f8b91045faac9d1dc2413b6052cfbb GIT binary patch literal 3856 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 using namespace metal; #include -extern "C" float4 arithmeticComposite(coreimage::sample_t in1, coreimage::sample_t in2, float k1, float k2, float k3, float k4) +extern "C" float4 RNSVGArithmeticFilter(coreimage::sample_t in1, coreimage::sample_t in2, float k1, float k2, float k3, float k4) { -// float4 res = k1 * in1 * in2 + k2 * in1 + k3 * in2 + k4; -// -// return res; float4 arithmeticResult; arithmeticResult.rgb = k1 * in1.rgb * in2.rgb + k2 * in1.rgb + k3 * in2.rgb + k4; arithmeticResult.a = k1 * in1.a * in2.a + k2 * in1.a + k3 * in2.a + k4; - // Clamp results between [0..1] arithmeticResult.rgb = clamp(arithmeticResult.rgb, 0.0, 1.0); arithmeticResult.a = clamp(arithmeticResult.a, 0.0, 1.0); diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.xros.air b/apple/Filters/MetalCI/RNSVGArithmeticFilter.xros.air new file mode 100644 index 0000000000000000000000000000000000000000..48c39168e270eef682802e6077e907039c199eca GIT binary patch literal 3856 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 F@;`z_G?@SZ literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.xros.metallib b/apple/Filters/MetalCI/RNSVGArithmeticFilter.xros.metallib new file mode 100644 index 0000000000000000000000000000000000000000..461f55d20eb30b29f6a3214cc0dabf8e78f7a3cb GIT binary patch literal 3993 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 literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.appletvos.air b/apple/Filters/MetalCI/RNSVGCompositeXor.appletvos.air new file mode 100644 index 0000000000000000000000000000000000000000..c43b92f8103498773ce624ba410ab019870e0d09 GIT binary patch literal 3392 zcmcIne^3)w9)Dpm8zF3hGBrq&+Zgm><;Rjx2m;eUD8>&IVTOFe?zJ?51)Sk1O&+HrA&4}zAA>tHByBB zm4r}gk_JJA?t@GQwFfI=$=k(peaRtFk96ZINv1max%zo-VN z)AiLzvn6{#uGt7h=1-;jUklqS8+X&$jopElM2cz}8LE;$Fbyk3iesiUt@J%+6vfj6 zqfAn5A7Iof5ZVoO){6EzUZ03rH7r9$bOVJ^$|A8rIVVyt%&V3M)8d2bSynkStehK6 zo6#s2MJnVE3w|9LU`U@t@alx3fY50nJ0k)gCTZn#P=#JmO^v8#0;=(O49<*4Y{%TN(Mpfqr)1W;nQqO5rv-8S(pn81~fl~+_%|usNz)Mq*{w@-r z+K-WL23DGwXc8t}M)X%;k470E{9j(O6PjeSxrG*s=vCnF?cjHOPSzeUK?~~FISc6< zBDOY%xB%H@7r<=)kkC0G7*7$!5u!K{N_)GOYDF@?o%BRVuZhHsN%5C*(jUN2YnbYa zkoZXmy%Dkvv)8JD0&lO3>@J4#UNfVU##f6D|KmoTp# zk-Q1R;_jsQYGMjN1GCp_YAE0Qqc0!6_|4(1XWn@39RJJ>wfgTi>$ksnQvH|9`M#2} z-@ZM|`e&YUOP_3uCYyi1K^Lsl314qE z1-o_O^gz9ic=LEqFG9!RG#mzfgCw9Fn^!hvh{}7-#-3+Gk zgS1i&SKz}zWfQY1p%%)D6Xh{;c^^?8@9Kl=vrj_$ECR=oeva^V2^=kC#?z^#Fg4G} zT#W3(GPP`_4DvD6d5v;fqZ(z^P0X{UXF{cu=8_Xc*_lvT4^bLl&hXmFea&QXGaO5@ zI3RFgfwPld9qGNk3Sc_}f=wc{D+GQ(@C^iWt}ato=cs=SQ%ej{9~)FI4B|@xB@oEC zMmZK#jkDrU!se2gxnv+wo{Ad#&Bk7$v_F~;lYZY_`Y};D6qUa36u3Hp=R%%ld?`E% z!4nZOKYT=X70JG~QVU_~f=M<{Q%kT4TBn*FQIA%rr!>mhpn7&r3B>i4NZq8UH4d4# z9u1Yot=T^;#4dDpkzE6|HP^y2>;d)D32M@)&X1^m1&jvoTC=3)OAMt#S)82b$Wi?k_Ko;HKtL)4lZhb(nP;pdd6ISiYVz1 zmBj1L!0y9h{a~j>=;TO*d~hbG;f(QW3vKR|X0GP-7FrwZJ9zM;s)$_ISXQ8~{B>CK zYF+KS#B)=1)8f|f+RQl9qRbqt7=bV1BUL--#~i%d+2-nOXl8kv+v#^S@ocLjmuqvn zJPw|9@_DUnm#xv^bv8I`^&L%3pnpr+(B^V`SeNHsxu=+u+Z) z@@-E$8a(cNa72SA*Ts6AUPrFmyC)=I>NZmUEqc@KJWt>mGCZmR-%P|;cm0m5vpWWT=Knq!bY#!WEx z%A#l_?GtIJy2T*<`SA&+`78)jv(nH34+y@PV05Vl^RU>Uut#!gF2wEj@zKI_((bG? zBhu(!#T;Ws6Y?rU@|1L>Flyf~Qp8Qx`ap0*TG7#fIOY58H=lZ1eCKl%zVqu(1szYk zm^B&fOWvf@78RW?I()MD&8;W(>kKD{-g>8YO@V^Y>j;C9D6|j{ShP7iKXl}@_9Kc< z+3|uqbKl<3j)pDY`9rVn*ylcy<$xe$Ahc_GdTD0&RBU{9v3m6)eR!y_WZh}~JMWw* ze!I4NtL1*c*qq~!rqsEnYWumozm^y?JU)uMF7qYf|r^l##>fS9`8&5%i z_&eb8jo{nV6kZ1$N&4%!0l1e@V55@BX!j-M*_)vUjvCkd4);n4Ml z<=zJ=5xkgDak9cFR{`E94860JBBrL#rf)x&RP*k&oZ+6rHR(I=tF-L09_h_4Pi4NH zdJC3;Ce)x03~yUG~iq5PmK{;FC)KSoZ;v zMnxG_hKB|^a&D=8x>_VPC;Ze--;DM3lzc-E`V$V_63GGa{!gH_hUj0$0{lOKWAfFI zYanAE)xQ+F1rCZ~;#xXjASOcdg!G=vxgAF-Y h|3{bnHj@Bz6&23h! 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 delta 109 zcmX>gbwG;u-T`rL1|SdtVvUWwaxDA?ObiT+3=9n*Q3eL)%~mYm*co{y8}g_NiUI{d uSPO__fS6};CXYNP50C`{Jd-E#2=l4}SwhTH)PP1XBv0PP)5QvsV*mhxZ4UMT diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.metallib b/apple/Filters/MetalCI/RNSVGCompositeXor.iphoneos.metallib similarity index 81% rename from apple/Filters/MetalCI/RNSVGCompositeXor.metallib rename to apple/Filters/MetalCI/RNSVGCompositeXor.iphoneos.metallib index c92f817f83c2a92f4c3fa86c6ac552ee1d0d0aaa..0d0f40644cfff5106ba3d3771114cd7f32b94a0b 100644 GIT binary patch delta 301 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 literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.macosx.metallib b/apple/Filters/MetalCI/RNSVGCompositeXor.macosx.metallib new file mode 100644 index 0000000000000000000000000000000000000000..8819212d94811ecb5aa0ecfa9e05e16814bbbc3d GIT binary patch literal 3525 zcmZuz4Nx1$72e}OCmV5+Z5j)6r<^R4D6xSbz#;LH0hqTTh0m3NZN1Ox* z(q<%tb7ZO{^3Nn>>P|(QW}G&YA&%?1iJJilJA}wFW|G$9Fbu?m;0*RKjZ5exP5V}W z2XxG2&nQ&Ybk+}ET;Vy4xN0`ni2f$yQNN@#Zj{9Nd_U*G+}D2R8U$XvOBi$?YH@K~^Kt+?(Wx23Mz_Zp!rIjQMh~k(leir?X9Uo$^`q*&e&WLRFx3hHRZ#7~ z@{|y!+#J;f17Pn)n7vy&d$)EG5bl6lqW7WN-Q`2yyTM6!0R{i(W`cD7_3{=9Cew1%XZlf7811P;kvdyDlV}|0rmGn~NOjBqQPPxs($CcMNpZ74dWHe&g>a>V17uDq=+r6TT6Vqbr==l&m z&C8p4`LzXl!Ak2D!|bG*xuRwxc2zz9LczH}!I(M!G+B5qP}oBj#1>N9ZPc?3)Q$#7 zBWj0FbcIBhjcV6Y?Mq1j+u;+dA-9yG&?k2G`M2F%pl?pm{~Dy{d9r4tpPA{$Nen&w z@S|#G*w2pIC4Uc@^GD42eewQm)NtHv=p_q|N3&tk@4E{=B?|_kvJai2t4b7H0Z#)? zVvkbvgvGQ^_RDV~`9H1nOo+Z_luvW?JnVwgvJ*q9h)FfBW+wcqi75sO&DVsgURhxn zFz-AOD2Q3NtZc+4c6cdoUq$(?kQ_%q^>nEF3v4uael6@&>;QkDjzCf9^B=sXpyvnaFRk=9yk=3+r(2~Ic-0C4tP;~czd+C1{nP7+2EPTN^^@H`?Zwk(ti_Vhy z#{>DXs&nx5VY6M}r$y{=Q3!Q%2wj036I2$?+$&34Bj_xg#veR#Ltw+|4gt>iYR^3?x4p^L2&?Tc*~1+G>TGH5 zsBN$d)oy2(qh7E#IWk=>&SsB8!2Z-aVJT;$$JvZIyKt!5)9G?lH-lMyV~gFByDG*K zIJDu&j!%OthO^O;Rp)4K5t`i9bxyavrqOYys^0GQR5#f@4b_h3`*hfi<)~EGJ3O_k zHYOLi&NVqa_C~IK*>_H_<8}J1obB5=ZCp|B$h<9jWG^<&e!>m5*-zV_X{$LTbai&v zYrC?oLd(;RT8}#$LRIU@Y_@xx?T$=$`=M+*UL?B=HjQV+5zM=@@4Go=#aBZ}vI`Oc z8sBYA)JP8lk!hq!Io;M&;BvZcyheH+I8Gxi)pc978Yu}T+w`&nu8VwCWP8+>@()>{ z)CPhhAb376I>1iI%%T?rr!Ml14=Q84Hd${TljxPU@V4@6F`H*Jl6y%ONgo`NnU!Zv zOiW?aCtjBMbItrkqqSztKO{4?)gl-3Ve9f!!%2R8e3F{M>jWDn*s50?m;J%ShqRi! zy!Z27J+tG~&NI4=`ZELX{}tHXXO6j7#?% zbEoY|&*%-Dh>Xu1yfArnYW&LR2a{8CHkCe-o_h;8y(K?^mK z>Z)?}!G9TrYLq_~?Ve>WEMFDyDGxs`u00RrUbE3(S)ruKXK-PYe`Td_4fy<2r#4=3 zy&_Z#TyLseC!&VaM8WHUqT|toXP|g9aM_sPm>E0n=lrUOof+$AMwW|&eTb0X;^fm- zIh-5#dtZigN&=LM6}}!QI01#1ED8q-p$Lbf_|k3X5HbSYkZ9V5k2HL7t<)n=ZHkc# zBI_$dQgof^5tQ;FB_ZwRet2=6kCS#!8FMxn4V%C=APa_qYF@g@v~(#)VbYB#Qe~3E zOLASwi2iv#e>uAO19`pvjYQ>ua?&lA}Xgzs+0SoZ`9p9nXz*`P4j$swNxM7NU7iOU0 z_&{pJ?J using namespace metal; #include -// Porter-Duff XOR composition -extern "C" float4 compositeXor(coreimage::sample_t in1, coreimage::sample_t in2) +extern "C" float4 RNSVGCompositeXor(coreimage::sample_t in1, coreimage::sample_t in2) { float4 result; diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.xros.air b/apple/Filters/MetalCI/RNSVGCompositeXor.xros.air new file mode 100644 index 0000000000000000000000000000000000000000..cce619766b2a7b0ff221d6c98720f6849182b368 GIT binary patch literal 3392 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 literal 0 HcmV?d00001 diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.xros.metallib b/apple/Filters/MetalCI/RNSVGCompositeXor.xros.metallib new file mode 100644 index 0000000000000000000000000000000000000000..7ea8a3708196ffe2be7c9b9717291109306d079e GIT binary patch literal 3509 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 KSCGdgl>84b?06Ue literal 0 HcmV?d00001 From c08a72fb57070651c5c73082a75edc0e32766760 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 24 Oct 2024 10:20:30 +0200 Subject: [PATCH 13/17] feat: compile separate metallib for every device types --- RNSVG.podspec | 5 ++++- scripts/metal.js | 35 +++++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/RNSVG.podspec b/RNSVG.podspec index 8b3fde414..b3e0ca3a7 100644 --- a/RNSVG.podspec +++ b/RNSVG.podspec @@ -20,7 +20,10 @@ Pod::Spec.new do |s| s.requires_arc = true s.platforms = { :osx => "10.14", :ios => "12.4", :tvos => "12.4", :visionos => "1.0" } - s.resource_bundles = {'RNSVGFilters' => ['apple/**/*.{metallib}']} + s.osx.resource_bundles = {'RNSVGFilters' => ['apple/**/*.macosx.metallib']} + s.ios.resource_bundles = {'RNSVGFilters' => ['apple/**/*.iphoneos.metallib']} + s.tvos.resource_bundles = {'RNSVGFilters' => ['apple/**/*.appletvos.metallib']} + s.visionos.resource_bundles = {'RNSVGFilters' => ['apple/**/*.xros.metallib']} if fabric_enabled install_modules_dependencies(s) diff --git a/scripts/metal.js b/scripts/metal.js index 1fff924fa..41b661be3 100644 --- a/scripts/metal.js +++ b/scripts/metal.js @@ -22,25 +22,32 @@ function clearGeneratedFiles() { console.log('Generated files removed.'); } +function compileMetalFile(file, sdk) { + const filePath = path.join(FILTERS_DIR, file); + const fileName = path.basename(filePath).replace('.metal', ''); + const filePathWithoutExt = path.join(FILTERS_DIR, file).replace('.metal', ''); + console.log('* for ' + sdk); + exec( + `xcrun -sdk ${sdk} metal -fcikernel -c ${filePathWithoutExt}.metal -o ${filePathWithoutExt}.${sdk}.air` + ); + console.log(` ├─ ${fileName}.${sdk}.air`); + exec( + `xcrun -sdk ${sdk} metallib -cikernel ${filePathWithoutExt}.${sdk}.air -o ${filePathWithoutExt}.${sdk}.metallib` + ); + console.log(` └─ ${fileName}.${sdk}.metallib`); +} + function generateMetallib() { const files = fs.readdirSync(FILTERS_DIR); files.forEach((file) => { - const filePath = path.join(FILTERS_DIR, file); - const filePathWithoutExt = path - .join(FILTERS_DIR, file) - .replace('.metal', ''); - const fileName = path.basename(filePath).replace('.metal', ''); const fileExtension = path.extname(file); if (fileExtension === '.metal') { - console.log('Compiling Metal file:', fileName + '.metal'); - exec( - `xcrun -sdk iphoneos metal -fcikernel -c ${filePathWithoutExt}.metal -o ${filePathWithoutExt}.air` - ); - console.log(' ├─', fileName + '.air'); - exec( - `xcrun -sdk iphoneos metallib -cikernel ${filePathWithoutExt}.air -o ${filePathWithoutExt}.metallib` - ); - console.log(' └─', fileName + '.metallib'); + const fileName = path.basename(file).replace('.metal', ''); + console.log('Compiling:', fileName + '.metal'); + compileMetalFile(file, 'macosx'); + compileMetalFile(file, 'iphoneos'); + compileMetalFile(file, 'appletvos'); + compileMetalFile(file, 'xros'); } }); } From 349bf55da1fcba7f46bb9dda7f1f8c8b4dad569a Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 24 Oct 2024 10:34:00 +0200 Subject: [PATCH 14/17] feat: extract custom metal filter --- apple/Filters/MetalCI/RNSVGArithmeticFilter.h | 5 +- .../Filters/MetalCI/RNSVGArithmeticFilter.mm | 59 +------------------ apple/Filters/MetalCI/RNSVGCompositeXor.h | 5 +- apple/Filters/MetalCI/RNSVGCompositeXor.mm | 56 +----------------- apple/Filters/MetalCI/RNSVGCustomFilter.h | 9 +++ apple/Filters/MetalCI/RNSVGCustomFilter.mm | 35 +++++++++++ apple/Filters/RNSVGFeComposite.mm | 6 +- 7 files changed, 53 insertions(+), 122 deletions(-) create mode 100644 apple/Filters/MetalCI/RNSVGCustomFilter.h create mode 100644 apple/Filters/MetalCI/RNSVGCustomFilter.mm diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.h b/apple/Filters/MetalCI/RNSVGArithmeticFilter.h index 16e90b337..7c78724cc 100644 --- a/apple/Filters/MetalCI/RNSVGArithmeticFilter.h +++ b/apple/Filters/MetalCI/RNSVGArithmeticFilter.h @@ -1,7 +1,6 @@ -#import +#import "RNSVGCustomFilter.h" -@interface RNSVGArithmeticFilter : CIFilter { - CIImage *inputImage1; +@interface RNSVGArithmeticFilter : RNSVGCustomFilter { CIImage *inputImage2; NSNumber *inputK1; NSNumber *inputK2; diff --git a/apple/Filters/MetalCI/RNSVGArithmeticFilter.mm b/apple/Filters/MetalCI/RNSVGArithmeticFilter.mm index 1b8f37bb1..bbc4c15da 100644 --- a/apple/Filters/MetalCI/RNSVGArithmeticFilter.mm +++ b/apple/Filters/MetalCI/RNSVGArithmeticFilter.mm @@ -7,48 +7,13 @@ @implementation RNSVGArithmeticFilter - (id)init { if (arithmeticFilter == nil) { - NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]]; - NSURL *bundleUrl = [frameworkBundle.resourceURL URLByAppendingPathComponent:@"RNSVGFilters.bundle"]; - NSBundle *bundle = [NSBundle bundleWithURL:bundleUrl]; - NSURL *url = [bundle URLForResource:@"RNSVGArithmeticFilter" withExtension:@"metallib"]; - NSLog(@"%@", url); - if (url != nil) { - NSError *error = nil; - NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error]; - - if (error) { - NSLog(@"%@", error); - @throw [NSException exceptionWithName:@"KernelInitializationException" - reason:error.localizedDescription - userInfo:nil]; - } - - @try { - arithmeticFilter = [CIColorKernel kernelWithFunctionName:@"arithmeticComposite" - fromMetalLibraryData:data - error:&error]; - if (error) { - NSLog(@"%@", error); - @throw [NSException exceptionWithName:@"KernelInitializationException" - reason:error.localizedDescription - userInfo:nil]; - } - } @catch (NSException *exception) { - NSLog(@"%@", exception); - } - } + arithmeticFilter = [super getWithName:@"RNSVGArithmeticFilter"]; } return [super init]; } - (NSDictionary *)customAttributes { - // CIImage *inputImage1; - // CIImage *inputImage2; - // NSNumber *inputK1; - // NSNumber *inputK2; - // NSNumber *inputK3; - // NSNumber *inputK4; return @{ @"inputImage1" : @{ kCIAttributeIdentity : @0, @@ -95,29 +60,7 @@ - (CIImage *)outputImage CISampler *in2 = [CISampler samplerWithImage:inputImage2]; return [arithmeticFilter applyWithExtent:inputImage1.extent - roiCallback:^CGRect(int index, CGRect rect) { - return rect; - } arguments:@[ in1, in2, inputK1, inputK2, inputK3, inputK4 ]]; } -+ (void)initialize -{ - [CIFilter - registerFilterName:@"arithmeticComposite" - constructor:(id)self - classAttributes:@{ - kCIAttributeFilterDisplayName : @"RNSVG Arithmetic Composite", - kCIAttributeFilterCategories : - @[ kCICategoryColorAdjustment, kCICategoryStillImage, kCICategoryInterlaced, kCICategoryNonSquarePixels ] - }]; -} - -+ (CIFilter *)filterWithName:(NSString *)name -{ - CIFilter *filter; - filter = [[self alloc] init]; - return filter; -} - @end diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.h b/apple/Filters/MetalCI/RNSVGCompositeXor.h index b6f70b71f..33a2fc09c 100644 --- a/apple/Filters/MetalCI/RNSVGCompositeXor.h +++ b/apple/Filters/MetalCI/RNSVGCompositeXor.h @@ -1,7 +1,6 @@ -#import +#import "RNSVGCustomFilter.h" -@interface RNSVGCompositeXor : CIFilter { - CIImage *inputImage1; +@interface RNSVGCompositeXor : RNSVGCustomFilter { CIImage *inputImage2; } diff --git a/apple/Filters/MetalCI/RNSVGCompositeXor.mm b/apple/Filters/MetalCI/RNSVGCompositeXor.mm index 948022577..486d92afb 100644 --- a/apple/Filters/MetalCI/RNSVGCompositeXor.mm +++ b/apple/Filters/MetalCI/RNSVGCompositeXor.mm @@ -7,42 +7,13 @@ @implementation RNSVGCompositeXor - (id)init { if (compositeXor == nil) { - NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]]; - NSURL *bundleUrl = [frameworkBundle.resourceURL URLByAppendingPathComponent:@"RNSVGFilters.bundle"]; - NSBundle *bundle = [NSBundle bundleWithURL:bundleUrl]; - NSURL *url = [bundle URLForResource:@"RNSVGCompositeXor" withExtension:@"metallib"]; - NSLog(@"%@", url); - if (url != nil) { - NSError *error = nil; - NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error]; - - if (error) { - NSLog(@"%@", error); - @throw [NSException exceptionWithName:@"KernelInitializationException" - reason:error.localizedDescription - userInfo:nil]; - } - - @try { - compositeXor = [CIColorKernel kernelWithFunctionName:@"compositeXor" fromMetalLibraryData:data error:&error]; - if (error) { - NSLog(@"%@", error); - @throw [NSException exceptionWithName:@"KernelInitializationException" - reason:error.localizedDescription - userInfo:nil]; - } - } @catch (NSException *exception) { - NSLog(@"%@", exception); - } - } + compositeXor = [super getWithName:@"RNSVGCompositeXor"]; } return [super init]; } - (NSDictionary *)customAttributes { - // CIImage *inputImage1; - // CIImage *inputImage2; return @{ @"inputImage1" : @{ kCIAttributeIdentity : @0, @@ -64,30 +35,7 @@ - (CIImage *)outputImage CISampler *in1 = [CISampler samplerWithImage:inputImage1]; CISampler *in2 = [CISampler samplerWithImage:inputImage2]; - return [compositeXor applyWithExtent:inputImage1.extent - roiCallback:^CGRect(int index, CGRect rect) { - return rect; - } - arguments:@[ in1, in2 ]]; -} - -+ (void)initialize -{ - [CIFilter - registerFilterName:@"compositeXor" - constructor:(id)self - classAttributes:@{ - kCIAttributeFilterDisplayName : @"RNSVG Composite XOR", - kCIAttributeFilterCategories : - @[ kCICategoryColorAdjustment, kCICategoryStillImage, kCICategoryInterlaced, kCICategoryNonSquarePixels ] - }]; -} - -+ (CIFilter *)filterWithName:(NSString *)name -{ - CIFilter *filter; - filter = [[self alloc] init]; - return filter; + return [compositeXor applyWithExtent:inputImage1.extent arguments:@[ in1, in2 ]]; } @end diff --git a/apple/Filters/MetalCI/RNSVGCustomFilter.h b/apple/Filters/MetalCI/RNSVGCustomFilter.h new file mode 100644 index 000000000..baf27ad25 --- /dev/null +++ b/apple/Filters/MetalCI/RNSVGCustomFilter.h @@ -0,0 +1,9 @@ +#import + +@interface RNSVGCustomFilter : CIFilter { + CIImage *inputImage1; +} + +- (CIColorKernel *)getWithName:(NSString *)name; + +@end diff --git a/apple/Filters/MetalCI/RNSVGCustomFilter.mm b/apple/Filters/MetalCI/RNSVGCustomFilter.mm new file mode 100644 index 000000000..2f43bcaf0 --- /dev/null +++ b/apple/Filters/MetalCI/RNSVGCustomFilter.mm @@ -0,0 +1,35 @@ +#import "RNSVGCustomFilter.h" + +#if TARGET_OS_OSX +#define extension @"macosx.metallib" +#elif TARGET_OS_IOS +#define extension @"iphoneos.metallib" +#elif TARGET_OS_TV +#define extension @"tvos.metallib" +#elif TARGET_OS_VISION +#define extension @"xros.metallib" +#endif + +@implementation RNSVGCustomFilter + +- (CIColorKernel *)getWithName:(NSString *)name +{ + NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]]; + NSURL *bundleUrl = [frameworkBundle.resourceURL URLByAppendingPathComponent:@"RNSVGFilters.bundle"]; + NSBundle *bundle = [NSBundle bundleWithURL:bundleUrl]; + NSURL *url = [bundle URLForResource:name withExtension:extension]; + + if (url != nil) { + NSError *error = nil; + NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error]; + + @try { + return [CIColorKernel kernelWithFunctionName:name fromMetalLibraryData:data error:&error]; + } @catch (NSException *exception) { + NSLog(@"RNSVG CustomFilter exception: %@", exception); + } + } + return nil; +} + +@end diff --git a/apple/Filters/RNSVGFeComposite.mm b/apple/Filters/RNSVGFeComposite.mm index 3a302bd7a..4aa9dc1f1 100644 --- a/apple/Filters/RNSVGFeComposite.mm +++ b/apple/Filters/RNSVGFeComposite.mm @@ -1,12 +1,12 @@ #import "RNSVGFeComposite.h" +#import "RNSVGArithmeticFilter.h" +#import "RNSVGCompositeXor.h" #ifdef RCT_NEW_ARCH_ENABLED #import #import #import #import -#import "RNSVGArithmeticFilter.h" -#import "RNSVGCompositeXor.h" #import "RNSVGConvert.h" #import "RNSVGFabricConversions.h" #endif // RCT_NEW_ARCH_ENABLED @@ -162,11 +162,9 @@ - (CIImage *)applyFilter:(NSMutableDictionary *)results p filter = [CIFilter filterWithName:@"CISourceAtopCompositing"]; break; case SVG_FECOMPOSITE_OPERATOR_XOR: - [RNSVGCompositeXor class]; filter = [[RNSVGCompositeXor alloc] init]; break; case SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: - [RNSVGArithmeticFilter class]; filter = [[RNSVGArithmeticFilter alloc] init]; break; default: From fc0387baa303a381168a6de8497c520585a88098 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 24 Oct 2024 10:34:21 +0200 Subject: [PATCH 15/17] feat: update reference image --- .../src/examples/Filters/feComposite.png | Bin 6839 -> 9950 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/examples/src/examples/Filters/feComposite.png b/apps/examples/src/examples/Filters/feComposite.png index a2bf09449392b27a2ed1ef43a8ee7bcadd49eb4c..d1605daf57dd3eb5a36cbbc8a144c46f4fff2f2c 100644 GIT binary patch literal 9950 zcmZ{qbyOSQ+V82+6t_~`tq`ENLn#C)4O-kO4#8bp+$r9o#S0XN;4UdpiUd#50704t ziWj@-@7#0Nx$AxJKQqa!S$p<=_TKY+pU-z;UjqOD#Ja{B_AiYW$iPe4#>K|N(#zEYN8Z}i%7#ftPnk*2!N%9d zBaQnW1_y@;M^#b&wO=ke58P1vGP^7fYVy43fno%6)e4S*hR_n)#|d;9pBVa!QWM8@zvYM`@2G))q9?urlrP!cX0L2M5)t7M^%Emz5_ZEoBR6BNldFdbkA2Ip&C|J4<(c+IZ>T=8(#Yueb15 z{3KY3(GZP)xoC^)YDiX{rgs1Nv&v|8ljGFUu}_+>e#g8X7ZvhTo2om7QsCf%e!q<% z?kEuy6lWr$HgUAbq3$eqdS$+(h@+HyqZyIhRst6kKmY0AwP%^L+tNcm)vSa)JHjX4C7`xn8PK zX_aY^xj5f^)c(oRk@Q9haEwiLM?59dhC1oXyc2^Q9yLfyi^5BKOz;Zi?2!H2j$O6? zA;%&V-R`2n&;UfZv_K(JNsX(RlQmwuAmh;D;Ngg|wh{$Fu5~MdbzLFE7YQfci6bTe zQFJ&2Ay1NSLk$y%o1Arg9A&AiD^Eg~th{ zS`-f1`4e`hhS%LDe9h02kZX#aG}-<5VduVdS*z(^BKV*eBG@#`WZnZ@F?_qk->hRKG6@OH!p58)HqrnjP(VOu?ffe@C)7F~z4eM0Vl}y8@5+!L z$@pL#u^I`PGm`M7d&sECCYm$)`h~5bt>K(U+ZS*9lljsMKa+Vdys5HM7`!VZXjhT# zSsB`naCY3SX6COd^BRrs_*EI8&TC&0-=8WVOKN>^HtPogFcGc8(i2HA17QE>@~Y}7OvpS-?2ZaWRpE$kqxL8cnX ztWxY`<-49uA`lt+)t>u7vgWn($itZ0w-N*j_lNbly^-SEZ+Z_0*5AV2@fJKypS-J` zccOzGJLy~9E3qExcRN_n86afFv*T<5PW8)8 zC#OEmD=RhQdD`(spDW`=Azo4Dd{4Z>b&zy&%|s^5xbxmQT{g`H(i6tjdhqxkHR(-G zlTKHX!si6S7z#C&<=!wqO>m*i&rbq%%udpes~^hb8Az>&+`;VY-sn8%Ct42P-XMnA zl|>i0>yOK}>5z+G5em!}iLb~d0{F~}Xqlyw!nvF9EF(;`Hg&uq*XN4u<~7HL-E%kk zUkV&=S9M;Lo{>BLd_^`cq&d7VPbMk*G0estxp_zlibLYUi`7$Ek;9*i>632=V&0ed zZz@8#m#p;d>j~kPnd`iMaG)@$cVeKfZU)N#mh1S_Vlg1WMdGkgsq&2U!^0WT%^C4y58B1r9Z+6+`^$HX%J)sp9zS#gglJ=#8LD9f5(Hz2YQ&qUI zDw!-hNXmeBes+OC8<>92>XQ$z*4Gc$9>kY#H^hz!T^O}&H}qdf3??O zE`yxwrcatV{RKtVr$PxF8CWwCz^c0oLdyAKlrQsa{OB>_Nls&p)Ng9`r|p8kse=tJ z$xKm}t&7f+S#uB2AwA}NS(!HIv&*^KOq=R?C%gibL;=;K?5mxLyu7yZ+8Tk~yi8c1 zoyMEjwCg9M5~rpWywe|&OW2dmz`q%SA84shc4`YLiFx!s;Y0p*PtBA_iCJ-UT5|r@wKleVdTp(HzCxIuR9Jl z2cm)jM%0~&3Hf@suB^r78GVTVT<+TGU8v3brNq7yzv^?08T}aykvgvu^h~Jd=Y`$W z0K?4@f}g*eWDS{Tm`?N0C*_D6@*4%T$P{=SXX!ydR$k6m^l-(uA(xt21WZHGF{k_H z86WoR&q2$t@7hcZ$8U_!kgSY|mTd5y4pxL6tW)detXK)xmtwRU%MBVtv{SI z!f}O*cyEH^GR%?X_HLg&-QF-%I-bmirS4J?o=Xw^n?>V@WZ-4+9+4O6&L!Eq4NT) zg?;@sky`2M?w`=mzL@EZNvmtQUt9Pz*Q4TLBO&;X#bBEbfYIAqiCi|liP)1Iz-Z@= zw;r%y8*l)HBB*=)s^O@-Lg;S{gpBLM{m zOi4^ZbPkN$N~E$w8{+-V_2Wi|-;aX2%mVY3ff+U**&flCFK0IZ2U1P~z}Vzh#I@lY z)k{=vn8^$k246I$vN^c0rr0d{bPU;6TwZtMyFR4}SmdlHBn*af%z2 zAc6z`HF0$c5co;Y0tdAekEPUcwy%4y#wDL*61+L_l@`T9YBN*=sToX~Pt5WTvQu@C z@Z@Q*N2uk`p7_Z0W2TU6Zs7+ulGqX6jNaVvzhJg8yz;Q=i4%D!(m0;&_fWoW6{D3U zTQHH2inNR=Ad0>xYk_&adL|E);N_0HYn%;pPoT1&x6X|TZ&GeYijQrPb!6KaQbw(d z>lbeJHUZTpj)e9B6^q8 zq%V9yq16N%!4tBYek-|kU(1{m-)e6(mznP4y%FpRQIGtNI%?&1r-Ru?chn#f3Qt2w z7uQWPs}5=qg%Oa?`yX|L-_%#p*Zh=shD28}p$ANqrA+dMYJASS7Hq+t1J6o+@lZ@{ zIs?Lb3TGW3EIhZ+)t%uc8hEc%cmAK;Y*+9lb*zw0mCJwvWF3hqP=mjon6_ z<{w8-S_wTvZ9;FKfSnbXu6{WS^#y+ym=me*spQ-q+hVC22Ri$yScKXiP}`qArPQzp z+&fU)5aV0bRw53nu3c z4%t>T5{ZfMmlN5P@gQ;xSDgJgN6*XGiWF2%UuXWNeZnW?!i~~jHIlH;>TylSi@#fm z%q!as>1lyTO?alSGqnN7q$lWM^$@AChH+bkH&fU)B_77&meRxej7TNJ3|;2;GZ_0` z5FGQZ^;l674y}r4=#|}fx%sw3_1Un@%(m!wRX!!Sc+-eN2Rn`*d1VfUnK|QSK(*&Y z+w`zP8|DOoFI31!u-;b8B^Rpx`~B832O1D*PYpRwFFniTpvYZY4&O26g2pMbG5XbG(qA;zU$BvbhDr%HOcEVG# zA4U!$wG5SJaPYyqVIeT2xWI#p7{8fWij=&HQj1f1x1G~K>&OxGe4=eyYGLV-EZw55 zuu-^fpjv8a*R6-t8^T1S2!(xVO<+Uvx;?%jrk(tnk zFf^^m(8lxG!z5%YR60i>>gfi>u(zqRtB=s>GXk+3!avjPpO!IaV_VY=U#>$||I9W3 zfl`sbrL&stHw&`e(ip?DVJchE!)(|UliT1rbFLFzVI~3V<|)oHtIBNJJoFZ%PVWAB z&f(Dd;@Ub<6Wh>0)1N?*I2`a z^cj41>kP_;=e*3L*1W&%pMTy&5q@S;VwE#LMYH!+SFxIpg;8JUYK2G}-QHJKu+~_hKEIXhU6d_hBbQ0wpP%OXbXdZJ z-jYX^%!I1}t8TR@V#p8AN*au;?5S=caJMT7I)YeY+{P-#H{p7vrU`L$|KnP;{n(|FJ z%`o<5xPKyNcRJ$At@awVB&Sri*dl;#Ap?($FX80@ylWeSzf2T_jw|%PTx+W0!uw(~ z9A8XnTW`RGLj>(Mt|;r3dv9Y1oln5lDEvI<(xtTrZr?)RDr}sc`TlwP-YwIk%gl5h z`%cv+BZmnDiE3_=Afc_))it>r%r)%KGpCL&5;~c~?>RAFr)3<-TQE9i+-~nmE$5z}Dj4MAAk>au#AwWLLjU zsUZ{dHKgzC%rbpAyOcS7|C|cPeBT3Jur`J598&x$CW*q>Z(H+pZleTNj~Y#z6s2SY zKTjSx3E+*p+l))fW6IL86mXeh)SZ*~N=#t*-iYsI^OKX>AE(_Rq7!cXQ_sRDq3a0g zWA3ec^GhI|k|uO8`s-8YDOtlA@%y+)4`l|U5j&}A4d`TvGgyPrR=9A;Gy0%aCwia| z_A<0v(@Mw62!nr{(PL7KSV=b$Oa#u<&_1Y-Z$GaR2;huwM?5qq5WFHG8wR z1oyiVx7pTs%_2qjrgmqb#_=grT}{g_j8<$LTGj`m*(uwdqzkNjrGekE^4s`-$nXD; zD*qpsPbxjX^Jb*9{6ZFex5|;Yz6iV_sD$$;T$iv}=>(`{iX_Wq*Sus5P26kG*GQ8e zeqE0h#2&LSD9z76;2!RCdECp@jCP^(v3o;*n8RCym-$+3?zzD?6v+9si37a;YHWg) z1~wzktcPzu4LxKx=}bIoji|E4GOJR1gFs_koN%Bl-MYdhKSPQep|g;TpYMe>g?>It zhRD3K(x`TR;mWipZCoJO0ggjudH4>%I4^c#5V8N4Yz4;ggFJrDG}fNmHd-c_@@1W! zow2Dpy0E7^2FYD4kSiMp0s6}mq@?lImlkZR{nC*A*{*|S3Io6~w+K3#Ijgnc!}=)x zp}(rQoo;aDI3dS|8oK65XV15j{je z!T7K#9^Rl`Diy9^TVijUBXUR-X3?`+%oi+MATxnK zKq8ldANg;_lyWb$Ri%G<)N1qGRw#*?-&#`c5Bk`S0OVtsz|#6=vg2n*3{z=0 z|HpQT^5rS+266KK*~g7X%vWa4jT|eROWDDqzD~d5*BsoNjqb2b4h0Gk47|tlyz#3d zxd`ZD*z@IxV=<5q&Ntc)?|e>_vBYh@-~T9s5~JR_$9+r(=wU@9h)74wNw%!{kjUa0 zM$0L4d#`(^STXTOn|4$9yC#@+(~Jna-YpwhwHhb%7{~YRSXc|)u;g@T9g3x<3t`{1 zcB_=Qrv5f`1C~@Mlaz^=`@vcybmh?|EW^9)zar^2i+ompng*@+)>ZX6WdF33(u@H%VtFT9@yxbOTDVvIQRwm+yy zwfJs*0OMjapwphXu>myf9Z+UBZ;KOEPI5<(dVo^YCNpmAp%t?qMn1i|E^&Eq_N=Qi z)U_|`BAIyTbK0;|szh2JG>y}c0@x+d5M98mQ&f5uU+JD!P#q&gonBKA(7i1GFAfAQ zxRZ_Y?`dlQ4k(4VhPh-i*z>Cz%AxP4v9Y165e1O^VSe&I&hf~16IymR* z1;hc=Ivka;%(w6Zs_mpg7;O1^^8WN2#HmLcg@%FYbs$b+vTs8AhrdsANy4aL0fsR6 z?6M1jc>Ou-f5$*U!yDw;*53<^Gi|cVu4=`@GR(wNR%j4t$~V4OuXKS@g}(A=9u}A# z0t(}&Cttj0|Ed$ozL-1m$t%7E(Ea2u*mA?-CL2Q+QChdJvOLrOAwuk`+PbqIZO6d{ zR7&oIom#9|lo~a@3&1n}B03POnmXAj40v|g-DAR6RaqH4WThPvmWR1~bC55-^ySs` zw~qubTeyaQnF4BSsRjlg4^z#B6jBZ1p~aK>7;K>=Y6j%k5Nc5%&~siDe+HO9X2oNW)+G%{3t|xRZFF)yjnV6SKst7sHQR^YAraZA&(Nl> z3dS+-u#@bPQfr`L``XbO?f7xd3L$FL=m>Nq3%C=p-TpG*HOhDp8^dHJ z+@yffgZcb)?#qw5$c)aetLlJ@Auz7|6QUkhnyEom3#x{k6mrD zNpUnR53vqOy4(Nmrtti8xw5-t6Xf+L6p!`xrpJir2BDhKR?yS(@se0~o9d0+ZQ<71 zt-rp_FAWIK*{%1I3;p$9#F_d##bBMshyNl)13pgFQl_E%NqP^~Wt>|w>)|J;U-pklZ$c4qE>VJd?{03N zuur|HjTcJ;pO1SOOJeT|HAsK?@81g3k1$rWsp_rT(8YM<_$Dcz0cV!VIT$Jje92-` zr_PshkmIaC_6TD~o2t_42>sZXGr|<48EA~R9)@iw_tp6)tasD@U@@wMgs)$eE%I-& z3l|fPJRl8rAb-R-cp5$QC?a`BEl1^?30fE%5s!sNY$n8rSHvqItw~vK)l`C|cb%1$ zCjp6xCg*vN{Vn&Y%vi}Jk`AV>H;W%J_F)^)ib(#&$p}6NKntfLh;3+Tz^$Tx=~R6N zjqH)}lXyU2H5Lp1lO@|l<=E|dCtJOU*n>8x76ARqjn|g$OzY&ZUL_LQY>55+b>u>n z5=qT}J2_Sr|8jC5!~fUHk^BlH!Ipc6_@`O}-Bteid$Yu_Fxxmo?%^LLvJe zma*h~HbH?T>*R|!bzHAn(+|<|5gOLCG+4$2EtHRN`kU>dlvl9s4NTyIn~CwBC6!AH zf(h`}#xN7mW>mey#E5lyKw4|ZWe{hJS3bpD8#2*IrZ)+q4(LThD_0zws*yQ~0y`Gu zwDE*Rs99bP6ydCsp=tnRe31~9_XoSq3SklZb~z%PrMUk^k5UTWV{HfG1sdwW1flPR zPv{=qm&aLKMAd9JSL-_vd&1l^$Jnn}tp7nr8oiqZt^Yzt_j+pg0l~K#K7SbVdR`V} zogSUh>gcgITw5L{UL$UQigE^;Efr*nm3?_>P5TE~u-J2h>BebTi0Zxyzg|Lo>%zy9 zrSB4t3%Nvdz&4ZEw;n2i$KrzAb<~}1-Wx8AtpXgflUDLGq8HDuPXc7xFTi^&CR4d^ zhW=9QB-Mwzfjrd%0a@QgXRwe7TFB6k84}&c814VQulX;$^v6%ytakqB0vO{3cBd<* z|JCjy6t#2-8Wiel{oSKGZqz<~v02^h1;VaO=b7n@@0_mHr94)&j@6}A7JrYcDUi8A z+Fy4Ls6k%i)FgBP)p|U=xOb~6i^b^GQ8nHCgde* zS~$-@2sK1rV_B_|=vInte-kiYr&pqc-8Y3a>w61PjuER_kh#55wlTp325gDf-S2Fe ziSmyhVj)myDlnZl1yYLtqo5wt%%Z1+Q2q=T-13cW@gqkUbRg2{@Z~Z0++0Gz;V`DR z653_sVpA9vFoCpQ>+1f4 znCJ+!kyk;o11Fs3wcBsr`Z5nwi9}89M-{l0FscyPi&Y$o-$+}Z{F6|>|X1d3Se!gScok%8aMii zFKF1|xui=rJ*~(2g$^&#jPLsU^4-{lk-BrS^`jnv;Sc9gG;xmVMJ@#Po2rpmH`4_= z)O?A8!Iyzfg2f{nESIMw2Ne@qj}${eQnej^o^{kicx%dvD@R`DDTbZ zG+bJ#F3O(k1N5(moX2nImzo)6cVC5TuSgc@+1G+szp6+V|lmvy!t3hifkq9%%kn6BSE=? z5d}z#LReItM+OwJW!}tcm^rKY?I<_Xr_2GbIE>>x0|J^gR)3Gb10k=@TFg+9ce=x7 z+*z7-OywKE8`5!j*#)TmH>1kI(|vF9mkcB!7od4I)YYQ$ID^S_H8?o9)_=bRpcx$A zBc(~%p5Pr51nb=B)Acz%GinYifFgJ^eWnw9PuqS*tUPG0jiD=mAQ;*@ojGX^gvIw% zmmHE+vOxlQY{SiPr^6i0&mANyVPb^7*xqMu**4yZ{@KWa7ANAxw@g@sCRRA>>hfl( zt)9hNQq1?#irig2b6Cht`c!ukT)pnkB)B`y}d|6#7 zw3bSpxFYA%`k&Ysi!yx)>EDMNJ#&u~h-xYD2NkQzi+}oghgc!UzuCwzGZIuB^P>Ui_*qP2u;g$q!m2vn#_(<1sdvvRf0kNz z0r61Bq{zaf$h|2C$NK|KIw4`lfT&&JjoiOo=J*I#@(b2>{A7 zFHzBHOx2G5DIdq<{)#k;X&O#wgwzCE^Y{z$h zj0kqrvi0s!kLO2+^4Y*Ho@yN!_^PBAdN& z=JVcho{*>Y{zR~MXH{if(buESaog~CfNKN=PX4Pyi7~;6Bfr%Ozs7BUzWUbv-!Mt7 z@!SSRwJ7O{kroOhU0YIJ2HPV(ipBo07lX0qfz#n|v7E&7cBb4RPMoKh`f1Pk-_onj zqRoMcm)g3zSVcY>GdDKd8Qj|GpFdE{rzbPlZ{Z+>@o4d1_M5sF8zCa}d(UrR>IEGv z3F(&~ePY+SYPH0}5m$5)Ko1kZNQtPXG6C8%`v}Oo^!!4QR_|~+$Ck4{|4%knHOoz)a5J#wVVTg?(*u7PA z8%JlA(3gUs@ZO>zcIUm*kbq@Kn-8=Op^DQ-H#gtSJxQ@X<8{acl~lpRwVvXyr7aH$ zhGa{s-)CDMZEN~BqK8>k`=^IlEh4YbYgi+U+uq$b$jbo^#iqEIIe`EZ#P5=dtl^yNRyfZrv-@maDP2#WR9D-s%%A6u z;}v+87@72T8J>98vWE{JuHUD);23T-3CxeadlV#F<+(P+eRHRyjqlPn$&AMJIB4V1 z^IF`#&Q(l3{)2v;bEB-BoBPRn`s($u?EPQ4Cl0?A{;VESO@1?x!C43a%4WZ1NZUV& z8*jT`?G^jeaUZShc;O-{xI9Qj%(jZ2H=F74KwSP=lpg3(93Xgsh;luetV$;~ae4wy znTDPcS z-3R6uVkD+d*4om&#ZEm}SN%q&W2DGPpe&lyBn1yQKgY;3?up!m2m5SL zr@ELTbjMHV1Im8^)VTY}rwMo2T)QgmN6tFTv?g2g?UB}Ojj@oMlcWY`;|juF{q9N} z-BMS!dik)@S0yFi^hru1rGD%eTjMH6-cK$+1nlN}vKFH<|Jlzc9jhU4%Hdr)me$s6 f#y!`=H~2e`2F6^B&-SrjsNtxB)D>%9ScLr_9S;o8cdfg>ea?5jefBx$&f05kim9V$yOHAK zo+Z61L^y*NXr`+Hs2pM6!a1gH)_U$nMu1y5ObWoqqXiJ$P;fUO$rC{M4+a1PaTWj| zD8&0;Zz2AFdhzrN3I2ltZa2i3$x>&Wh>fR(HQd_BP|*bj6?bxlIlGA?pnf+5fHFc6 z2cd3oCvF7P$2U+Bp~CwQLlK8>njyU0|4`uGD!kT4rresa05@(~aS3q=-a9~UZf@lO zS9e7-EuDW4$9XEekKk}WMF=D$Bt$$!S{xSO0g+TtP=H8CL8PR_a161)P+zzcLd-Xi z?_VPS(a~}XbP4eEgL}e!xo>oxoMAz56<*$(K>xk|HBY#w`~M>O2L3xOT!N6B9*Cs4 z1mwTkxS`57t%@cAo^H6vH~M!ZmH%P>KW+bxqYSwT{(nv8Uzz^Xic9qlP#N;yWxE4p zaabV%0GO-wwA3vSc)PESp6%Yw>D%X<1%L~A*J=opQO`JtvQb^t@jvmvc!`{yw2oui zGt}!Uv8fxcg4=1I30ecb0?&Sro<#5K+1um@*aWN(Kj-Tb;d%`_ui}edWU6v#ZEIEe zRq9dbv7F-O$W8@QuE`3MS0PX#$cd$d8EC_PQ7G3_z!9qTDsyXFEY&z@dn@dX$8wol zVb^)t?l`B(XbcWw&BobO2u#EXI2KKynST&r#9$oENnPAzL3puj9z=PCf9ji*cEmxn z#V?)FcJsk@q={HzH^PDch@qyHQm?*_S!!m4wdOGeC*`hT;!b@Xn%VJD)pXJ2rQc~F zhY>2rp|v%^XCZ<{k+I>{aBlR%uY=K(ch=4#1tx;+BGS<6j8)40RRRciBOGj84t30)^wVnOUeHe95De`hHQ#Ir31oHTN+Pc>PgY%_TF+U9`b*%N50TBD`4?p1f!yaBIbOr z1+4%pJUAXzP1^l2nENpLvc5@Wquk(I0N5Dyoxt%8E=Cs1a_{Eb^gCe*`zcV`Rn=+y zMd24qktZCFitwsGUmO{{Fuir~t|01*A@doP>cv3^371+D={p0s48V%flw?GG8E&XV zZm)KTD_c0ei}vCbRR@6_AV^kjitB?n!6TNhYcH+y?eGBux~>dqfWlPN*9bup z>%ot$1cX%sAr&FLvgiFta$}_cFLBVp`xUhZ=d?o~@rbJNV0ctnbz?-8+{Ljp>a4Q~ z;)D~_PwO|;4qt~Xs^<^`?+xDNq05Z0-?q;0G$c^d#%(7zPkSnEI~PJp4Kz=$W(65y z2NWEUlr3HA0{6xkw7oxOIX>IAQG4FGEoChhlyWQ^wpn};&USY>@dR6@{B?rIe26JxD#qkT73_F|Ki9++_BjcGH&F2MvJr##Wvtq? zJVU_7jGBN)Uj8t^5WWxV!t-(6m;;jTKXB7SY2v+A`}tzpEghUZGhi9IN|7JcH$46k>F2NV^M$H8;O~B^ z{pLgY38sFgVg@{M&-e zUgAI^g*^_Wm_G-1+j5@VWgvR|{zc*G(;s*8e2JS)J`^+h%a_h$p9cgL)m=>0B)l$Y z=hgjLE{ZfT&22Xmy6su!Bd%_bZ(tnbP3o{cTJxfdEv8{%k66NyjGsK|J<+{S>Tg;Z z@oB)4p~NfYWqHYLiT5jM)Tw1(ZfV4zji-=N zgd(|@TEsFrXNN4!_yUu

3>xfiqTfqCl1QL4K>do|IlIMwpzaE%(1U4_n7wXKE1Z z>79eWm=U7|21qPn<$ zRE(!g(#q2|A@=GXj4+}kHduZ)DbC5jAGRr z3C4uTz@)bz-9(Y9ic$I`w(a$4h0a&G@9TeyeNz~p8LkK{e|gY6^Sg;|dziW6!w~t8 zPb`RXBIV8RvS5D!3wt8#ZZw-V$mdPfGuD|pYo#tbVsC*oNtv=p76*^&-g1xk-_oHM z?~C{tpPXI%Y!yGeEq~k6V`rkI8vDrpHitCRwyj0u+_=tm@wb;v)=R~mQ%_!6GR%Ky z^eH^L)2;TqZ9ig8EXJM<%U>S*W!5)2ZyT>ys$rJNK%~7g6`KFPVl;E`^QZNblieYT z?kAas_eFM;kX@y(#rAG~Xpp>^E+rzZ*Y7-*Z%L1>M80ULP+E}AdKOE${~R2ILdAX@ zQcF6yzlYv~kE-btD`L!RzlMepS4t6Fi3(V;XthnQMQ;r98_ZwX#{9-gs+DV;eU~j< z$3_z-*WWF`aE<*c2*Gn^n25&EnI6yVJbX$iY{Pr`!>w?mVF|zcR*CB6(u$wCc6QbG zJj;FT^&#Co?{HG5mYgHFN&!ZHV|eXCCSg~ZL8kHgsDbqXXUY?#Wt6fxB7209G}G}s z8!OmyFymG)M$Op~T;1!N`4?6+Ay%J3ef1F1gz3!I|i>_CGpbx�Zk39iNN2W!0vSxoXU0yenu@hIyf}m7lC6B4 z&1p&{eb|HJY9ZLMQdTr86*U=Mqa2GRj!K<$H(VgjMAkO4tfb($w@6L8aa?r-5T^_5 z3~85L3`Ur=_>gzjRadOJ@Zk)Oi??Ef<7SYKcA~+)S_nn7n=fDINr!CZ9v*D54ZZ*V zpo}rHTF>)={c$MSoj;wr53J`QqRnw<@N~qd;BY#u8!4n6eIcTQz(bobrcpb@K=VXz z9Jd5s2+TiAGdd?+n zIw5bq3Ag;1ZfqCNr;1QuicBougT6mbG@ z|61ANk9gK`)+wSKd#}WiFg|TIiWZ7m4L3%~BdCjoq#_{+sg;wy64A>2YB3L58V4e* zP#PI&RU9WGE%}&WUK60j?bf{l(p162pSGy*gUg?C8GS zF0d~Iikn{R7D%w_L(eC3V-#@<%0%tJft6xXM+D)rBwPuq5euYAP^CxvgJsvjm$U$Q zmR<$%-3T9MaI7KKN@{43(UhBxQK)W2r8+&^!<-BMisw_&R`K;4b-#3GbF``NJY;n` zclDPwfF(fl2v&|uY0z%M@&>S2Xdd~<1Q#_H@uLgLBK6o}&n(~b5w94~TY{KdqU}bClg3Ywr+vlZ(sO;Y)l8puDJ2QFO{xpm9*rP9+ z2y@(GDU!lcp?SyDxTe}o9t;QCZAA05%b6`V0%2|(o4v;w=sEmaLi793pWTKf;&wGs z*Ep!GwgsYm9Pl;cn^zSx+>Mf^`c|qjGFKvnpxyeaaC#Y30-DO-9c1^;&(%2gaM2`P z!owa-QnwM{RxIK6BVARI{ z)6UGhhnbrK*fY!;Cw8E2eNO4dBV(%#6y0ldp$td$5A1GZBbN>dSGt1V1>TN0x~gPU zKZQOC$A+q(?pE6yeITa3%0ybMzm3pSbpbTL&mtaArPPxqNYaT-ePv|<61_ZG@EE~{ zPw0EwZJGS!eAX!VR>I?@;^FzAA8-Ek`Q`C0e59%To^M6{G;=(KW>&MBvec3|d}LrP zpYX>Fw~Q7hFL{gWD?+uzMM>aMCRME#$o2Clc6uKA+LkpiF)=ZoTlm)j0J~3 z`gnzpm71Dgb<%te)s7_5&NWVK z`bZIFy|XCa(8$>JDroaJB$wi`=msY}9%e70rk9$W(Z1}i?bWjCJ*`=1d(Cq5$TdX+ zqbEggYkQh^S<8IJ?{j!%@~jHZRr9J;{_+T3DnC%A?~Fvm3!oH8I4v!TmX$~oI`!o3 z0TYX|MdZXSDIm6nvK5QQO0d08b8B%Sbv-S;YHj|{z#`P+@Ex-r*81cwk<C3D7f^uH5Yl^uIq&{QWM#xUz3;Zg@zr~u}Nc+;47D1UrqK*J82Dh-a#|UJB z*=Y%ri$Scvt zocpl}1wa_epaR7B*0of!{8#wGn}!8M;B2L;xwhcB<#lfb@X3*8Vvb~dNbGO-SWe#k z%mXV<28Hbkt%CkgQ zDEZ+xDXAg8v>G-2^s<-vDFstV=p)x2mP?c(f9#xH11io&>`AQynXeryFugDPqSo6K zxlBy|s~THx1Ev4JRb#;0;gW^ck#|R&7C-1n z3bI;M)`322Tme0GL=gl?hEw1g)&-+9t3+5<)-Czsa400um;Q1Iv~s0cMz10`ut&F` zeWi+_Hr;T$-y2sg+Lh;%AzgHOy=xPoEcfb)YhyTbP+|=8@RT5UA0kx40ORpBTMBp!k3FI4hpleP?T!*r%HUVGZw>E ze!oc4a_ni5^W7CAXZ?G(4=wJaec^T<3IP-;5!*hvGd{d@=AGarM;aYq%q8vR{#kr- zs{U|E1xb3YnlNDdevNS@;v0{6?F0uC<%z5*i!A?7=56IappWdK6fXIff{U*gu&gUr z-<7c);$zZd(g(uQ)GzZ@^;KKUZ~kl(U?DXeG58A4L&c(E`*LwbV_$BME0Jex|na-&V-xZ3y7wFm{N+$6@k zgIbFUw^O!tGSO?^imPl8LL;+?Auwj6=)B^tmT8CC54u!X-zhUaRP0+tOo!T;zm3R~ zM6cP0e|)sl;Cb5)ixSOOm}#5SrY>X|{dpqI(-5nmgBro2jSE9a@myMI`WwI6MtWxJ z`9rMhAnP&^y7}EE(q~+Fa!qfT?{P;31+%lcR>hCRcS3G-9WJQ7y3_#Lw5VoRfz{0J zZ+r(OFXKrr@3Kfke~3A2^LE@z7cUnj#Lmn?gcFLXT}Pg|>-@-UI3FVu^8PxZE&C{3 zS=ef4Z0iLl1jfh*qW_{-64w;Acd+ikJPXBacPe?grpjva#R$Fo!gp>4P3Gq?X8faq zl*qDlcitNbt}B@81%w3)|)vY=^lsUgA7?_%f!lYZL?8va|M9fY0Megn~VL9fEj%T&=_V0Akd>ALA z^2|G47W0vK^qG7GMW)epTZ=VVO+$TbEnoIw>qOeiQU8i1<@){sk!0sd)`*zb^a~3M zHkw12a{Sk_BzT#d$V4$v@U6Kq$1kNI%`=_`u`jv2Q|jR1bpY~y`jPW9=cm_|74*?} zTb>m#H!jAnE~uA0;$x_JRy#Ahg&5&k*<(sR(k&|6eLGk>>22>D7O%`nL#04DzPvt6 z|1(BQi;{3g?cBx+)~g)QM>(cpt68`x`?w!K^|Vu5aXY{ND{2i z1#2&Y9e(S!@R1wG6|YYKp;P)21Qdq!wtr3d`X`e&r&sR&ab0*aE8u~W!Q@?JF>&Cz zrgn9<8*(gnCpsLG9_;zkDMKE7If|dm}_Nj9Sl^U*f35lo(d`zmxku*=DT_SDg@c=v!_SWtM=&MW=gj})6;k}dQM98xvRq! zJ$iTFv~A7nULnPvxReuKsuM=p!hx@83qPei3nn?g9d_gw#oqc08)-!PHrpu< zZN_SJ{n@vBaVQLwuAnZV=6WvY@`tiNv@#|*ng@P{X7A#k(jiLvrOhb6V&eK_Gc>Ex zv4r(hAq?YL&HH-NT$zeh!xRk;50rK9Veft}*lbZ~Hq;ZkZn=8#^Zx199Ur~ijZ9!8 zG86(6|NJsO>PX{JQUmhiV$?DP>0)r|ul7Z|rqJcf^%qHF3(;mQfZ0Xw`<(*wcQl$)o@n1-RBg1K eZV)hb6`f+Ge?kg1Ww`kaq^E7HRjJ_^_kRG63#4-Z From b5abadec058be50a1b1b092a0cf2f57d22e8449d Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 24 Oct 2024 10:34:43 +0200 Subject: [PATCH 16/17] docs: add feCompostie to examples --- .../src/examples/Filters/FeComposite.tsx | 592 +++++++++++------- apps/examples/src/examples/Filters/index.tsx | 2 + 2 files changed, 379 insertions(+), 215 deletions(-) diff --git a/apps/examples/src/examples/Filters/FeComposite.tsx b/apps/examples/src/examples/Filters/FeComposite.tsx index 057743ec2..e7485b619 100644 --- a/apps/examples/src/examples/Filters/FeComposite.tsx +++ b/apps/examples/src/examples/Filters/FeComposite.tsx @@ -1,9 +1,10 @@ -import React, {Component} from 'react'; -import {Image, Text as RNText} from 'react-native'; +import {Image, Text as RNText, View} from 'react-native'; import { Defs, FeComposite, - FeOffset, + FeFlood, + FeMerge, + FeMergeNode, Filter, G, Path, @@ -13,229 +14,390 @@ import { Use, } from 'react-native-svg'; -class QuickTestExample extends Component { - static title = 'QuickTestExample'; - render() { - return ( - - - - - - - - ); - } +import React from 'react'; + +QuickTestExample.title = 'Quick Test Example'; +function QuickTestExample() { + return ( + + + + + + + + ); } -class ReferenceExample extends Component { - static title = 'Composite'; - render() { - return ( - <> - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + opacity 1.0 + + + (with FeFlood) + + + opacity 0.5 + + + (with FeFlood) + + + + + + + over + - - - - - - - + + + + + in + - - - - - - - opacity 1.0 + + + + + out - - (without feFlood) + + + + + + atop - - opacity 0.5 + + + + + + xor - - (without feFlood) + + + + + + arithmetic - - - - - - over - - - - - - - in - - - - - - - out - - - - - - - atop - - - - - - - xor - - - - - - - arithmetic - - - - W3 Reference - - - ); - } + + + opacity 1.0 + + + (without FeFlood) + + + opacity 0.5 + + + (without FeFlood) + + + + + + + over + + + + + + + in + + + + + + + out + + + + + + + atop + + + + + + + xor + + + + + + + arithmetic + + + + + + W3 Reference + + + ); } const icon = ( @@ -257,6 +419,6 @@ const icon = ( /> ); +const samples = [QuickTestExample, ReferenceExample]; -const samples = [ReferenceExample, QuickTestExample]; export {icon, samples}; diff --git a/apps/examples/src/examples/Filters/index.tsx b/apps/examples/src/examples/Filters/index.tsx index 870030e8a..131cb9429 100644 --- a/apps/examples/src/examples/Filters/index.tsx +++ b/apps/examples/src/examples/Filters/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import Svg, {Circle} from 'react-native-svg'; import * as FeBlend from './FeBlend'; import * as FeColorMatrix from './FeColorMatrix'; +import * as FeComposite from './FeComposite'; import * as FeFlood from './FeFlood'; import * as FeGaussianBlur from './FeGaussianBlur'; import * as FeMerge from './FeMerge'; @@ -11,6 +12,7 @@ import * as ReanimatedFeColorMatrix from './ReanimatedFeColorMatrix'; const samples = { FeBlend, FeColorMatrix, + FeComposite, FeFlood, FeGaussianBlur, FeMerge, From 892af70f68a4b3e07946d6cf5bda3cf8dfa7036a Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 24 Oct 2024 10:37:17 +0200 Subject: [PATCH 17/17] docs: revert unnecessary changes --- apps/examples/src/examples/Filters/FeColorMatrix.tsx | 2 +- apps/examples/src/examples/Filters/FeGaussianBlur.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/examples/src/examples/Filters/FeColorMatrix.tsx b/apps/examples/src/examples/Filters/FeColorMatrix.tsx index c4892b7a6..4edb34e58 100644 --- a/apps/examples/src/examples/Filters/FeColorMatrix.tsx +++ b/apps/examples/src/examples/Filters/FeColorMatrix.tsx @@ -99,7 +99,7 @@ LuminanceToAlphaExample.title = 'Luminance to alpha'; const icon = ( - + diff --git a/apps/examples/src/examples/Filters/FeGaussianBlur.tsx b/apps/examples/src/examples/Filters/FeGaussianBlur.tsx index 22a81c519..5c294079e 100644 --- a/apps/examples/src/examples/Filters/FeGaussianBlur.tsx +++ b/apps/examples/src/examples/Filters/FeGaussianBlur.tsx @@ -66,7 +66,7 @@ StdDeviation025Example.title = 'stdDeviation="0 25"'; const icon = ( - +