rsvg/filters/
drop_shadow.rs

1use markup5ever::{expanded_name, local_name, ns};
2
3use crate::color::resolve_color;
4use crate::document::AcquiredNodes;
5use crate::element::{set_attribute, ElementTrait};
6use crate::filter_func::drop_shadow_primitives;
7use crate::node::{CascadedValues, Node};
8use crate::parsers::{NumberOptionalNumber, ParseValue};
9use crate::session::Session;
10use crate::xml::Attributes;
11
12use super::{FilterEffect, FilterResolveError, Input, Primitive, ResolvedPrimitive};
13
14/// The `feDropShadow` element.
15#[derive(Default)]
16pub struct FeDropShadow {
17    base: Primitive,
18    params: DropShadow,
19}
20
21/// Resolved `feDropShadow` parameters for rendering.
22pub struct DropShadow {
23    pub in1: Input,
24    pub dx: f64,
25    pub dy: f64,
26    pub std_deviation: NumberOptionalNumber<f64>,
27}
28
29impl Default for DropShadow {
30    /// Defaults come from <https://www.w3.org/TR/filter-effects/#feDropShadowElement>
31    fn default() -> Self {
32        Self {
33            in1: Default::default(),
34            dx: 2.0,
35            dy: 2.0,
36            std_deviation: NumberOptionalNumber(2.0, 2.0),
37        }
38    }
39}
40
41impl ElementTrait for FeDropShadow {
42    fn set_attributes(&mut self, attrs: &Attributes, session: &Session) {
43        self.params.in1 = self.base.parse_one_input(attrs, session);
44
45        for (attr, value) in attrs.iter() {
46            match attr.expanded() {
47                expanded_name!("", "dx") => {
48                    set_attribute(&mut self.params.dx, attr.parse(value), session);
49                }
50
51                expanded_name!("", "dy") => {
52                    set_attribute(&mut self.params.dy, attr.parse(value), session);
53                }
54
55                expanded_name!("", "stdDeviation") => {
56                    set_attribute(&mut self.params.std_deviation, attr.parse(value), session);
57                }
58
59                _ => (),
60            }
61        }
62    }
63}
64
65impl FilterEffect for FeDropShadow {
66    fn resolve(
67        &self,
68        _acquired_nodes: &mut AcquiredNodes<'_>,
69        node: &Node,
70    ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
71        let cascaded = CascadedValues::new_from_node(node);
72        let values = cascaded.get();
73
74        let color = resolve_color(
75            &values.flood_color().0,
76            values.flood_opacity().0,
77            &values.color().0,
78        );
79
80        Ok(drop_shadow_primitives(
81            self.params.dx,
82            self.params.dy,
83            self.params.std_deviation,
84            color,
85        ))
86    }
87}