1use strict_num::PositiveF32;
8
9use crate::{BlendMode, Color, Group, NonEmptyString, NonZeroF32, NonZeroRect, Opacity};
10
11#[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 pub fn id(&self) -> &str {
27 self.id.get()
28 }
29
30 pub fn rect(&self) -> NonZeroRect {
34 self.rect
35 }
36
37 pub fn primitives(&self) -> &[Primitive] {
39 &self.primitives
40 }
41}
42
43#[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 pub fn rect(&self) -> NonZeroRect {
57 self.rect
58 }
59
60 pub fn color_interpolation(&self) -> ColorInterpolation {
64 self.color_interpolation
65 }
66
67 pub fn result(&self) -> &str {
71 &self.result
72 }
73
74 pub fn kind(&self) -> &Kind {
76 &self.kind
77 }
78}
79
80#[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 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#[allow(missing_docs)]
130#[derive(Clone, PartialEq, Debug)]
131pub enum Input {
132 SourceGraphic,
133 SourceAlpha,
134 Reference(String),
135}
136
137#[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#[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 pub fn input1(&self) -> &Input {
166 &self.input1
167 }
168
169 pub fn input2(&self) -> &Input {
173 &self.input2
174 }
175
176 pub fn mode(&self) -> BlendMode {
180 self.mode
181 }
182}
183
184#[derive(Clone, Debug)]
188pub struct ColorMatrix {
189 pub(crate) input: Input,
190 pub(crate) kind: ColorMatrixKind,
191}
192
193impl ColorMatrix {
194 pub fn input(&self) -> &Input {
198 &self.input
199 }
200
201 pub fn kind(&self) -> &ColorMatrixKind {
205 &self.kind
206 }
207}
208
209#[derive(Clone, Debug)]
211#[allow(missing_docs)]
212pub enum ColorMatrixKind {
213 Matrix(Vec<f32>), 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#[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 pub fn input(&self) -> &Input {
245 &self.input
246 }
247
248 pub fn func_r(&self) -> &TransferFunction {
250 &self.func_r
251 }
252
253 pub fn func_g(&self) -> &TransferFunction {
255 &self.func_g
256 }
257
258 pub fn func_b(&self) -> &TransferFunction {
260 &self.func_b
261 }
262
263 pub fn func_a(&self) -> &TransferFunction {
265 &self.func_a
266 }
267}
268
269#[derive(Clone, Debug)]
273pub enum TransferFunction {
274 Identity,
276
277 Table(Vec<f32>),
281
282 Discrete(Vec<f32>),
286
287 #[allow(missing_docs)]
289 Linear { slope: f32, intercept: f32 },
290
291 #[allow(missing_docs)]
293 Gamma {
294 amplitude: f32,
295 exponent: f32,
296 offset: f32,
297 },
298}
299
300#[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 pub fn input1(&self) -> &Input {
315 &self.input1
316 }
317
318 pub fn input2(&self) -> &Input {
322 &self.input2
323 }
324
325 pub fn operator(&self) -> CompositeOperator {
329 self.operator
330 }
331}
332
333#[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#[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 pub fn input(&self) -> &Input {
363 &self.input
364 }
365
366 pub fn matrix(&self) -> &ConvolveMatrixData {
368 &self.matrix
369 }
370
371 pub fn divisor(&self) -> NonZeroF32 {
375 self.divisor
376 }
377
378 pub fn bias(&self) -> f32 {
382 self.bias
383 }
384
385 pub fn edge_mode(&self) -> EdgeMode {
389 self.edge_mode
390 }
391
392 pub fn preserve_alpha(&self) -> bool {
396 self.preserve_alpha
397 }
398}
399
400#[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 pub fn target_x(&self) -> u32 {
417 self.target_x
418 }
419
420 pub fn target_y(&self) -> u32 {
424 self.target_y
425 }
426
427 pub fn columns(&self) -> u32 {
431 self.columns
432 }
433
434 pub fn rows(&self) -> u32 {
438 self.rows
439 }
440
441 pub fn data(&self) -> &[f32] {
443 &self.data
444 }
445}
446
447impl ConvolveMatrixData {
448 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 pub fn get(&self, x: u32, y: u32) -> f32 {
481 self.data[(y * self.columns + x) as usize]
482 }
483}
484
485#[allow(missing_docs)]
487#[derive(Clone, Copy, PartialEq, Debug)]
488pub enum EdgeMode {
489 None,
490 Duplicate,
491 Wrap,
492}
493
494#[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 pub fn input1(&self) -> &Input {
511 &self.input1
512 }
513
514 pub fn input2(&self) -> &Input {
518 &self.input2
519 }
520
521 pub fn scale(&self) -> f32 {
525 self.scale
526 }
527
528 pub fn x_channel_selector(&self) -> ColorChannel {
532 self.x_channel_selector
533 }
534
535 pub fn y_channel_selector(&self) -> ColorChannel {
539 self.y_channel_selector
540 }
541}
542
543#[allow(missing_docs)]
545#[derive(Clone, Copy, PartialEq, Debug)]
546pub enum ColorChannel {
547 R,
548 G,
549 B,
550 A,
551}
552
553#[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 pub fn input(&self) -> &Input {
574 &self.input
575 }
576
577 pub fn dx(&self) -> f32 {
579 self.dx
580 }
581
582 pub fn dy(&self) -> f32 {
584 self.dy
585 }
586
587 pub fn std_dev_x(&self) -> PositiveF32 {
591 self.std_dev_x
592 }
593
594 pub fn std_dev_y(&self) -> PositiveF32 {
598 self.std_dev_y
599 }
600
601 pub fn color(&self) -> Color {
605 self.color
606 }
607
608 pub fn opacity(&self) -> Opacity {
612 self.opacity
613 }
614}
615
616#[derive(Clone, Copy, Debug)]
620pub struct Flood {
621 pub(crate) color: Color,
622 pub(crate) opacity: Opacity,
623}
624
625impl Flood {
626 pub fn color(&self) -> Color {
630 self.color
631 }
632
633 pub fn opacity(&self) -> Opacity {
637 self.opacity
638 }
639}
640
641#[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 pub fn input(&self) -> &Input {
656 &self.input
657 }
658
659 pub fn std_dev_x(&self) -> PositiveF32 {
663 self.std_dev_x
664 }
665
666 pub fn std_dev_y(&self) -> PositiveF32 {
670 self.std_dev_y
671 }
672}
673
674#[derive(Clone, Debug)]
678pub struct Image {
679 pub(crate) root: Group,
680}
681
682impl Image {
683 pub fn root(&self) -> &Group {
685 &self.root
686 }
687}
688
689#[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 pub fn input(&self) -> &Input {
706 &self.input
707 }
708
709 pub fn surface_scale(&self) -> f32 {
713 self.surface_scale
714 }
715
716 pub fn diffuse_constant(&self) -> f32 {
720 self.diffuse_constant
721 }
722
723 pub fn lighting_color(&self) -> Color {
727 self.lighting_color
728 }
729
730 pub fn light_source(&self) -> LightSource {
732 self.light_source
733 }
734}
735
736#[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 pub fn input(&self) -> &Input {
754 &self.input
755 }
756
757 pub fn surface_scale(&self) -> f32 {
761 self.surface_scale
762 }
763
764 pub fn specular_constant(&self) -> f32 {
768 self.specular_constant
769 }
770
771 pub fn specular_exponent(&self) -> f32 {
777 self.specular_exponent
778 }
779
780 pub fn lighting_color(&self) -> Color {
784 self.lighting_color
785 }
786
787 pub fn light_source(&self) -> LightSource {
789 self.light_source
790 }
791}
792
793#[allow(missing_docs)]
795#[derive(Clone, Copy, Debug)]
796pub enum LightSource {
797 DistantLight(DistantLight),
798 PointLight(PointLight),
799 SpotLight(SpotLight),
800}
801
802#[derive(Clone, Copy, Debug)]
806pub struct DistantLight {
807 pub azimuth: f32,
812
813 pub elevation: f32,
817}
818
819#[derive(Clone, Copy, Debug)]
823pub struct PointLight {
824 pub x: f32,
828
829 pub y: f32,
833
834 pub z: f32,
838}
839
840#[derive(Clone, Copy, Debug)]
844pub struct SpotLight {
845 pub x: f32,
849
850 pub y: f32,
854
855 pub z: f32,
859
860 pub points_at_x: f32,
864
865 pub points_at_y: f32,
869
870 pub points_at_z: f32,
874
875 pub specular_exponent: PositiveF32,
879
880 pub limiting_cone_angle: Option<f32>,
884}
885
886#[derive(Clone, Debug)]
890pub struct Merge {
891 pub(crate) inputs: Vec<Input>,
892}
893
894impl Merge {
895 pub fn inputs(&self) -> &[Input] {
899 &self.inputs
900 }
901}
902
903#[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 pub fn input(&self) -> &Input {
919 &self.input
920 }
921
922 pub fn operator(&self) -> MorphologyOperator {
926 self.operator
927 }
928
929 pub fn radius_x(&self) -> PositiveF32 {
935 self.radius_x
936 }
937
938 pub fn radius_y(&self) -> PositiveF32 {
944 self.radius_y
945 }
946}
947
948#[allow(missing_docs)]
950#[derive(Clone, Copy, PartialEq, Debug)]
951pub enum MorphologyOperator {
952 Erode,
953 Dilate,
954}
955
956#[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 pub fn input(&self) -> &Input {
971 &self.input
972 }
973
974 pub fn dx(&self) -> f32 {
976 self.dx
977 }
978
979 pub fn dy(&self) -> f32 {
981 self.dy
982 }
983}
984
985#[derive(Clone, Debug)]
989pub struct Tile {
990 pub(crate) input: Input,
991}
992
993impl Tile {
994 pub fn input(&self) -> &Input {
998 &self.input
999 }
1000}
1001
1002#[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 pub fn base_frequency_x(&self) -> PositiveF32 {
1020 self.base_frequency_x
1021 }
1022
1023 pub fn base_frequency_y(&self) -> PositiveF32 {
1027 self.base_frequency_y
1028 }
1029
1030 pub fn num_octaves(&self) -> u32 {
1034 self.num_octaves
1035 }
1036
1037 pub fn seed(&self) -> i32 {
1041 self.seed
1042 }
1043
1044 pub fn stitch_tiles(&self) -> bool {
1048 self.stitch_tiles
1049 }
1050
1051 pub fn kind(&self) -> TurbulenceKind {
1055 self.kind
1056 }
1057}
1058
1059#[allow(missing_docs)]
1061#[derive(Clone, Copy, PartialEq, Debug)]
1062pub enum TurbulenceKind {
1063 FractalNoise,
1064 Turbulence,
1065}