Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/gpu_display/src/gpu_display_win/math_util.rs
5394 views
1
// Copyright 2022 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
use std::any::type_name;
6
use std::fmt;
7
8
use euclid::point2;
9
use euclid::size2;
10
use euclid::Size2D;
11
use num_traits::NumCast;
12
use winapi::shared::windef::LPPOINT;
13
use winapi::shared::windef::POINT;
14
use winapi::shared::windef::RECT;
15
16
use super::HostWindowSpace;
17
18
pub type Point = euclid::Point2D<i32, HostWindowSpace>;
19
pub type Rect = euclid::Rect<i32, HostWindowSpace>;
20
pub type Size = euclid::Size2D<i32, HostWindowSpace>;
21
22
pub trait SizeExtension {
23
fn create_and_enforce_aspect_ratio(
24
original_size: &Self,
25
expected_aspect_ratio: f32,
26
should_adjust_width: bool,
27
) -> Self;
28
#[allow(dead_code)]
29
fn get_largest_inner_rect_size(original_size: &Self, expected_aspect_ratio: f32) -> Self;
30
#[allow(dead_code)]
31
fn scale(&self, ratio: f32) -> Self;
32
#[allow(dead_code)]
33
fn transpose(&self) -> Self;
34
#[allow(dead_code)]
35
fn shorter_edge(&self) -> i32;
36
fn aspect_ratio(&self) -> f32;
37
#[allow(dead_code)]
38
fn is_square(&self) -> bool;
39
#[allow(dead_code)]
40
fn is_landscape(&self) -> bool;
41
}
42
43
impl SizeExtension for Size {
44
fn create_and_enforce_aspect_ratio(
45
original_size: &Self,
46
expected_aspect_ratio: f32,
47
should_adjust_width: bool,
48
) -> Self {
49
let mut size = *original_size;
50
if should_adjust_width {
51
size.width = (size.height as f32 * expected_aspect_ratio).round() as i32;
52
} else {
53
size.height = (size.width as f32 / expected_aspect_ratio).round() as i32;
54
}
55
size
56
}
57
58
fn get_largest_inner_rect_size(original_size: &Self, expected_aspect_ratio: f32) -> Self {
59
Size::create_and_enforce_aspect_ratio(
60
original_size,
61
expected_aspect_ratio,
62
/* should_adjust_width */ original_size.aspect_ratio() > expected_aspect_ratio,
63
)
64
}
65
66
#[inline]
67
fn scale(&self, ratio: f32) -> Self {
68
size2(
69
(self.width as f32 * ratio) as i32,
70
(self.height as f32 * ratio) as i32,
71
)
72
}
73
74
#[inline]
75
fn transpose(&self) -> Self {
76
size2(self.height, self.width)
77
}
78
79
#[inline]
80
fn shorter_edge(&self) -> i32 {
81
std::cmp::min(self.width, self.height)
82
}
83
84
#[inline]
85
fn aspect_ratio(&self) -> f32 {
86
self.width as f32 / self.height as f32
87
}
88
89
#[inline]
90
fn is_square(&self) -> bool {
91
self.width == self.height
92
}
93
94
#[inline]
95
fn is_landscape(&self) -> bool {
96
self.width > self.height
97
}
98
}
99
100
pub trait RectExtension {
101
fn to_sys_rect(&self) -> RECT;
102
}
103
104
impl RectExtension for Rect {
105
#[inline]
106
fn to_sys_rect(&self) -> RECT {
107
RECT {
108
left: self.min_x(),
109
top: self.min_y(),
110
right: self.max_x(),
111
bottom: self.max_y(),
112
}
113
}
114
}
115
116
pub trait SysRectExtension {
117
fn to_rect(&self) -> Rect;
118
}
119
120
impl SysRectExtension for RECT {
121
#[inline]
122
fn to_rect(&self) -> Rect {
123
Rect::new(
124
point2(self.left, self.top),
125
size2(self.right - self.left, self.bottom - self.top),
126
)
127
}
128
}
129
130
pub trait PointExtension {
131
fn to_sys_point(&self) -> POINT;
132
}
133
134
impl PointExtension for Point {
135
#[inline]
136
fn to_sys_point(&self) -> POINT {
137
POINT {
138
x: self.x,
139
y: self.y,
140
}
141
}
142
}
143
144
pub trait SysPointExtension {
145
fn to_point(&self) -> Point;
146
fn as_mut_ptr(&mut self) -> LPPOINT;
147
}
148
149
impl SysPointExtension for POINT {
150
#[inline]
151
fn to_point(&self) -> Point {
152
point2(self.x, self.y)
153
}
154
155
#[inline]
156
fn as_mut_ptr(&mut self) -> LPPOINT {
157
self as LPPOINT
158
}
159
}
160
161
pub trait Size2DCheckedCast<U>: Sized {
162
fn checked_cast<T: NumCast>(self) -> Size2D<T, U>;
163
}
164
165
impl<T, U> Size2DCheckedCast<U> for Size2D<T, U>
166
where
167
T: NumCast + Copy + fmt::Debug,
168
{
169
fn checked_cast<NewT: NumCast>(self) -> Size2D<NewT, U> {
170
self.try_cast::<NewT>().unwrap_or_else(|| {
171
panic!(
172
"Cannot cast {:?} from {} to {}",
173
self,
174
type_name::<T>(),
175
type_name::<NewT>(),
176
)
177
})
178
}
179
}
180
181
#[cfg(test)]
182
mod tests {
183
use super::*;
184
185
#[test]
186
fn largest_inner_rect_size_when_outer_is_wider() {
187
assert_eq!(
188
Size::get_largest_inner_rect_size(
189
/* original_size */ &size2(1600, 900),
190
/* expected_aspect_ratio */ 0.5
191
),
192
size2(450, 900)
193
);
194
}
195
196
#[test]
197
fn largest_inner_rect_size_when_outer_is_taller() {
198
assert_eq!(
199
Size::get_largest_inner_rect_size(
200
/* original_size */ &size2(900, 1600),
201
/* expected_aspect_ratio */ 3.0
202
),
203
size2(900, 300)
204
);
205
}
206
}
207
208