Skip to main content

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