1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 
5 use crate::qt;
6 
7 use crate::prelude::*;
8 use crate::image;
9 use crate::ConvTransform;
10 
11 
draw( image: &usvg::Image, opt: &Options, p: &mut qt::Painter, ) -> Rect12 pub fn draw(
13     image: &usvg::Image,
14     opt: &Options,
15     p: &mut qt::Painter,
16 ) -> Rect {
17     if image.visibility != usvg::Visibility::Visible {
18         return image.view_box.rect;
19     }
20 
21     if image.format == usvg::ImageFormat::SVG {
22         draw_svg(&image.data, image.view_box, opt, p);
23     } else {
24         draw_raster(image.format, &image.data, image.view_box, image.rendering_mode, opt, p);
25     }
26 
27     image.view_box.rect
28 }
29 
draw_raster( format: usvg::ImageFormat, data: &usvg::ImageData, view_box: usvg::ViewBox, rendering_mode: usvg::ImageRendering, opt: &Options, p: &mut qt::Painter, )30 pub fn draw_raster(
31     format: usvg::ImageFormat,
32     data: &usvg::ImageData,
33     view_box: usvg::ViewBox,
34     rendering_mode: usvg::ImageRendering,
35     opt: &Options,
36     p: &mut qt::Painter,
37 ) {
38     let img = try_opt!(image::load_raster(format, data, opt));
39 
40     let image = {
41         let (w, h) = img.size.dimensions();
42         let mut image = try_opt_warn_or!(
43             qt::Image::new_rgba(w, h), (),
44             "Failed to create a {}x{} image.", w, h
45         );
46         image_to_surface(&img, &mut image.data_mut());
47         image
48     };
49 
50     if rendering_mode == usvg::ImageRendering::OptimizeSpeed {
51         p.set_smooth_pixmap_transform(false);
52     }
53 
54     if view_box.aspect.slice {
55         let r = view_box.rect;
56         p.set_clip_rect(r.x(), r.y(), r.width(), r.height());
57     }
58 
59     let r = image::image_rect(&view_box, img.size);
60     p.draw_image_rect(r.x(), r.y(), r.width(), r.height(), &image);
61 
62     // Revert.
63     p.set_smooth_pixmap_transform(true);
64     p.reset_clip_path();
65 }
66 
image_to_surface(image: &image::Image, surface: &mut [u8])67 fn image_to_surface(image: &image::Image, surface: &mut [u8]) {
68     // Surface is always ARGB.
69     const SURFACE_CHANNELS: usize = 4;
70 
71     use crate::image::ImageData;
72     use rgb::FromSlice;
73 
74     let mut i = 0;
75 
76     let mut to_surface = |r, g, b, a| {
77         surface[i + 0] = b;
78         surface[i + 1] = g;
79         surface[i + 2] = r;
80         surface[i + 3] = a;
81 
82         i += SURFACE_CHANNELS;
83     };
84 
85     match &image.data {
86         ImageData::RGB(data) => {
87             for p in data.as_rgb() {
88                 to_surface(p.r, p.g, p.b, 255);
89             }
90         }
91         ImageData::RGBA(data) => {
92             for p in data.as_rgba() {
93                 to_surface(p.r, p.g, p.b, p.a);
94             }
95         }
96     }
97 }
98 
draw_svg( data: &usvg::ImageData, view_box: usvg::ViewBox, opt: &Options, p: &mut qt::Painter, )99 pub fn draw_svg(
100     data: &usvg::ImageData,
101     view_box: usvg::ViewBox,
102     opt: &Options,
103     p: &mut qt::Painter,
104 ) {
105     let (tree, sub_opt) = try_opt!(image::load_sub_svg(data, opt));
106 
107     let img_size = tree.svg_node().size.to_screen_size();
108     let (ts, clip) = image::prepare_sub_svg_geom(view_box, img_size);
109 
110     if let Some(clip) = clip {
111         p.set_clip_rect(clip.x(), clip.y(), clip.width(), clip.height());
112     }
113 
114     p.apply_transform(&ts.to_native());
115     super::render_to_canvas(&tree, &sub_opt, img_size, p);
116     p.reset_clip_path();
117 }
118