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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::prelude::ContentDrawFunction;

#[allow(dead_code)]
pub fn save_image<'a>(
    context: impl Into<Option<&'a mut skia_safe::gpu::DirectContext>>,
    image: &skia_safe::Image,
    name: &str,
) {
    use std::fs::File;
    use std::io::Write;

    let data = image
        .encode(context.into(), skia_safe::EncodedImageFormat::PNG, None)
        .unwrap();
    let bytes = data.as_bytes();
    let filename = format!("{}.png", name);
    let mut file = File::create(filename).unwrap();
    file.write_all(bytes).unwrap();
}

// pub fn svg_dom(
//     image_path: &str,
//     size: impl Into<skia_safe::ISize>,
// ) -> Result<skia_safe::svg::Dom, String> {
//     let svg_data =
//         std::fs::read(image_path).map_err(|e| format!("Failed to read SVG file: {}", e))?;

//     let size: skia_safe::ISize = size.into();
//     let options = usvg::Options {
//         resources_dir: None,
//         dpi: 96.0,
//         // Default font is user-agent dependent so we can use whichever we like.
//         font_family: "Times New Roman".to_owned(),
//         font_size: 12.0,
//         languages: vec!["en".to_string()],
//         shape_rendering: usvg::ShapeRendering::default(),
//         text_rendering: usvg::TextRendering::default(),
//         image_rendering: usvg::ImageRendering::default(),
//         default_size: usvg::Size::from_wh(size.width as f32, size.height as f32).unwrap(),
//         image_href_resolver: usvg::ImageHrefResolver::default(),
//     };
//     let mut rtree = usvg::Tree::from_data(&svg_data, &options)
//         .map_err(|e| format!("Failed to parse SVG data: {}", e))?;
//     rtree.size = usvg::Size::from_wh(size.width as f32, size.height as f32).unwrap();
//     let xml_options = usvg::XmlOptions::default();
//     let xml = usvg::TreeWriting::to_string(&rtree, &xml_options);
//     let resource_provider = SvgResourceProvider {};
//     let mut svg = skia_safe::svg::Dom::from_bytes(xml.as_bytes(), resource_provider)
//         .map_err(|e| format!("Failed to create SVG DOM: {}", e))?;
//     svg.set_container_size((size.width as f32, size.height as f32));
//     // println!("SVG DOM created {} \n {:?}", image_path, svg.root());
//     Ok(svg)
// }
pub fn load_svg_image(
    image_path: &str,
    size: impl Into<skia_safe::ISize>,
) -> Result<skia_safe::Image, String> {
    let size: skia_safe::ISize = size.into();

    println!("Loading image from path: {}", image_path);
    println!("Loading image with size: {:?}", size);

    // let svg = svg_dom(image_path, size)?;

    let svg_data =
        std::fs::read(image_path).map_err(|e| format!("Failed to read SVG file: {}", e))?;

    let pixmap_size =
        resvg::tiny_skia::IntSize::from_wh(size.width as u32, size.height as u32).unwrap();

    let options = usvg::Options {
        languages: vec!["en".to_string()],
        dpi: 1.0,
        default_size: usvg::Size::from_wh(pixmap_size.width() as f32, pixmap_size.height() as f32)
            .unwrap(),
        ..Default::default()
    };
    let rtree = usvg::Tree::from_data(&svg_data, &options)
        .map_err(|e| format!("Failed to parse SVG data: {}", e))?;

    let size = rtree.size().to_int_size();

    let mut pixmap =
        resvg::tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();

    let transform = resvg::tiny_skia::Transform::from_scale(
        pixmap_size.width() as f32 / size.width() as f32,
        pixmap_size.height() as f32 / size.height() as f32,
    );
    resvg::render(&rtree, transform, &mut pixmap.as_mut());

    let info = skia_safe::ImageInfo::new(
        (pixmap_size.width() as i32, pixmap_size.height() as i32),
        skia_safe::ColorType::RGBA8888,
        skia_safe::AlphaType::Premul,
        None,
    );
    let image = skia_safe::images::raster_from_data(
        &info,
        skia_safe::Data::new_copy(pixmap.data()),
        pixmap_size.width() as usize * 4,
    )
    .unwrap();

    Ok(image)
}

pub fn draw_image_content(image: &skia_safe::Image) -> ContentDrawFunction {
    let resampler = skia_safe::CubicResampler::catmull_rom();

    let img = image.clone();
    let draw_function = move |canvas: &skia_safe::Canvas, w: f32, h: f32| -> skia_safe::Rect {
        let paint = skia_safe::Paint::new(skia_safe::Color4f::new(1.0, 1.0, 1.0, 1.0), None);
        canvas.draw_image_rect_with_sampling_options(
            &img,
            None,
            skia_safe::Rect::from_xywh(0.0, 0.0, w, h),
            resampler,
            &paint,
        );
        skia_safe::Rect::from_xywh(0.0, 0.0, w, h)
    };
    draw_function.into()
}