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