Skip to main content

usvg/tree/
filter.rs

1// Copyright 2018 the Resvg Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! SVG filter types.
5
6use strict_num::PositiveF32;
7
8use crate::{BlendMode, Color, Group, NonEmptyString, NonZeroF32, NonZeroRect, Opacity};
9
10/// A filter element.
11///
12/// `filter` element in the SVG.
13#[derive(Debug)]
14pub struct Filter {
15    pub(crate) id: NonEmptyString,
16    pub(crate) rect: NonZeroRect,
17    pub(crate) primitives: Vec<Primitive>,
18}
19
20impl Filter {
21    /// Element's ID.
22    ///
23    /// Taken from the SVG itself.
24    /// Used only during SVG writing. `resvg` doesn't rely on this property.
25    pub fn id(&self) -> &str {
26        self.id.get()
27    }
28
29    /// Filter region.
30    ///
31    /// `x`, `y`, `width` and `height` in the SVG.
32    pub fn rect(&self) -> NonZeroRect {
33        self.rect
34    }
35
36    /// A list of filter primitives.
37    pub fn primitives(&self) -> &[Primitive] {
38        &self.primitives
39    }
40}
41
42/// A filter primitive element.
43#[derive(Clone, Debug)]
44pub struct Primitive {
45    pub(crate) rect: NonZeroRect,
46    pub(crate) color_interpolation: ColorInterpolation,
47    pub(crate) result: String,
48    pub(crate) kind: Kind,
49}
50
51impl Primitive {
52    /// Filter subregion.
53    ///
54    /// `x`, `y`, `width` and `height` in the SVG.
55    pub fn rect(&self) -> NonZeroRect {
56        self.rect
57    }
58
59    /// Color interpolation mode.
60    ///
61    /// `color-interpolation-filters` in the SVG.
62    pub fn color_interpolation(&self) -> ColorInterpolation {
63        self.color_interpolation
64    }
65
66    /// Assigned name for this filter primitive.
67    ///
68    /// `result` in the SVG.
69    pub fn result(&self) -> &str {
70        &self.result
71    }
72
73    /// Filter primitive kind.
74    pub fn kind(&self) -> &Kind {
75        &self.kind
76    }
77}
78
79/// A filter kind.
80#[allow(missing_docs)]
81#[derive(Clone, Debug)]
82pub enum Kind {
83    Blend(Blend),
84    ColorMatrix(ColorMatrix),
85    ComponentTransfer(ComponentTransfer),
86    Composite(Composite),
87    ConvolveMatrix(ConvolveMatrix),
88    DiffuseLighting(DiffuseLighting),
89    DisplacementMap(DisplacementMap),
90    DropShadow(DropShadow),
91    Flood(Flood),
92    GaussianBlur(GaussianBlur),
93    Image(Image),
94    Merge(Merge),
95    Morphology(Morphology),
96    Offset(Offset),
97    SpecularLighting(SpecularLighting),
98    Tile(Tile),
99    Turbulence(Turbulence),
100}
101
102impl Kind {
103    /// Checks that `FilterKind` has a specific input.
104    pub fn has_input(&self, input: &Input) -> bool {
105        match self {
106            Kind::Blend(fe) => fe.input1 == *input || fe.input2 == *input,
107            Kind::ColorMatrix(fe) => fe.input == *input,
108            Kind::ComponentTransfer(fe) => fe.input == *input,
109            Kind::Composite(fe) => fe.input1 == *input || fe.input2 == *input,
110            Kind::ConvolveMatrix(fe) => fe.input == *input,
111            Kind::DiffuseLighting(fe) => fe.input == *input,
112            Kind::DisplacementMap(fe) => fe.input1 == *input || fe.input2 == *input,
113            Kind::DropShadow(fe) => fe.input == *input,
114            Kind::Flood(_) => false,
115            Kind::GaussianBlur(fe) => fe.input == *input,
116            Kind::Image(_) => false,
117            Kind::Merge(fe) => fe.inputs.iter().any(|i| i == input),
118            Kind::Morphology(fe) => fe.input == *input,
119            Kind::Offset(fe) => fe.input == *input,
120            Kind::SpecularLighting(fe) => fe.input == *input,
121            Kind::Tile(fe) => fe.input == *input,
122            Kind::Turbulence(_) => false,
123        }
124    }
125}
126
127/// Identifies input for a filter primitive.
128#[allow(missing_docs)]
129#[derive(Clone, PartialEq, Debug)]
130pub enum Input {
131    SourceGraphic,
132    SourceAlpha,
133    Reference(String),
134}
135
136/// A color interpolation mode.
137///
138/// The default is `ColorInterpolation::LinearRGB`.
139#[allow(missing_docs)]
140#[derive(Clone, Copy, PartialEq, Debug, Default)]
141pub enum ColorInterpolation {
142    SRGB,
143    #[default]
144    LinearRGB,
145}
146
147/// A blend filter primitive.
148///
149/// `feBlend` element in the SVG.
150#[derive(Clone, Debug)]
151pub struct Blend {
152    pub(crate) input1: Input,
153    pub(crate) input2: Input,
154    pub(crate) mode: BlendMode,
155}
156
157impl Blend {
158    /// Identifies input for the given filter primitive.
159    ///
160    /// `in` in the SVG.
161    pub fn input1(&self) -> &Input {
162        &self.input1
163    }
164
165    /// Identifies input for the given filter primitive.
166    ///
167    /// `in2` in the SVG.
168    pub fn input2(&self) -> &Input {
169        &self.input2
170    }
171
172    /// A blending mode.
173    ///
174    /// `mode` in the SVG.
175    pub fn mode(&self) -> BlendMode {
176        self.mode
177    }
178}
179
180/// A color matrix filter primitive.
181///
182/// `feColorMatrix` element in the SVG.
183#[derive(Clone, Debug)]
184pub struct ColorMatrix {
185    pub(crate) input: Input,
186    pub(crate) kind: ColorMatrixKind,
187}
188
189impl ColorMatrix {
190    /// Identifies input for the given filter primitive.
191    ///
192    /// `in` in the SVG.
193    pub fn input(&self) -> &Input {
194        &self.input
195    }
196
197    /// A matrix kind.
198    ///
199    /// `type` in the SVG.
200    pub fn kind(&self) -> &ColorMatrixKind {
201        &self.kind
202    }
203}
204
205/// A color matrix filter primitive kind.
206#[derive(Clone, Debug)]
207#[allow(missing_docs)]
208pub enum ColorMatrixKind {
209    Matrix(Vec<f32>), // Guarantee to have 20 numbers.
210    Saturate(PositiveF32),
211    HueRotate(f32),
212    LuminanceToAlpha,
213}
214
215impl Default for ColorMatrixKind {
216    fn default() -> Self {
217        ColorMatrixKind::Matrix(vec![
218            1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
219            0.0, 1.0, 0.0,
220        ])
221    }
222}
223
224/// A component-wise remapping filter primitive.
225///
226/// `feComponentTransfer` element in the SVG.
227#[derive(Clone, Debug)]
228pub struct ComponentTransfer {
229    pub(crate) input: Input,
230    pub(crate) func_r: TransferFunction,
231    pub(crate) func_g: TransferFunction,
232    pub(crate) func_b: TransferFunction,
233    pub(crate) func_a: TransferFunction,
234}
235
236impl ComponentTransfer {
237    /// Identifies input for the given filter primitive.
238    ///
239    /// `in` in the SVG.
240    pub fn input(&self) -> &Input {
241        &self.input
242    }
243
244    /// `feFuncR` in the SVG.
245    pub fn func_r(&self) -> &TransferFunction {
246        &self.func_r
247    }
248
249    /// `feFuncG` in the SVG.
250    pub fn func_g(&self) -> &TransferFunction {
251        &self.func_g
252    }
253
254    /// `feFuncB` in the SVG.
255    pub fn func_b(&self) -> &TransferFunction {
256        &self.func_b
257    }
258
259    /// `feFuncA` in the SVG.
260    pub fn func_a(&self) -> &TransferFunction {
261        &self.func_a
262    }
263}
264
265/// A transfer function used by `FeComponentTransfer`.
266///
267/// <https://www.w3.org/TR/SVG11/filters.html#transferFuncElements>
268#[derive(Clone, Debug)]
269pub enum TransferFunction {
270    /// Keeps a component as is.
271    Identity,
272
273    /// Applies a linear interpolation to a component.
274    ///
275    /// The number list can be empty.
276    Table(Vec<f32>),
277
278    /// Applies a step function to a component.
279    ///
280    /// The number list can be empty.
281    Discrete(Vec<f32>),
282
283    /// Applies a linear shift to a component.
284    #[allow(missing_docs)]
285    Linear { slope: f32, intercept: f32 },
286
287    /// Applies an exponential shift to a component.
288    #[allow(missing_docs)]
289    Gamma {
290        amplitude: f32,
291        exponent: f32,
292        offset: f32,
293    },
294}
295
296/// A composite filter primitive.
297///
298/// `feComposite` element in the SVG.
299#[derive(Clone, Debug)]
300pub struct Composite {
301    pub(crate) input1: Input,
302    pub(crate) input2: Input,
303    pub(crate) operator: CompositeOperator,
304}
305
306impl Composite {
307    /// Identifies input for the given filter primitive.
308    ///
309    /// `in` in the SVG.
310    pub fn input1(&self) -> &Input {
311        &self.input1
312    }
313
314    /// Identifies input for the given filter primitive.
315    ///
316    /// `in2` in the SVG.
317    pub fn input2(&self) -> &Input {
318        &self.input2
319    }
320
321    /// A compositing operation.
322    ///
323    /// `operator` in the SVG.
324    pub fn operator(&self) -> CompositeOperator {
325        self.operator
326    }
327}
328
329/// An images compositing operation.
330#[allow(missing_docs)]
331#[derive(Clone, Copy, PartialEq, Debug)]
332pub enum CompositeOperator {
333    Over,
334    In,
335    Out,
336    Atop,
337    Xor,
338    Lighter,
339    Arithmetic { k1: f32, k2: f32, k3: f32, k4: f32 },
340}
341
342/// A matrix convolution filter primitive.
343///
344/// `feConvolveMatrix` element in the SVG.
345#[derive(Clone, Debug)]
346pub struct ConvolveMatrix {
347    pub(crate) input: Input,
348    pub(crate) matrix: ConvolveMatrixData,
349    pub(crate) divisor: NonZeroF32,
350    pub(crate) bias: f32,
351    pub(crate) edge_mode: EdgeMode,
352    pub(crate) preserve_alpha: bool,
353}
354
355impl ConvolveMatrix {
356    /// Identifies input for the given filter primitive.
357    ///
358    /// `in` in the SVG.
359    pub fn input(&self) -> &Input {
360        &self.input
361    }
362
363    /// A convolve matrix.
364    pub fn matrix(&self) -> &ConvolveMatrixData {
365        &self.matrix
366    }
367
368    /// A matrix divisor.
369    ///
370    /// `divisor` in the SVG.
371    pub fn divisor(&self) -> NonZeroF32 {
372        self.divisor
373    }
374
375    /// A kernel matrix bias.
376    ///
377    /// `bias` in the SVG.
378    pub fn bias(&self) -> f32 {
379        self.bias
380    }
381
382    /// An edges processing mode.
383    ///
384    /// `edgeMode` in the SVG.
385    pub fn edge_mode(&self) -> EdgeMode {
386        self.edge_mode
387    }
388
389    /// An alpha preserving flag.
390    ///
391    /// `preserveAlpha` in the SVG.
392    pub fn preserve_alpha(&self) -> bool {
393        self.preserve_alpha
394    }
395}
396
397/// A convolve matrix representation.
398///
399/// Used primarily by [`ConvolveMatrix`].
400#[derive(Clone, Debug)]
401pub struct ConvolveMatrixData {
402    pub(crate) target_x: u32,
403    pub(crate) target_y: u32,
404    pub(crate) columns: u32,
405    pub(crate) rows: u32,
406    pub(crate) data: Vec<f32>,
407}
408
409impl ConvolveMatrixData {
410    /// Returns a matrix's X target.
411    ///
412    /// `targetX` in the SVG.
413    pub fn target_x(&self) -> u32 {
414        self.target_x
415    }
416
417    /// Returns a matrix's Y target.
418    ///
419    /// `targetY` in the SVG.
420    pub fn target_y(&self) -> u32 {
421        self.target_y
422    }
423
424    /// Returns a number of columns in the matrix.
425    ///
426    /// Part of the `order` attribute in the SVG.
427    pub fn columns(&self) -> u32 {
428        self.columns
429    }
430
431    /// Returns a number of rows in the matrix.
432    ///
433    /// Part of the `order` attribute in the SVG.
434    pub fn rows(&self) -> u32 {
435        self.rows
436    }
437
438    /// The actual matrix.
439    pub fn data(&self) -> &[f32] {
440        &self.data
441    }
442}
443
444impl ConvolveMatrixData {
445    /// Creates a new `ConvolveMatrixData`.
446    ///
447    /// Returns `None` when:
448    ///
449    /// - `columns` * `rows` != `data.len()`
450    /// - `target_x` >= `columns`
451    /// - `target_y` >= `rows`
452    pub(crate) fn new(
453        target_x: u32,
454        target_y: u32,
455        columns: u32,
456        rows: u32,
457        data: Vec<f32>,
458    ) -> Option<Self> {
459        if (columns * rows) as usize != data.len() || target_x >= columns || target_y >= rows {
460            return None;
461        }
462
463        Some(ConvolveMatrixData {
464            target_x,
465            target_y,
466            columns,
467            rows,
468            data,
469        })
470    }
471
472    /// Returns a matrix value at the specified position.
473    ///
474    /// # Panics
475    ///
476    /// - When position is out of bounds.
477    pub fn get(&self, x: u32, y: u32) -> f32 {
478        self.data[(y * self.columns + x) as usize]
479    }
480}
481
482/// An edges processing mode.
483#[allow(missing_docs)]
484#[derive(Clone, Copy, PartialEq, Debug)]
485pub enum EdgeMode {
486    None,
487    Duplicate,
488    Wrap,
489}
490
491/// A displacement map filter primitive.
492///
493/// `feDisplacementMap` element in the SVG.
494#[derive(Clone, Debug)]
495pub struct DisplacementMap {
496    pub(crate) input1: Input,
497    pub(crate) input2: Input,
498    pub(crate) scale: f32,
499    pub(crate) x_channel_selector: ColorChannel,
500    pub(crate) y_channel_selector: ColorChannel,
501}
502
503impl DisplacementMap {
504    /// Identifies input for the given filter primitive.
505    ///
506    /// `in` in the SVG.
507    pub fn input1(&self) -> &Input {
508        &self.input1
509    }
510
511    /// Identifies input for the given filter primitive.
512    ///
513    /// `in2` in the SVG.
514    pub fn input2(&self) -> &Input {
515        &self.input2
516    }
517
518    /// Scale factor.
519    ///
520    /// `scale` in the SVG.
521    pub fn scale(&self) -> f32 {
522        self.scale
523    }
524
525    /// Indicates a source color channel along the X-axis.
526    ///
527    /// `xChannelSelector` in the SVG.
528    pub fn x_channel_selector(&self) -> ColorChannel {
529        self.x_channel_selector
530    }
531
532    /// Indicates a source color channel along the Y-axis.
533    ///
534    /// `yChannelSelector` in the SVG.
535    pub fn y_channel_selector(&self) -> ColorChannel {
536        self.y_channel_selector
537    }
538}
539
540/// A color channel.
541#[allow(missing_docs)]
542#[derive(Clone, Copy, PartialEq, Debug)]
543pub enum ColorChannel {
544    R,
545    G,
546    B,
547    A,
548}
549
550/// A drop shadow filter primitive.
551///
552/// This is essentially `feGaussianBlur`, `feOffset` and `feFlood` joined together.
553///
554/// `feDropShadow` element in the SVG.
555#[derive(Clone, Debug)]
556pub struct DropShadow {
557    pub(crate) input: Input,
558    pub(crate) dx: f32,
559    pub(crate) dy: f32,
560    pub(crate) std_dev_x: PositiveF32,
561    pub(crate) std_dev_y: PositiveF32,
562    pub(crate) color: Color,
563    pub(crate) opacity: Opacity,
564}
565
566impl DropShadow {
567    /// Identifies input for the given filter primitive.
568    ///
569    /// `in` in the SVG.
570    pub fn input(&self) -> &Input {
571        &self.input
572    }
573
574    /// The amount to offset the input graphic along the X-axis.
575    pub fn dx(&self) -> f32 {
576        self.dx
577    }
578
579    /// The amount to offset the input graphic along the Y-axis.
580    pub fn dy(&self) -> f32 {
581        self.dy
582    }
583
584    /// A standard deviation along the X-axis.
585    ///
586    /// `stdDeviation` in the SVG.
587    pub fn std_dev_x(&self) -> PositiveF32 {
588        self.std_dev_x
589    }
590
591    /// A standard deviation along the Y-axis.
592    ///
593    /// `stdDeviation` in the SVG.
594    pub fn std_dev_y(&self) -> PositiveF32 {
595        self.std_dev_y
596    }
597
598    /// A flood color.
599    ///
600    /// `flood-color` in the SVG.
601    pub fn color(&self) -> Color {
602        self.color
603    }
604
605    /// A flood opacity.
606    ///
607    /// `flood-opacity` in the SVG.
608    pub fn opacity(&self) -> Opacity {
609        self.opacity
610    }
611}
612
613/// A flood filter primitive.
614///
615/// `feFlood` element in the SVG.
616#[derive(Clone, Copy, Debug)]
617pub struct Flood {
618    pub(crate) color: Color,
619    pub(crate) opacity: Opacity,
620}
621
622impl Flood {
623    /// A flood color.
624    ///
625    /// `flood-color` in the SVG.
626    pub fn color(&self) -> Color {
627        self.color
628    }
629
630    /// A flood opacity.
631    ///
632    /// `flood-opacity` in the SVG.
633    pub fn opacity(&self) -> Opacity {
634        self.opacity
635    }
636}
637
638/// A Gaussian blur filter primitive.
639///
640/// `feGaussianBlur` element in the SVG.
641#[derive(Clone, Debug)]
642pub struct GaussianBlur {
643    pub(crate) input: Input,
644    pub(crate) std_dev_x: PositiveF32,
645    pub(crate) std_dev_y: PositiveF32,
646}
647
648impl GaussianBlur {
649    /// Identifies input for the given filter primitive.
650    ///
651    /// `in` in the SVG.
652    pub fn input(&self) -> &Input {
653        &self.input
654    }
655
656    /// A standard deviation along the X-axis.
657    ///
658    /// `stdDeviation` in the SVG.
659    pub fn std_dev_x(&self) -> PositiveF32 {
660        self.std_dev_x
661    }
662
663    /// A standard deviation along the Y-axis.
664    ///
665    /// `stdDeviation` in the SVG.
666    pub fn std_dev_y(&self) -> PositiveF32 {
667        self.std_dev_y
668    }
669}
670
671/// An image filter primitive.
672///
673/// `feImage` element in the SVG.
674#[derive(Clone, Debug)]
675pub struct Image {
676    pub(crate) root: Group,
677}
678
679impl Image {
680    /// `feImage` children.
681    pub fn root(&self) -> &Group {
682        &self.root
683    }
684}
685
686/// A diffuse lighting filter primitive.
687///
688/// `feDiffuseLighting` element in the SVG.
689#[derive(Clone, Debug)]
690pub struct DiffuseLighting {
691    pub(crate) input: Input,
692    pub(crate) surface_scale: f32,
693    pub(crate) diffuse_constant: f32,
694    pub(crate) lighting_color: Color,
695    pub(crate) light_source: LightSource,
696}
697
698impl DiffuseLighting {
699    /// Identifies input for the given filter primitive.
700    ///
701    /// `in` in the SVG.
702    pub fn input(&self) -> &Input {
703        &self.input
704    }
705
706    /// A surface scale.
707    ///
708    /// `surfaceScale` in the SVG.
709    pub fn surface_scale(&self) -> f32 {
710        self.surface_scale
711    }
712
713    /// A diffuse constant.
714    ///
715    /// `diffuseConstant` in the SVG.
716    pub fn diffuse_constant(&self) -> f32 {
717        self.diffuse_constant
718    }
719
720    /// A lighting color.
721    ///
722    /// `lighting-color` in the SVG.
723    pub fn lighting_color(&self) -> Color {
724        self.lighting_color
725    }
726
727    /// A light source.
728    pub fn light_source(&self) -> LightSource {
729        self.light_source
730    }
731}
732
733/// A specular lighting filter primitive.
734///
735/// `feSpecularLighting` element in the SVG.
736#[derive(Clone, Debug)]
737pub struct SpecularLighting {
738    pub(crate) input: Input,
739    pub(crate) surface_scale: f32,
740    pub(crate) specular_constant: f32,
741    pub(crate) specular_exponent: f32,
742    pub(crate) lighting_color: Color,
743    pub(crate) light_source: LightSource,
744}
745
746impl SpecularLighting {
747    /// Identifies input for the given filter primitive.
748    ///
749    /// `in` in the SVG.
750    pub fn input(&self) -> &Input {
751        &self.input
752    }
753
754    /// A surface scale.
755    ///
756    /// `surfaceScale` in the SVG.
757    pub fn surface_scale(&self) -> f32 {
758        self.surface_scale
759    }
760
761    /// A specular constant.
762    ///
763    /// `specularConstant` in the SVG.
764    pub fn specular_constant(&self) -> f32 {
765        self.specular_constant
766    }
767
768    /// A specular exponent.
769    ///
770    /// Should be in 1..128 range.
771    ///
772    /// `specularExponent` in the SVG.
773    pub fn specular_exponent(&self) -> f32 {
774        self.specular_exponent
775    }
776
777    /// A lighting color.
778    ///
779    /// `lighting-color` in the SVG.
780    pub fn lighting_color(&self) -> Color {
781        self.lighting_color
782    }
783
784    /// A light source.
785    pub fn light_source(&self) -> LightSource {
786        self.light_source
787    }
788}
789
790/// A light source kind.
791#[allow(missing_docs)]
792#[derive(Clone, Copy, Debug)]
793pub enum LightSource {
794    DistantLight(DistantLight),
795    PointLight(PointLight),
796    SpotLight(SpotLight),
797}
798
799/// A distant light source.
800///
801/// `feDistantLight` element in the SVG.
802#[derive(Clone, Copy, Debug)]
803pub struct DistantLight {
804    /// Direction angle for the light source on the XY plane (clockwise),
805    /// in degrees from the x axis.
806    ///
807    /// `azimuth` in the SVG.
808    pub azimuth: f32,
809
810    /// Direction angle for the light source from the XY plane towards the z axis, in degrees.
811    ///
812    /// `elevation` in the SVG.
813    pub elevation: f32,
814}
815
816/// A point light source.
817///
818/// `fePointLight` element in the SVG.
819#[derive(Clone, Copy, Debug)]
820pub struct PointLight {
821    /// X location for the light source.
822    ///
823    /// `x` in the SVG.
824    pub x: f32,
825
826    /// Y location for the light source.
827    ///
828    /// `y` in the SVG.
829    pub y: f32,
830
831    /// Z location for the light source.
832    ///
833    /// `z` in the SVG.
834    pub z: f32,
835}
836
837/// A spot light source.
838///
839/// `feSpotLight` element in the SVG.
840#[derive(Clone, Copy, Debug)]
841pub struct SpotLight {
842    /// X location for the light source.
843    ///
844    /// `x` in the SVG.
845    pub x: f32,
846
847    /// Y location for the light source.
848    ///
849    /// `y` in the SVG.
850    pub y: f32,
851
852    /// Z location for the light source.
853    ///
854    /// `z` in the SVG.
855    pub z: f32,
856
857    /// X point at which the light source is pointing.
858    ///
859    /// `pointsAtX` in the SVG.
860    pub points_at_x: f32,
861
862    /// Y point at which the light source is pointing.
863    ///
864    /// `pointsAtY` in the SVG.
865    pub points_at_y: f32,
866
867    /// Z point at which the light source is pointing.
868    ///
869    /// `pointsAtZ` in the SVG.
870    pub points_at_z: f32,
871
872    /// Exponent value controlling the focus for the light source.
873    ///
874    /// `specularExponent` in the SVG.
875    pub specular_exponent: PositiveF32,
876
877    /// A limiting cone which restricts the region where the light is projected.
878    ///
879    /// `limitingConeAngle` in the SVG.
880    pub limiting_cone_angle: Option<f32>,
881}
882
883/// A merge filter primitive.
884///
885/// `feMerge` element in the SVG.
886#[derive(Clone, Debug)]
887pub struct Merge {
888    pub(crate) inputs: Vec<Input>,
889}
890
891impl Merge {
892    /// List of input layers that should be merged.
893    ///
894    /// List of `feMergeNode`'s in the SVG.
895    pub fn inputs(&self) -> &[Input] {
896        &self.inputs
897    }
898}
899
900/// A morphology filter primitive.
901///
902/// `feMorphology` element in the SVG.
903#[derive(Clone, Debug)]
904pub struct Morphology {
905    pub(crate) input: Input,
906    pub(crate) operator: MorphologyOperator,
907    pub(crate) radius_x: PositiveF32,
908    pub(crate) radius_y: PositiveF32,
909}
910
911impl Morphology {
912    /// Identifies input for the given filter primitive.
913    ///
914    /// `in` in the SVG.
915    pub fn input(&self) -> &Input {
916        &self.input
917    }
918
919    /// A filter operator.
920    ///
921    /// `operator` in the SVG.
922    pub fn operator(&self) -> MorphologyOperator {
923        self.operator
924    }
925
926    /// A filter radius along the X-axis.
927    ///
928    /// A value of zero disables the effect of the given filter primitive.
929    ///
930    /// `radius` in the SVG.
931    pub fn radius_x(&self) -> PositiveF32 {
932        self.radius_x
933    }
934
935    /// A filter radius along the Y-axis.
936    ///
937    /// A value of zero disables the effect of the given filter primitive.
938    ///
939    /// `radius` in the SVG.
940    pub fn radius_y(&self) -> PositiveF32 {
941        self.radius_y
942    }
943}
944
945/// A morphology operation.
946#[allow(missing_docs)]
947#[derive(Clone, Copy, PartialEq, Debug)]
948pub enum MorphologyOperator {
949    Erode,
950    Dilate,
951}
952
953/// An offset filter primitive.
954///
955/// `feOffset` element in the SVG.
956#[derive(Clone, Debug)]
957pub struct Offset {
958    pub(crate) input: Input,
959    pub(crate) dx: f32,
960    pub(crate) dy: f32,
961}
962
963impl Offset {
964    /// Identifies input for the given filter primitive.
965    ///
966    /// `in` in the SVG.
967    pub fn input(&self) -> &Input {
968        &self.input
969    }
970
971    /// The amount to offset the input graphic along the X-axis.
972    pub fn dx(&self) -> f32 {
973        self.dx
974    }
975
976    /// The amount to offset the input graphic along the Y-axis.
977    pub fn dy(&self) -> f32 {
978        self.dy
979    }
980}
981
982/// A tile filter primitive.
983///
984/// `feTile` element in the SVG.
985#[derive(Clone, Debug)]
986pub struct Tile {
987    pub(crate) input: Input,
988}
989
990impl Tile {
991    /// Identifies input for the given filter primitive.
992    ///
993    /// `in` in the SVG.
994    pub fn input(&self) -> &Input {
995        &self.input
996    }
997}
998
999/// A turbulence generation filter primitive.
1000///
1001/// `feTurbulence` element in the SVG.
1002#[derive(Clone, Copy, Debug)]
1003pub struct Turbulence {
1004    pub(crate) base_frequency_x: PositiveF32,
1005    pub(crate) base_frequency_y: PositiveF32,
1006    pub(crate) num_octaves: u32,
1007    pub(crate) seed: i32,
1008    pub(crate) stitch_tiles: bool,
1009    pub(crate) kind: TurbulenceKind,
1010}
1011
1012impl Turbulence {
1013    /// Identifies the base frequency for the noise function.
1014    ///
1015    /// `baseFrequency` in the SVG.
1016    pub fn base_frequency_x(&self) -> PositiveF32 {
1017        self.base_frequency_x
1018    }
1019
1020    /// Identifies the base frequency for the noise function.
1021    ///
1022    /// `baseFrequency` in the SVG.
1023    pub fn base_frequency_y(&self) -> PositiveF32 {
1024        self.base_frequency_y
1025    }
1026
1027    /// Identifies the number of octaves for the noise function.
1028    ///
1029    /// `numOctaves` in the SVG.
1030    pub fn num_octaves(&self) -> u32 {
1031        self.num_octaves
1032    }
1033
1034    /// The starting number for the pseudo random number generator.
1035    ///
1036    /// `seed` in the SVG.
1037    pub fn seed(&self) -> i32 {
1038        self.seed
1039    }
1040
1041    /// Smooth transitions at the border of tiles.
1042    ///
1043    /// `stitchTiles` in the SVG.
1044    pub fn stitch_tiles(&self) -> bool {
1045        self.stitch_tiles
1046    }
1047
1048    /// Indicates whether the filter primitive should perform a noise or turbulence function.
1049    ///
1050    /// `type` in the SVG.
1051    pub fn kind(&self) -> TurbulenceKind {
1052        self.kind
1053    }
1054}
1055
1056/// A turbulence kind for the `feTurbulence` filter.
1057#[allow(missing_docs)]
1058#[derive(Clone, Copy, PartialEq, Debug)]
1059pub enum TurbulenceKind {
1060    FractalNoise,
1061    Turbulence,
1062}