1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use super::Kind;
use crate::svgtree::{self, AId};
use crate::{converter, AspectRatio, Group, ImageRendering, Node, NodeKind};

/// An image filter primitive.
///
/// `feImage` element in the SVG.
#[derive(Clone, Debug)]
pub struct Image {
    /// Value of the `preserveAspectRatio` attribute.
    pub aspect: AspectRatio,

    /// Rendering method.
    ///
    /// `image-rendering` in SVG.
    pub rendering_mode: ImageRendering,

    /// Image data.
    pub data: ImageKind,
}

/// Kind of the `feImage` data.
#[derive(Clone, Debug)]
pub enum ImageKind {
    /// An image data.
    Image(crate::ImageKind),

    /// An SVG node.
    ///
    /// Isn't inside a dummy group like clip, mask and pattern because
    /// `feImage` can reference only a single element.
    Use(Node),
}

pub(crate) fn convert(
    fe: svgtree::Node,
    state: &converter::State,
    cache: &mut converter::Cache,
) -> Kind {
    let aspect = fe.attribute(AId::PreserveAspectRatio).unwrap_or_default();
    let rendering_mode = fe
        .find_attribute(AId::ImageRendering)
        .unwrap_or(state.opt.image_rendering);

    if let Some(node) = fe.attribute::<svgtree::Node>(AId::Href) {
        let mut state = state.clone();
        state.fe_image_link = true;
        let mut root = Node::new(NodeKind::Group(Group::default()));
        crate::converter::convert_element(node, &state, cache, &mut root);
        return if let Some(node) = root.first_child() {
            node.detach(); // drops `root` node
            Kind::Image(Image {
                aspect,
                rendering_mode,
                data: ImageKind::Use(node),
            })
        } else {
            super::create_dummy_primitive()
        };
    }

    let href = match fe.attribute(AId::Href) {
        Some(s) => s,
        _ => {
            log::warn!("The 'feImage' element lacks the 'xlink:href' attribute. Skipped.");
            return super::create_dummy_primitive();
        }
    };

    let href = crate::image::get_href_data(href, state.opt);
    let img_data = match href {
        Some(data) => data,
        None => return super::create_dummy_primitive(),
    };

    Kind::Image(Image {
        aspect,
        rendering_mode,
        data: ImageKind::Image(img_data),
    })
}