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