1#![allow(missing_docs)]
5
6use strict_num::PositiveF32;
9
10use crate::{BlendMode, Color, Group, NonEmptyString, NonZeroF32, NonZeroRect, Opacity};
11
12#[derive(Debug)]
16pub struct Filter {
17 pub id: NonEmptyString,
18 pub rect: NonZeroRect,
19 pub primitives: Vec<Primitive>,
20}
21
22impl Filter {
23 pub fn id(&self) -> &str {
28 self.id.get()
29 }
30
31 pub fn rect(&self) -> NonZeroRect {
35 self.rect
36 }
37
38 pub fn primitives(&self) -> &[Primitive] {
40 &self.primitives
41 }
42}
43
44#[derive(Clone, Debug)]
46pub struct Primitive {
47 pub rect: NonZeroRect,
48 pub color_interpolation: ColorInterpolation,
49 pub result: String,
50 pub kind: Kind,
51}
52
53impl Primitive {
54 pub fn rect(&self) -> NonZeroRect {
58 self.rect
59 }
60
61 pub fn color_interpolation(&self) -> ColorInterpolation {
65 self.color_interpolation
66 }
67
68 pub fn result(&self) -> &str {
72 &self.result
73 }
74
75 pub fn kind(&self) -> &Kind {
77 &self.kind
78 }
79}
80
81#[allow(missing_docs)]
83#[derive(Clone, Debug)]
84pub enum Kind {
85 Blend(Blend),
86 ColorMatrix(ColorMatrix),
87 ComponentTransfer(ComponentTransfer),
88 Composite(Composite),
89 ConvolveMatrix(ConvolveMatrix),
90 DiffuseLighting(DiffuseLighting),
91 DisplacementMap(DisplacementMap),
92 DropShadow(DropShadow),
93 Flood(Flood),
94 GaussianBlur(GaussianBlur),
95 Image(Image),
96 Merge(Merge),
97 Morphology(Morphology),
98 Offset(Offset),
99 SpecularLighting(SpecularLighting),
100 Tile(Tile),
101 Turbulence(Turbulence),
102}
103
104impl Kind {
105 pub fn has_input(&self, input: &Input) -> bool {
107 match self {
108 Kind::Blend(fe) => fe.input1 == *input || fe.input2 == *input,
109 Kind::ColorMatrix(fe) => fe.input == *input,
110 Kind::ComponentTransfer(fe) => fe.input == *input,
111 Kind::Composite(fe) => fe.input1 == *input || fe.input2 == *input,
112 Kind::ConvolveMatrix(fe) => fe.input == *input,
113 Kind::DiffuseLighting(fe) => fe.input == *input,
114 Kind::DisplacementMap(fe) => fe.input1 == *input || fe.input2 == *input,
115 Kind::DropShadow(fe) => fe.input == *input,
116 Kind::Flood(_) => false,
117 Kind::GaussianBlur(fe) => fe.input == *input,
118 Kind::Image(_) => false,
119 Kind::Merge(fe) => fe.inputs.iter().any(|i| i == input),
120 Kind::Morphology(fe) => fe.input == *input,
121 Kind::Offset(fe) => fe.input == *input,
122 Kind::SpecularLighting(fe) => fe.input == *input,
123 Kind::Tile(fe) => fe.input == *input,
124 Kind::Turbulence(_) => false,
125 }
126 }
127}
128
129#[allow(missing_docs)]
131#[derive(Clone, PartialEq, Debug)]
132pub enum Input {
133 SourceGraphic,
134 SourceAlpha,
135 Reference(String),
136}
137
138#[allow(missing_docs)]
142#[derive(Clone, Copy, PartialEq, Debug, Default)]
143pub enum ColorInterpolation {
144 SRGB,
145 #[default]
146 LinearRGB,
147}
148
149#[derive(Clone, Debug)]
153pub struct Blend {
154 pub input1: Input,
155 pub input2: Input,
156 pub mode: BlendMode,
157}
158
159impl Blend {
160 pub fn input1(&self) -> &Input {
164 &self.input1
165 }
166
167 pub fn input2(&self) -> &Input {
171 &self.input2
172 }
173
174 pub fn mode(&self) -> BlendMode {
178 self.mode
179 }
180}
181
182#[derive(Clone, Debug)]
186pub struct ColorMatrix {
187 pub input: Input,
188 pub kind: ColorMatrixKind,
189}
190
191impl ColorMatrix {
192 pub fn input(&self) -> &Input {
196 &self.input
197 }
198
199 pub fn kind(&self) -> &ColorMatrixKind {
203 &self.kind
204 }
205}
206
207#[derive(Clone, Debug)]
209#[allow(missing_docs)]
210pub enum ColorMatrixKind {
211 Matrix(Vec<f32>), Saturate(PositiveF32),
213 HueRotate(f32),
214 LuminanceToAlpha,
215}
216
217impl Default for ColorMatrixKind {
218 fn default() -> Self {
219 ColorMatrixKind::Matrix(vec![
220 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
221 0.0, 1.0, 0.0,
222 ])
223 }
224}
225
226#[derive(Clone, Debug)]
230pub struct ComponentTransfer {
231 pub input: Input,
232 pub func_r: TransferFunction,
233 pub func_g: TransferFunction,
234 pub func_b: TransferFunction,
235 pub func_a: TransferFunction,
236}
237
238impl ComponentTransfer {
239 pub fn input(&self) -> &Input {
243 &self.input
244 }
245
246 pub fn func_r(&self) -> &TransferFunction {
248 &self.func_r
249 }
250
251 pub fn func_g(&self) -> &TransferFunction {
253 &self.func_g
254 }
255
256 pub fn func_b(&self) -> &TransferFunction {
258 &self.func_b
259 }
260
261 pub fn func_a(&self) -> &TransferFunction {
263 &self.func_a
264 }
265}
266
267#[derive(Clone, Debug)]
271pub enum TransferFunction {
272 Identity,
274
275 Table(Vec<f32>),
279
280 Discrete(Vec<f32>),
284
285 #[allow(missing_docs)]
287 Linear { slope: f32, intercept: f32 },
288
289 #[allow(missing_docs)]
291 Gamma {
292 amplitude: f32,
293 exponent: f32,
294 offset: f32,
295 },
296}
297
298#[derive(Clone, Debug)]
302pub struct Composite {
303 pub input1: Input,
304 pub input2: Input,
305 pub operator: CompositeOperator,
306}
307
308impl Composite {
309 pub fn input1(&self) -> &Input {
313 &self.input1
314 }
315
316 pub fn input2(&self) -> &Input {
320 &self.input2
321 }
322
323 pub fn operator(&self) -> CompositeOperator {
327 self.operator
328 }
329}
330
331#[allow(missing_docs)]
333#[derive(Clone, Copy, PartialEq, Debug)]
334pub enum CompositeOperator {
335 Over,
336 In,
337 Out,
338 Atop,
339 Xor,
340 Arithmetic { k1: f32, k2: f32, k3: f32, k4: f32 },
341}
342
343#[derive(Clone, Debug)]
347pub struct ConvolveMatrix {
348 pub input: Input,
349 pub matrix: ConvolveMatrixData,
350 pub divisor: NonZeroF32,
351 pub bias: f32,
352 pub edge_mode: EdgeMode,
353 pub preserve_alpha: bool,
354}
355
356impl ConvolveMatrix {
357 pub fn input(&self) -> &Input {
361 &self.input
362 }
363
364 pub fn matrix(&self) -> &ConvolveMatrixData {
366 &self.matrix
367 }
368
369 pub fn divisor(&self) -> NonZeroF32 {
373 self.divisor
374 }
375
376 pub fn bias(&self) -> f32 {
380 self.bias
381 }
382
383 pub fn edge_mode(&self) -> EdgeMode {
387 self.edge_mode
388 }
389
390 pub fn preserve_alpha(&self) -> bool {
394 self.preserve_alpha
395 }
396}
397
398#[derive(Clone, Debug)]
402pub struct ConvolveMatrixData {
403 pub target_x: u32,
404 pub target_y: u32,
405 pub columns: u32,
406 pub rows: u32,
407 pub data: Vec<f32>,
408}
409
410impl ConvolveMatrixData {
411 pub fn target_x(&self) -> u32 {
415 self.target_x
416 }
417
418 pub fn target_y(&self) -> u32 {
422 self.target_y
423 }
424
425 pub fn columns(&self) -> u32 {
429 self.columns
430 }
431
432 pub fn rows(&self) -> u32 {
436 self.rows
437 }
438
439 pub fn data(&self) -> &[f32] {
441 &self.data
442 }
443}
444
445impl ConvolveMatrixData {
446 pub fn new(
454 target_x: u32,
455 target_y: u32,
456 columns: u32,
457 rows: u32,
458 data: Vec<f32>,
459 ) -> Option<Self> {
460 if (columns * rows) as usize != data.len() || target_x >= columns || target_y >= rows {
461 return None;
462 }
463
464 Some(ConvolveMatrixData {
465 target_x,
466 target_y,
467 columns,
468 rows,
469 data,
470 })
471 }
472
473 pub fn get(&self, x: u32, y: u32) -> f32 {
479 self.data[(y * self.columns + x) as usize]
480 }
481}
482
483#[allow(missing_docs)]
485#[derive(Clone, Copy, PartialEq, Debug)]
486pub enum EdgeMode {
487 None,
488 Duplicate,
489 Wrap,
490}
491
492#[derive(Clone, Debug)]
496pub struct DisplacementMap {
497 pub input1: Input,
498 pub input2: Input,
499 pub scale: f32,
500 pub x_channel_selector: ColorChannel,
501 pub y_channel_selector: ColorChannel,
502}
503
504impl DisplacementMap {
505 pub fn input1(&self) -> &Input {
509 &self.input1
510 }
511
512 pub fn input2(&self) -> &Input {
516 &self.input2
517 }
518
519 pub fn scale(&self) -> f32 {
523 self.scale
524 }
525
526 pub fn x_channel_selector(&self) -> ColorChannel {
530 self.x_channel_selector
531 }
532
533 pub fn y_channel_selector(&self) -> ColorChannel {
537 self.y_channel_selector
538 }
539}
540
541#[allow(missing_docs)]
543#[derive(Clone, Copy, PartialEq, Debug)]
544pub enum ColorChannel {
545 R,
546 G,
547 B,
548 A,
549}
550
551#[derive(Clone, Debug)]
557pub struct DropShadow {
558 pub input: Input,
559 pub dx: f32,
560 pub dy: f32,
561 pub std_dev_x: PositiveF32,
562 pub std_dev_y: PositiveF32,
563 pub color: Color,
564 pub opacity: Opacity,
565}
566
567impl DropShadow {
568 pub fn input(&self) -> &Input {
572 &self.input
573 }
574
575 pub fn dx(&self) -> f32 {
577 self.dx
578 }
579
580 pub fn dy(&self) -> f32 {
582 self.dy
583 }
584
585 pub fn std_dev_x(&self) -> PositiveF32 {
589 self.std_dev_x
590 }
591
592 pub fn std_dev_y(&self) -> PositiveF32 {
596 self.std_dev_y
597 }
598
599 pub fn color(&self) -> Color {
603 self.color
604 }
605
606 pub fn opacity(&self) -> Opacity {
610 self.opacity
611 }
612}
613
614#[derive(Clone, Copy, Debug)]
618pub struct Flood {
619 pub color: Color,
620 pub opacity: Opacity,
621}
622
623impl Flood {
624 pub fn color(&self) -> Color {
628 self.color
629 }
630
631 pub fn opacity(&self) -> Opacity {
635 self.opacity
636 }
637}
638
639#[derive(Clone, Debug)]
643pub struct GaussianBlur {
644 pub input: Input,
645 pub std_dev_x: PositiveF32,
646 pub std_dev_y: PositiveF32,
647}
648
649impl GaussianBlur {
650 pub fn input(&self) -> &Input {
654 &self.input
655 }
656
657 pub fn std_dev_x(&self) -> PositiveF32 {
661 self.std_dev_x
662 }
663
664 pub fn std_dev_y(&self) -> PositiveF32 {
668 self.std_dev_y
669 }
670}
671
672#[derive(Clone, Debug)]
676pub struct Image {
677 pub root: Group,
678}
679
680impl Image {
681 pub fn root(&self) -> &Group {
683 &self.root
684 }
685}
686
687#[derive(Clone, Debug)]
691pub struct DiffuseLighting {
692 pub input: Input,
693 pub surface_scale: f32,
694 pub diffuse_constant: f32,
695 pub lighting_color: Color,
696 pub light_source: LightSource,
697}
698
699impl DiffuseLighting {
700 pub fn input(&self) -> &Input {
704 &self.input
705 }
706
707 pub fn surface_scale(&self) -> f32 {
711 self.surface_scale
712 }
713
714 pub fn diffuse_constant(&self) -> f32 {
718 self.diffuse_constant
719 }
720
721 pub fn lighting_color(&self) -> Color {
725 self.lighting_color
726 }
727
728 pub fn light_source(&self) -> LightSource {
730 self.light_source
731 }
732}
733
734#[derive(Clone, Debug)]
738pub struct SpecularLighting {
739 pub input: Input,
740 pub surface_scale: f32,
741 pub specular_constant: f32,
742 pub specular_exponent: f32,
743 pub lighting_color: Color,
744 pub light_source: LightSource,
745}
746
747impl SpecularLighting {
748 pub fn input(&self) -> &Input {
752 &self.input
753 }
754
755 pub fn surface_scale(&self) -> f32 {
759 self.surface_scale
760 }
761
762 pub fn specular_constant(&self) -> f32 {
766 self.specular_constant
767 }
768
769 pub fn specular_exponent(&self) -> f32 {
775 self.specular_exponent
776 }
777
778 pub fn lighting_color(&self) -> Color {
782 self.lighting_color
783 }
784
785 pub fn light_source(&self) -> LightSource {
787 self.light_source
788 }
789}
790
791#[allow(missing_docs)]
793#[derive(Clone, Copy, Debug)]
794pub enum LightSource {
795 DistantLight(DistantLight),
796 PointLight(PointLight),
797 SpotLight(SpotLight),
798}
799
800#[derive(Clone, Copy, Debug)]
804pub struct DistantLight {
805 pub azimuth: f32,
810
811 pub elevation: f32,
815}
816
817#[derive(Clone, Copy, Debug)]
821pub struct PointLight {
822 pub x: f32,
826
827 pub y: f32,
831
832 pub z: f32,
836}
837
838#[derive(Clone, Copy, Debug)]
842pub struct SpotLight {
843 pub x: f32,
847
848 pub y: f32,
852
853 pub z: f32,
857
858 pub points_at_x: f32,
862
863 pub points_at_y: f32,
867
868 pub points_at_z: f32,
872
873 pub specular_exponent: PositiveF32,
877
878 pub limiting_cone_angle: Option<f32>,
882}
883
884#[derive(Clone, Debug)]
888pub struct Merge {
889 pub inputs: Vec<Input>,
890}
891
892impl Merge {
893 pub fn inputs(&self) -> &[Input] {
897 &self.inputs
898 }
899}
900
901#[derive(Clone, Debug)]
905pub struct Morphology {
906 pub input: Input,
907 pub operator: MorphologyOperator,
908 pub radius_x: PositiveF32,
909 pub radius_y: PositiveF32,
910}
911
912impl Morphology {
913 pub fn input(&self) -> &Input {
917 &self.input
918 }
919
920 pub fn operator(&self) -> MorphologyOperator {
924 self.operator
925 }
926
927 pub fn radius_x(&self) -> PositiveF32 {
933 self.radius_x
934 }
935
936 pub fn radius_y(&self) -> PositiveF32 {
942 self.radius_y
943 }
944}
945
946#[allow(missing_docs)]
948#[derive(Clone, Copy, PartialEq, Debug)]
949pub enum MorphologyOperator {
950 Erode,
951 Dilate,
952}
953
954#[derive(Clone, Debug)]
958pub struct Offset {
959 pub input: Input,
960 pub dx: f32,
961 pub dy: f32,
962}
963
964impl Offset {
965 pub fn input(&self) -> &Input {
969 &self.input
970 }
971
972 pub fn dx(&self) -> f32 {
974 self.dx
975 }
976
977 pub fn dy(&self) -> f32 {
979 self.dy
980 }
981}
982
983#[derive(Clone, Debug)]
987pub struct Tile {
988 pub input: Input,
989}
990
991impl Tile {
992 pub fn input(&self) -> &Input {
996 &self.input
997 }
998}
999
1000#[derive(Clone, Copy, Debug)]
1004pub struct Turbulence {
1005 pub base_frequency_x: PositiveF32,
1006 pub base_frequency_y: PositiveF32,
1007 pub num_octaves: u32,
1008 pub seed: i32,
1009 pub stitch_tiles: bool,
1010 pub kind: TurbulenceKind,
1011}
1012
1013impl Turbulence {
1014 pub fn base_frequency_x(&self) -> PositiveF32 {
1018 self.base_frequency_x
1019 }
1020
1021 pub fn base_frequency_y(&self) -> PositiveF32 {
1025 self.base_frequency_y
1026 }
1027
1028 pub fn num_octaves(&self) -> u32 {
1032 self.num_octaves
1033 }
1034
1035 pub fn seed(&self) -> i32 {
1039 self.seed
1040 }
1041
1042 pub fn stitch_tiles(&self) -> bool {
1046 self.stitch_tiles
1047 }
1048
1049 pub fn kind(&self) -> TurbulenceKind {
1053 self.kind
1054 }
1055}
1056
1057#[allow(missing_docs)]
1059#[derive(Clone, Copy, PartialEq, Debug)]
1060pub enum TurbulenceKind {
1061 FractalNoise,
1062 Turbulence,
1063}