1 | // Copyright 2018 the Resvg Authors |
2 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
3 | |
4 | //! SVG filter types. |
5 | |
6 | use strict_num::PositiveF32; |
7 | |
8 | use crate::{BlendMode, Color, Group, NonEmptyString, NonZeroF32, NonZeroRect, Opacity}; |
9 | |
10 | /// A filter element. |
11 | /// |
12 | /// `filter` element in the SVG. |
13 | #[derive (Debug)] |
14 | pub struct Filter { |
15 | pub(crate) id: NonEmptyString, |
16 | pub(crate) rect: NonZeroRect, |
17 | pub(crate) primitives: Vec<Primitive>, |
18 | } |
19 | |
20 | impl 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)] |
44 | pub 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 | |
51 | impl 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)] |
82 | pub 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 | |
102 | impl 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: &Blend) => fe.input1 == *input || fe.input2 == *input, |
107 | Kind::ColorMatrix(ref fe: &ColorMatrix) => fe.input == *input, |
108 | Kind::ComponentTransfer(ref fe: &ComponentTransfer) => fe.input == *input, |
109 | Kind::Composite(ref fe: &Composite) => fe.input1 == *input || fe.input2 == *input, |
110 | Kind::ConvolveMatrix(ref fe: &ConvolveMatrix) => fe.input == *input, |
111 | Kind::DiffuseLighting(ref fe: &DiffuseLighting) => fe.input == *input, |
112 | Kind::DisplacementMap(ref fe: &DisplacementMap) => fe.input1 == *input || fe.input2 == *input, |
113 | Kind::DropShadow(ref fe: &DropShadow) => fe.input == *input, |
114 | Kind::Flood(_) => false, |
115 | Kind::GaussianBlur(ref fe: &GaussianBlur) => fe.input == *input, |
116 | Kind::Image(_) => false, |
117 | Kind::Merge(ref fe: &Merge) => fe.inputs.iter().any(|i: &Input| i == input), |
118 | Kind::Morphology(ref fe: &Morphology) => fe.input == *input, |
119 | Kind::Offset(ref fe: &Offset) => fe.input == *input, |
120 | Kind::SpecularLighting(ref fe: &SpecularLighting) => fe.input == *input, |
121 | Kind::Tile(ref fe: &Tile) => 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)] |
130 | pub 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)] |
141 | pub 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)] |
151 | pub struct Blend { |
152 | pub(crate) input1: Input, |
153 | pub(crate) input2: Input, |
154 | pub(crate) mode: BlendMode, |
155 | } |
156 | |
157 | impl 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)] |
184 | pub struct ColorMatrix { |
185 | pub(crate) input: Input, |
186 | pub(crate) kind: ColorMatrixKind, |
187 | } |
188 | |
189 | impl 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)] |
208 | pub enum ColorMatrixKind { |
209 | Matrix(Vec<f32>), // Guarantee to have 20 numbers. |
210 | Saturate(PositiveF32), |
211 | HueRotate(f32), |
212 | LuminanceToAlpha, |
213 | } |
214 | |
215 | impl 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)] |
228 | pub 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 | |
236 | impl 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)] |
269 | pub 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)] |
300 | pub struct Composite { |
301 | pub(crate) input1: Input, |
302 | pub(crate) input2: Input, |
303 | pub(crate) operator: CompositeOperator, |
304 | } |
305 | |
306 | impl 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)] |
332 | pub 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)] |
345 | pub 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 | |
354 | impl 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)] |
400 | pub 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 | |
408 | impl 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 | |
443 | impl 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)] |
484 | pub 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)] |
494 | pub 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 | |
502 | impl 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)] |
542 | pub 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)] |
555 | pub 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 | |
565 | impl 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)] |
616 | pub struct Flood { |
617 | pub(crate) color: Color, |
618 | pub(crate) opacity: Opacity, |
619 | } |
620 | |
621 | impl 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)] |
641 | pub struct GaussianBlur { |
642 | pub(crate) input: Input, |
643 | pub(crate) std_dev_x: PositiveF32, |
644 | pub(crate) std_dev_y: PositiveF32, |
645 | } |
646 | |
647 | impl 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)] |
674 | pub struct Image { |
675 | pub(crate) root: Group, |
676 | } |
677 | |
678 | impl 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)] |
689 | pub 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 | |
697 | impl 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)] |
736 | pub 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 | |
745 | impl 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)] |
792 | pub 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)] |
802 | pub 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)] |
819 | pub 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)] |
840 | pub 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)] |
886 | pub struct Merge { |
887 | pub(crate) inputs: Vec<Input>, |
888 | } |
889 | |
890 | impl 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)] |
903 | pub 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 | |
910 | impl 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)] |
947 | pub enum MorphologyOperator { |
948 | Erode, |
949 | Dilate, |
950 | } |
951 | |
952 | /// An offset filter primitive. |
953 | /// |
954 | /// `feOffset` element in the SVG. |
955 | #[derive (Clone, Debug)] |
956 | pub struct Offset { |
957 | pub(crate) input: Input, |
958 | pub(crate) dx: f32, |
959 | pub(crate) dy: f32, |
960 | } |
961 | |
962 | impl 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)] |
985 | pub struct Tile { |
986 | pub(crate) input: Input, |
987 | } |
988 | |
989 | impl 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)] |
1002 | pub 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 | |
1011 | impl 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)] |
1058 | pub enum TurbulenceKind { |
1059 | FractalNoise, |
1060 | Turbulence, |
1061 | } |
1062 | |