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(ref fe) => fe.input1 == *input || fe.input2 == *input,
107            Kind::ColorMatrix(ref fe) => fe.input == *input,
108            Kind::ComponentTransfer(ref fe) => fe.input == *input,
109            Kind::Composite(ref fe) => fe.input1 == *input || fe.input2 == *input,
110            Kind::ConvolveMatrix(ref fe) => fe.input == *input,
111            Kind::DiffuseLighting(ref fe) => fe.input == *input,
112            Kind::DisplacementMap(ref fe) => fe.input1 == *input || fe.input2 == *input,
113            Kind::DropShadow(ref fe) => fe.input == *input,
114            Kind::Flood(_) => false,
115            Kind::GaussianBlur(ref fe) => fe.input == *input,
116            Kind::Image(_) => false,
117            Kind::Merge(ref fe) => fe.inputs.iter().any(|i| i == input),
118            Kind::Morphology(ref fe) => fe.input == *input,
119            Kind::Offset(ref fe) => fe.input == *input,
120            Kind::SpecularLighting(ref fe) => fe.input == *input,
121            Kind::Tile(ref 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    Arithmetic { k1: f32, k2: f32, k3: f32, k4: f32 },
339}
340
341/// A matrix convolution filter primitive.
342///
343/// `feConvolveMatrix` element in the SVG.
344#[derive(Clone, Debug)]
345pub struct ConvolveMatrix {
346    pub(crate) input: Input,
347    pub(crate) matrix: ConvolveMatrixData,
348    pub(crate) divisor: NonZeroF32,
349    pub(crate) bias: f32,
350    pub(crate) edge_mode: EdgeMode,
351    pub(crate) preserve_alpha: bool,
352}
353
354impl ConvolveMatrix {
355    /// Identifies input for the given filter primitive.
356    ///
357    /// `in` in the SVG.
358    pub fn input(&self) -> &Input {
359        &self.input
360    }
361
362    /// A convolve matrix.
363    pub fn matrix(&self) -> &ConvolveMatrixData {
364        &self.matrix
365    }
366
367    /// A matrix divisor.
368    ///
369    /// `divisor` in the SVG.
370    pub fn divisor(&self) -> NonZeroF32 {
371        self.divisor
372    }
373
374    /// A kernel matrix bias.
375    ///
376    /// `bias` in the SVG.
377    pub fn bias(&self) -> f32 {
378        self.bias
379    }
380
381    /// An edges processing mode.
382    ///
383    /// `edgeMode` in the SVG.
384    pub fn edge_mode(&self) -> EdgeMode {
385        self.edge_mode
386    }
387
388    /// An alpha preserving flag.
389    ///
390    /// `preserveAlpha` in the SVG.
391    pub fn preserve_alpha(&self) -> bool {
392        self.preserve_alpha
393    }
394}
395
396/// A convolve matrix representation.
397///
398/// Used primarily by [`ConvolveMatrix`].
399#[derive(Clone, Debug)]
400pub struct ConvolveMatrixData {
401    pub(crate) target_x: u32,
402    pub(crate) target_y: u32,
403    pub(crate) columns: u32,
404    pub(crate) rows: u32,
405    pub(crate) data: Vec<f32>,
406}
407
408impl ConvolveMatrixData {
409    /// Returns a matrix's X target.
410    ///
411    /// `targetX` in the SVG.
412    pub fn target_x(&self) -> u32 {
413        self.target_x
414    }
415
416    /// Returns a matrix's Y target.
417    ///
418    /// `targetY` in the SVG.
419    pub fn target_y(&self) -> u32 {
420        self.target_y
421    }
422
423    /// Returns a number of columns in the matrix.
424    ///
425    /// Part of the `order` attribute in the SVG.
426    pub fn columns(&self) -> u32 {
427        self.columns
428    }
429
430    /// Returns a number of rows in the matrix.
431    ///
432    /// Part of the `order` attribute in the SVG.
433    pub fn rows(&self) -> u32 {
434        self.rows
435    }
436
437    /// The actual matrix.
438    pub fn data(&self) -> &[f32] {
439        &self.data
440    }
441}
442
443impl ConvolveMatrixData {
444    /// Creates a new `ConvolveMatrixData`.
445    ///
446    /// Returns `None` when:
447    ///
448    /// - `columns` * `rows` != `data.len()`
449    /// - `target_x` >= `columns`
450    /// - `target_y` >= `rows`
451    pub(crate) fn new(
452        target_x: u32,
453        target_y: u32,
454        columns: u32,
455        rows: u32,
456        data: Vec<f32>,
457    ) -> Option<Self> {
458        if (columns * rows) as usize != data.len() || target_x >= columns || target_y >= rows {
459            return None;
460        }
461
462        Some(ConvolveMatrixData {
463            target_x,
464            target_y,
465            columns,
466            rows,
467            data,
468        })
469    }
470
471    /// Returns a matrix value at the specified position.
472    ///
473    /// # Panics
474    ///
475    /// - When position is out of bounds.
476    pub fn get(&self, x: u32, y: u32) -> f32 {
477        self.data[(y * self.columns + x) as usize]
478    }
479}
480
481/// An edges processing mode.
482#[allow(missing_docs)]
483#[derive(Clone, Copy, PartialEq, Debug)]
484pub enum EdgeMode {
485    None,
486    Duplicate,
487    Wrap,
488}
489
490/// A displacement map filter primitive.
491///
492/// `feDisplacementMap` element in the SVG.
493#[derive(Clone, Debug)]
494pub struct DisplacementMap {
495    pub(crate) input1: Input,
496    pub(crate) input2: Input,
497    pub(crate) scale: f32,
498    pub(crate) x_channel_selector: ColorChannel,
499    pub(crate) y_channel_selector: ColorChannel,
500}
501
502impl DisplacementMap {
503    /// Identifies input for the given filter primitive.
504    ///
505    /// `in` in the SVG.
506    pub fn input1(&self) -> &Input {
507        &self.input1
508    }
509
510    /// Identifies input for the given filter primitive.
511    ///
512    /// `in2` in the SVG.
513    pub fn input2(&self) -> &Input {
514        &self.input2
515    }
516
517    /// Scale factor.
518    ///
519    /// `scale` in the SVG.
520    pub fn scale(&self) -> f32 {
521        self.scale
522    }
523
524    /// Indicates a source color channel along the X-axis.
525    ///
526    /// `xChannelSelector` in the SVG.
527    pub fn x_channel_selector(&self) -> ColorChannel {
528        self.x_channel_selector
529    }
530
531    /// Indicates a source color channel along the Y-axis.
532    ///
533    /// `yChannelSelector` in the SVG.
534    pub fn y_channel_selector(&self) -> ColorChannel {
535        self.y_channel_selector
536    }
537}
538
539/// A color channel.
540#[allow(missing_docs)]
541#[derive(Clone, Copy, PartialEq, Debug)]
542pub enum ColorChannel {
543    R,
544    G,
545    B,
546    A,
547}
548
549/// A drop shadow filter primitive.
550///
551/// This is essentially `feGaussianBlur`, `feOffset` and `feFlood` joined together.
552///
553/// `feDropShadow` element in the SVG.
554#[derive(Clone, Debug)]
555pub struct DropShadow {
556    pub(crate) input: Input,
557    pub(crate) dx: f32,
558    pub(crate) dy: f32,
559    pub(crate) std_dev_x: PositiveF32,
560    pub(crate) std_dev_y: PositiveF32,
561    pub(crate) color: Color,
562    pub(crate) opacity: Opacity,
563}
564
565impl DropShadow {
566    /// Identifies input for the given filter primitive.
567    ///
568    /// `in` in the SVG.
569    pub fn input(&self) -> &Input {
570        &self.input
571    }
572
573    /// The amount to offset the input graphic along the X-axis.
574    pub fn dx(&self) -> f32 {
575        self.dx
576    }
577
578    /// The amount to offset the input graphic along the Y-axis.
579    pub fn dy(&self) -> f32 {
580        self.dy
581    }
582
583    /// A standard deviation along the X-axis.
584    ///
585    /// `stdDeviation` in the SVG.
586    pub fn std_dev_x(&self) -> PositiveF32 {
587        self.std_dev_x
588    }
589
590    /// A standard deviation along the Y-axis.
591    ///
592    /// `stdDeviation` in the SVG.
593    pub fn std_dev_y(&self) -> PositiveF32 {
594        self.std_dev_y
595    }
596
597    /// A flood color.
598    ///
599    /// `flood-color` in the SVG.
600    pub fn color(&self) -> Color {
601        self.color
602    }
603
604    /// A flood opacity.
605    ///
606    /// `flood-opacity` in the SVG.
607    pub fn opacity(&self) -> Opacity {
608        self.opacity
609    }
610}
611
612/// A flood filter primitive.
613///
614/// `feFlood` element in the SVG.
615#[derive(Clone, Copy, Debug)]
616pub struct Flood {
617    pub(crate) color: Color,
618    pub(crate) opacity: Opacity,
619}
620
621impl Flood {
622    /// A flood color.
623    ///
624    /// `flood-color` in the SVG.
625    pub fn color(&self) -> Color {
626        self.color
627    }
628
629    /// A flood opacity.
630    ///
631    /// `flood-opacity` in the SVG.
632    pub fn opacity(&self) -> Opacity {
633        self.opacity
634    }
635}
636
637/// A Gaussian blur filter primitive.
638///
639/// `feGaussianBlur` element in the SVG.
640#[derive(Clone, Debug)]
641pub struct GaussianBlur {
642    pub(crate) input: Input,
643    pub(crate) std_dev_x: PositiveF32,
644    pub(crate) std_dev_y: PositiveF32,
645}
646
647impl GaussianBlur {
648    /// Identifies input for the given filter primitive.
649    ///
650    /// `in` in the SVG.
651    pub fn input(&self) -> &Input {
652        &self.input
653    }
654
655    /// A standard deviation along the X-axis.
656    ///
657    /// `stdDeviation` in the SVG.
658    pub fn std_dev_x(&self) -> PositiveF32 {
659        self.std_dev_x
660    }
661
662    /// A standard deviation along the Y-axis.
663    ///
664    /// `stdDeviation` in the SVG.
665    pub fn std_dev_y(&self) -> PositiveF32 {
666        self.std_dev_y
667    }
668}
669
670/// An image filter primitive.
671///
672/// `feImage` element in the SVG.
673#[derive(Clone, Debug)]
674pub struct Image {
675    pub(crate) root: Group,
676}
677
678impl Image {
679    /// `feImage` children.
680    pub fn root(&self) -> &Group {
681        &self.root
682    }
683}
684
685/// A diffuse lighting filter primitive.
686///
687/// `feDiffuseLighting` element in the SVG.
688#[derive(Clone, Debug)]
689pub struct DiffuseLighting {
690    pub(crate) input: Input,
691    pub(crate) surface_scale: f32,
692    pub(crate) diffuse_constant: f32,
693    pub(crate) lighting_color: Color,
694    pub(crate) light_source: LightSource,
695}
696
697impl DiffuseLighting {
698    /// Identifies input for the given filter primitive.
699    ///
700    /// `in` in the SVG.
701    pub fn input(&self) -> &Input {
702        &self.input
703    }
704
705    /// A surface scale.
706    ///
707    /// `surfaceScale` in the SVG.
708    pub fn surface_scale(&self) -> f32 {
709        self.surface_scale
710    }
711
712    /// A diffuse constant.
713    ///
714    /// `diffuseConstant` in the SVG.
715    pub fn diffuse_constant(&self) -> f32 {
716        self.diffuse_constant
717    }
718
719    /// A lighting color.
720    ///
721    /// `lighting-color` in the SVG.
722    pub fn lighting_color(&self) -> Color {
723        self.lighting_color
724    }
725
726    /// A light source.
727    pub fn light_source(&self) -> LightSource {
728        self.light_source
729    }
730}
731
732/// A specular lighting filter primitive.
733///
734/// `feSpecularLighting` element in the SVG.
735#[derive(Clone, Debug)]
736pub struct SpecularLighting {
737    pub(crate) input: Input,
738    pub(crate) surface_scale: f32,
739    pub(crate) specular_constant: f32,
740    pub(crate) specular_exponent: f32,
741    pub(crate) lighting_color: Color,
742    pub(crate) light_source: LightSource,
743}
744
745impl SpecularLighting {
746    /// Identifies input for the given filter primitive.
747    ///
748    /// `in` in the SVG.
749    pub fn input(&self) -> &Input {
750        &self.input
751    }
752
753    /// A surface scale.
754    ///
755    /// `surfaceScale` in the SVG.
756    pub fn surface_scale(&self) -> f32 {
757        self.surface_scale
758    }
759
760    /// A specular constant.
761    ///
762    /// `specularConstant` in the SVG.
763    pub fn specular_constant(&self) -> f32 {
764        self.specular_constant
765    }
766
767    /// A specular exponent.
768    ///
769    /// Should be in 1..128 range.
770    ///
771    /// `specularExponent` in the SVG.
772    pub fn specular_exponent(&self) -> f32 {
773        self.specular_exponent
774    }
775
776    /// A lighting color.
777    ///
778    /// `lighting-color` in the SVG.
779    pub fn lighting_color(&self) -> Color {
780        self.lighting_color
781    }
782
783    /// A light source.
784    pub fn light_source(&self) -> LightSource {
785        self.light_source
786    }
787}
788
789/// A light source kind.
790#[allow(missing_docs)]
791#[derive(Clone, Copy, Debug)]
792pub enum LightSource {
793    DistantLight(DistantLight),
794    PointLight(PointLight),
795    SpotLight(SpotLight),
796}
797
798/// A distant light source.
799///
800/// `feDistantLight` element in the SVG.
801#[derive(Clone, Copy, Debug)]
802pub struct DistantLight {
803    /// Direction angle for the light source on the XY plane (clockwise),
804    /// in degrees from the x axis.
805    ///
806    /// `azimuth` in the SVG.
807    pub azimuth: f32,
808
809    /// Direction angle for the light source from the XY plane towards the z axis, in degrees.
810    ///
811    /// `elevation` in the SVG.
812    pub elevation: f32,
813}
814
815/// A point light source.
816///
817/// `fePointLight` element in the SVG.
818#[derive(Clone, Copy, Debug)]
819pub struct PointLight {
820    /// X location for the light source.
821    ///
822    /// `x` in the SVG.
823    pub x: f32,
824
825    /// Y location for the light source.
826    ///
827    /// `y` in the SVG.
828    pub y: f32,
829
830    /// Z location for the light source.
831    ///
832    /// `z` in the SVG.
833    pub z: f32,
834}
835
836/// A spot light source.
837///
838/// `feSpotLight` element in the SVG.
839#[derive(Clone, Copy, Debug)]
840pub struct SpotLight {
841    /// X location for the light source.
842    ///
843    /// `x` in the SVG.
844    pub x: f32,
845
846    /// Y location for the light source.
847    ///
848    /// `y` in the SVG.
849    pub y: f32,
850
851    /// Z location for the light source.
852    ///
853    /// `z` in the SVG.
854    pub z: f32,
855
856    /// X point at which the light source is pointing.
857    ///
858    /// `pointsAtX` in the SVG.
859    pub points_at_x: f32,
860
861    /// Y point at which the light source is pointing.
862    ///
863    /// `pointsAtY` in the SVG.
864    pub points_at_y: f32,
865
866    /// Z point at which the light source is pointing.
867    ///
868    /// `pointsAtZ` in the SVG.
869    pub points_at_z: f32,
870
871    /// Exponent value controlling the focus for the light source.
872    ///
873    /// `specularExponent` in the SVG.
874    pub specular_exponent: PositiveF32,
875
876    /// A limiting cone which restricts the region where the light is projected.
877    ///
878    /// `limitingConeAngle` in the SVG.
879    pub limiting_cone_angle: Option<f32>,
880}
881
882/// A merge filter primitive.
883///
884/// `feMerge` element in the SVG.
885#[derive(Clone, Debug)]
886pub struct Merge {
887    pub(crate) inputs: Vec<Input>,
888}
889
890impl Merge {
891    /// List of input layers that should be merged.
892    ///
893    /// List of `feMergeNode`'s in the SVG.
894    pub fn inputs(&self) -> &[Input] {
895        &self.inputs
896    }
897}
898
899/// A morphology filter primitive.
900///
901/// `feMorphology` element in the SVG.
902#[derive(Clone, Debug)]
903pub struct Morphology {
904    pub(crate) input: Input,
905    pub(crate) operator: MorphologyOperator,
906    pub(crate) radius_x: PositiveF32,
907    pub(crate) radius_y: PositiveF32,
908}
909
910impl Morphology {
911    /// Identifies input for the given filter primitive.
912    ///
913    /// `in` in the SVG.
914    pub fn input(&self) -> &Input {
915        &self.input
916    }
917
918    /// A filter operator.
919    ///
920    /// `operator` in the SVG.
921    pub fn operator(&self) -> MorphologyOperator {
922        self.operator
923    }
924
925    /// A filter radius along the X-axis.
926    ///
927    /// A value of zero disables the effect of the given filter primitive.
928    ///
929    /// `radius` in the SVG.
930    pub fn radius_x(&self) -> PositiveF32 {
931        self.radius_x
932    }
933
934    /// A filter radius along the Y-axis.
935    ///
936    /// A value of zero disables the effect of the given filter primitive.
937    ///
938    /// `radius` in the SVG.
939    pub fn radius_y(&self) -> PositiveF32 {
940        self.radius_y
941    }
942}
943
944/// A morphology operation.
945#[allow(missing_docs)]
946#[derive(Clone, Copy, PartialEq, Debug)]
947pub enum MorphologyOperator {
948    Erode,
949    Dilate,
950}
951
952/// An offset filter primitive.
953///
954/// `feOffset` element in the SVG.
955#[derive(Clone, Debug)]
956pub struct Offset {
957    pub(crate) input: Input,
958    pub(crate) dx: f32,
959    pub(crate) dy: f32,
960}
961
962impl Offset {
963    /// Identifies input for the given filter primitive.
964    ///
965    /// `in` in the SVG.
966    pub fn input(&self) -> &Input {
967        &self.input
968    }
969
970    /// The amount to offset the input graphic along the X-axis.
971    pub fn dx(&self) -> f32 {
972        self.dx
973    }
974
975    /// The amount to offset the input graphic along the Y-axis.
976    pub fn dy(&self) -> f32 {
977        self.dy
978    }
979}
980
981/// A tile filter primitive.
982///
983/// `feTile` element in the SVG.
984#[derive(Clone, Debug)]
985pub struct Tile {
986    pub(crate) input: Input,
987}
988
989impl Tile {
990    /// Identifies input for the given filter primitive.
991    ///
992    /// `in` in the SVG.
993    pub fn input(&self) -> &Input {
994        &self.input
995    }
996}
997
998/// A turbulence generation filter primitive.
999///
1000/// `feTurbulence` element in the SVG.
1001#[derive(Clone, Copy, Debug)]
1002pub struct Turbulence {
1003    pub(crate) base_frequency_x: PositiveF32,
1004    pub(crate) base_frequency_y: PositiveF32,
1005    pub(crate) num_octaves: u32,
1006    pub(crate) seed: i32,
1007    pub(crate) stitch_tiles: bool,
1008    pub(crate) kind: TurbulenceKind,
1009}
1010
1011impl Turbulence {
1012    /// Identifies the base frequency for the noise function.
1013    ///
1014    /// `baseFrequency` in the SVG.
1015    pub fn base_frequency_x(&self) -> PositiveF32 {
1016        self.base_frequency_x
1017    }
1018
1019    /// Identifies the base frequency for the noise function.
1020    ///
1021    /// `baseFrequency` in the SVG.
1022    pub fn base_frequency_y(&self) -> PositiveF32 {
1023        self.base_frequency_y
1024    }
1025
1026    /// Identifies the number of octaves for the noise function.
1027    ///
1028    /// `numOctaves` in the SVG.
1029    pub fn num_octaves(&self) -> u32 {
1030        self.num_octaves
1031    }
1032
1033    /// The starting number for the pseudo random number generator.
1034    ///
1035    /// `seed` in the SVG.
1036    pub fn seed(&self) -> i32 {
1037        self.seed
1038    }
1039
1040    /// Smooth transitions at the border of tiles.
1041    ///
1042    /// `stitchTiles` in the SVG.
1043    pub fn stitch_tiles(&self) -> bool {
1044        self.stitch_tiles
1045    }
1046
1047    /// Indicates whether the filter primitive should perform a noise or turbulence function.
1048    ///
1049    /// `type` in the SVG.
1050    pub fn kind(&self) -> TurbulenceKind {
1051        self.kind
1052    }
1053}
1054
1055/// A turbulence kind for the `feTurbulence` filter.
1056#[allow(missing_docs)]
1057#[derive(Clone, Copy, PartialEq, Debug)]
1058pub enum TurbulenceKind {
1059    FractalNoise,
1060    Turbulence,
1061}