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/// Fits the current rect into the specified bounds.
6pub fn fit_to_rect(
7 r: tiny_skia::IntRect,
8 bounds: tiny_skia::IntRect,
9) -> Option<tiny_skia::IntRect> {
10 let mut left: i32 = r.left();
11 if left < bounds.left() {
12 left = bounds.left();
13 }
14
15 let mut top: i32 = r.top();
16 if top < bounds.top() {
17 top = bounds.top();
18 }
19
20 let mut right: i32 = r.right();
21 if right > bounds.right() {
22 right = bounds.right();
23 }
24
25 let mut bottom: i32 = r.bottom();
26 if bottom > bounds.bottom() {
27 bottom = bounds.bottom();
28 }
29
30 tiny_skia::IntRect::from_ltrb(left, top, right, bottom)
31}
32
33/// Converts `viewBox` to `Transform` with an optional clip rectangle.
34///
35/// Unlike `view_box_to_transform`, returns an optional clip rectangle
36/// that should be applied before rendering the image.
37pub fn view_box_to_transform_with_clip(
38 view_box: &usvg::ViewBox,
39 img_size: tiny_skia::IntSize,
40) -> (usvg::Transform, Option<tiny_skia::NonZeroRect>) {
41 let r = view_box.rect;
42
43 let new_size = fit_view_box(img_size.to_size(), view_box);
44
45 let (tx, ty, clip) = if view_box.aspect.slice {
46 let (dx, dy) = usvg::utils::aligned_pos(
47 view_box.aspect.align,
48 0.0,
49 0.0,
50 new_size.width() - r.width(),
51 new_size.height() - r.height(),
52 );
53
54 (r.x() - dx, r.y() - dy, Some(r))
55 } else {
56 let (dx, dy) = usvg::utils::aligned_pos(
57 view_box.aspect.align,
58 r.x(),
59 r.y(),
60 r.width() - new_size.width(),
61 r.height() - new_size.height(),
62 );
63
64 (dx, dy, None)
65 };
66
67 let sx = new_size.width() / img_size.width() as f32;
68 let sy = new_size.height() / img_size.height() as f32;
69 let ts = usvg::Transform::from_row(sx, 0.0, 0.0, sy, tx, ty);
70
71 (ts, clip)
72}
73
74/// Fits size into a viewbox.
75pub fn fit_view_box(size: usvg::Size, vb: &usvg::ViewBox) -> usvg::Size {
76 let s: Size = vb.rect.size();
77
78 if vb.aspect.align == usvg::Align::None {
79 s
80 } else if vb.aspect.slice {
81 size.expand_to(s)
82 } else {
83 size.scale_to(s)
84 }
85}
86