feat: add FeGaussianBlur filter (#2352)

# Summary

Continuation of #2316 
Introducing new filter `FeGaussianBlur`.

### Implementation notes

On Android there is no easy way to fully implement Gaussian blur, as
there is no native api for this. While a basic implementation is
possible with `RenderScript`, it does not allow for blur in one axis and
greater than `25`

## Test Plan

Example app -> Filters -> FeGaussianBlur

## Compatibility

| OS      | Implemented |
| ------- | :---------: |
| iOS     |         |
| Android |         |
This commit is contained in:
Jakub Grzywacz
2024-07-25 11:46:45 +02:00
committed by GitHub
parent ba7d77548f
commit 44254df9fb
27 changed files with 624 additions and 13 deletions

View File

@@ -25,6 +25,7 @@ import Marker from './elements/Marker';
import ForeignObject from './elements/ForeignObject';
import Filter from './elements/filters/Filter';
import FeColorMatrix from './elements/filters/FeColorMatrix';
import FeGaussianBlur from './elements/filters/FeGaussianBlur';
import {
parse,
@@ -71,6 +72,7 @@ import {
RNSVGUse,
RNSVGFilter,
RNSVGFeColorMatrix,
RNSVGFeGaussianBlur,
} from './fabric';
export {
@@ -109,6 +111,7 @@ export type { MarkerProps } from './elements/Marker';
export type { ForeignObjectProps } from './elements/ForeignObject';
export type { FilterProps } from './elements/filters/Filter';
export type { FeColorMatrixProps } from './elements/filters/FeColorMatrix';
export type { FeGaussianBlurProps } from './elements/filters/FeGaussianBlur';
export type { FilterPrimitiveCommonProps } from './elements/filters/FilterPrimitive';
export * from './lib/extract/types';
@@ -149,6 +152,7 @@ export {
Shape,
Filter,
FeColorMatrix,
FeGaussianBlur,
RNSVGMarker,
RNSVGMask,
RNSVGPattern,
@@ -173,6 +177,7 @@ export {
RNSVGForeignObject,
RNSVGFilter,
RNSVGFeColorMatrix,
RNSVGFeGaussianBlur,
};
export type {

View File

@@ -0,0 +1,40 @@
import * as React from 'react';
import { NativeMethods } from 'react-native';
import RNSVGFeGaussianBlur from '../../fabric/FeGaussianBlurNativeComponent';
import {
extractFeGaussianBlur,
extractFilter,
} from '../../lib/extract/extractFilter';
import { FilterEdgeMode, NumberProp } from '../../lib/extract/types';
import FilterPrimitive from './FilterPrimitive';
export interface FeGaussianBlurProps {
in?: string;
stdDeviation?: NumberProp;
// edgeMode is hard to implement and not supported by any
// browser except safari, so it's not implemented for now
// https://caniuse.com/mdn-api_svgfegaussianblurelement_edgemode
edgeMode?: FilterEdgeMode;
}
export default class FeGaussianBlur extends FilterPrimitive<FeGaussianBlurProps> {
static displayName = 'FeGaussianBlur';
static defaultProps = {
...this.defaultPrimitiveProps,
stdDeviation: 0,
edgeMode: 'none',
};
render() {
return (
<RNSVGFeGaussianBlur
ref={(ref) =>
this.refMethod(ref as (FeGaussianBlur & NativeMethods) | null)
}
{...extractFilter(this.props)}
{...extractFeGaussianBlur(this.props)}
/>
);
}
}

View File

@@ -0,0 +1,25 @@
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 FilterEdgeMode = 'duplicate' | 'wrap' | 'none';
interface FilterPrimitiveCommonProps {
x?: UnsafeMixed<NumberProp>;
y?: UnsafeMixed<NumberProp>;
width?: UnsafeMixed<NumberProp>;
height?: UnsafeMixed<NumberProp>;
result?: string;
}
export interface NativeProps extends ViewProps, FilterPrimitiveCommonProps {
in1?: string;
stdDeviationX?: Float;
stdDeviationY?: Float;
edgeMode?: WithDefault<FilterEdgeMode, 'none'>;
}
export default codegenNativeComponent<NativeProps>('RNSVGFeGaussianBlur');

View File

@@ -22,6 +22,7 @@ import RNSVGTSpan from './TSpanNativeComponent';
import RNSVGUse from './UseNativeComponent';
import RNSVGFilter from './FilterNativeComponent';
import RNSVGFeColorMatrix from './FeColorMatrixNativeComponent';
import RNSVGFeGaussianBlur from './FeGaussianBlurNativeComponent';
export {
RNSVGCircle,
@@ -48,4 +49,5 @@ export {
RNSVGUse,
RNSVGFilter,
RNSVGFeColorMatrix,
RNSVGFeGaussianBlur,
};

View File

@@ -1,7 +1,10 @@
import { FilterPrimitiveCommonProps } from '../elements/filters/FilterPrimitive';
import { FeColorMatrixProps } from '../index';
import { FeColorMatrixProps, FeGaussianBlurProps } from '../index';
export type FilterElement = ({ name: 'feColorMatrix' } & FeColorMatrixProps) &
export type FilterElement = (
| ({ name: 'feColorMatrix' } & FeColorMatrixProps)
| ({ name: 'feGaussianBlur' } & FeGaussianBlurProps)
) &
FilterPrimitiveCommonProps;
export type Filters = Array<FilterElement>;

View File

@@ -1,5 +1,7 @@
import { FeColorMatrixProps as FeColorMatrixComponentProps } from '../../elements/filters/FeColorMatrix';
import { FeGaussianBlurProps as FeGaussianBlurComponentProps } from '../../elements/filters/FeGaussianBlur';
import { NativeProps as FeColorMatrixNativeProps } from '../../fabric/FeColorMatrixNativeComponent';
import { NativeProps as FeGaussianBlurNativeProps } from '../../fabric/FeGaussianBlurNativeComponent';
import { NumberProp } from './types';
const spaceReg = /\s+/;
@@ -53,3 +55,32 @@ export const extractFeColorMatrix = (
return extracted;
};
export const extractFeGaussianBlur = (
props: FeGaussianBlurComponentProps
): FeGaussianBlurNativeProps => {
const extracted: FeGaussianBlurNativeProps = {};
if (props.in) {
extracted.in1 = props.in;
}
if (
typeof props.stdDeviation === 'string' &&
props.stdDeviation.match(spaceReg)
) {
const stdDeviation = props.stdDeviation.split(spaceReg);
extracted.stdDeviationX = Number(stdDeviation[0]) || 0;
extracted.stdDeviationY = Number(stdDeviation[1]) || 0;
} else if (
typeof props.stdDeviation === 'number' ||
(typeof props.stdDeviation === 'string' &&
!props.stdDeviation.match(spaceReg))
) {
extracted.stdDeviationX = Number(props.stdDeviation) || 0;
extracted.stdDeviationY = Number(props.stdDeviation) || 0;
}
if (props.edgeMode) {
extracted.edgeMode = props.edgeMode;
}
return extracted;
};

View File

@@ -27,6 +27,7 @@ import Mask from './elements/Mask';
import Marker from './elements/Marker';
import Filter from './elements/filters/Filter';
import FeColorMatrix from './elements/filters/FeColorMatrix';
import FeGaussianBlur from './elements/filters/FeGaussianBlur';
export const tags: { [tag: string]: ComponentType } = {
svg: Svg,
@@ -54,6 +55,7 @@ export const tags: { [tag: string]: ComponentType } = {
marker: Marker,
filter: Filter,
feColorMatrix: FeColorMatrix,
feGaussianBlur: FeGaussianBlur,
};
function missingTag() {