usvg/tree/
filter.rs

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