1pub trait Pixel: Copy + Into<f64> {
105 fn from_f64(f: f64) -> Self;
106 fn cast<P: Pixel>(self) -> P {
107 P::from_f64(self.into())
108 }
109}
110
111impl Pixel for u8 {
112 fn from_f64(f: f64) -> Self {
113 f.round() as u8
114 }
115}
116impl Pixel for u16 {
117 fn from_f64(f: f64) -> Self {
118 f.round() as u16
119 }
120}
121impl Pixel for u32 {
122 fn from_f64(f: f64) -> Self {
123 f.round() as u32
124 }
125}
126impl Pixel for i8 {
127 fn from_f64(f: f64) -> Self {
128 f.round() as i8
129 }
130}
131impl Pixel for i16 {
132 fn from_f64(f: f64) -> Self {
133 f.round() as i16
134 }
135}
136impl Pixel for i32 {
137 fn from_f64(f: f64) -> Self {
138 f.round() as i32
139 }
140}
141impl Pixel for f32 {
142 fn from_f64(f: f64) -> Self {
143 f as f32
144 }
145}
146impl Pixel for f64 {
147 fn from_f64(f: f64) -> Self {
148 f
149 }
150}
151
152#[inline]
158pub fn validate_scale_factor(scale_factor: f64) -> bool {
159 scale_factor.is_sign_positive() && scale_factor.is_normal()
160}
161
162#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
169pub struct LogicalPosition<P> {
170 pub x: P,
171 pub y: P,
172}
173
174impl<P> LogicalPosition<P> {
175 #[inline]
176 pub const fn new(x: P, y: P) -> Self {
177 LogicalPosition { x, y }
178 }
179}
180
181impl<P: Pixel> LogicalPosition<P> {
182 #[inline]
183 pub fn from_physical<T: Into<PhysicalPosition<X>>, X: Pixel>(
184 physical: T,
185 scale_factor: f64,
186 ) -> Self {
187 physical.into().to_logical(scale_factor)
188 }
189
190 #[inline]
191 pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalPosition<X> {
192 assert!(validate_scale_factor(scale_factor));
193 let x = self.x.into() * scale_factor;
194 let y = self.y.into() * scale_factor;
195 PhysicalPosition::new(x, y).cast()
196 }
197
198 #[inline]
199 pub fn cast<X: Pixel>(&self) -> LogicalPosition<X> {
200 LogicalPosition {
201 x: self.x.cast(),
202 y: self.y.cast(),
203 }
204 }
205}
206
207impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalPosition<P> {
208 fn from((x, y): (X, X)) -> LogicalPosition<P> {
209 LogicalPosition::new(x.cast(), y.cast())
210 }
211}
212
213impl<P: Pixel, X: Pixel> Into<(X, X)> for LogicalPosition<P> {
214 fn into(self: Self) -> (X, X) {
215 (self.x.cast(), self.y.cast())
216 }
217}
218
219impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalPosition<P> {
220 fn from([x, y]: [X; 2]) -> LogicalPosition<P> {
221 LogicalPosition::new(x.cast(), y.cast())
222 }
223}
224
225impl<P: Pixel, X: Pixel> Into<[X; 2]> for LogicalPosition<P> {
226 fn into(self: Self) -> [X; 2] {
227 [self.x.cast(), self.y.cast()]
228 }
229}
230
231#[cfg(feature = "mint")]
232impl<P: Pixel> From<mint::Point2<P>> for LogicalPosition<P> {
233 fn from(mint: mint::Point2<P>) -> Self {
234 Self::new(mint.x, mint.y)
235 }
236}
237
238#[cfg(feature = "mint")]
239impl<P: Pixel> From<LogicalPosition<P>> for mint::Point2<P> {
240 fn from(winit: LogicalPosition<P>) -> Self {
241 mint::Point2 {
242 x: winit.x,
243 y: winit.y,
244 }
245 }
246}
247
248#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
251pub struct PhysicalPosition<P> {
252 pub x: P,
253 pub y: P,
254}
255
256impl<P> PhysicalPosition<P> {
257 #[inline]
258 pub const fn new(x: P, y: P) -> Self {
259 PhysicalPosition { x, y }
260 }
261}
262
263impl<P: Pixel> PhysicalPosition<P> {
264 #[inline]
265 pub fn from_logical<T: Into<LogicalPosition<X>>, X: Pixel>(
266 logical: T,
267 scale_factor: f64,
268 ) -> Self {
269 logical.into().to_physical(scale_factor)
270 }
271
272 #[inline]
273 pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalPosition<X> {
274 assert!(validate_scale_factor(scale_factor));
275 let x = self.x.into() / scale_factor;
276 let y = self.y.into() / scale_factor;
277 LogicalPosition::new(x, y).cast()
278 }
279
280 #[inline]
281 pub fn cast<X: Pixel>(&self) -> PhysicalPosition<X> {
282 PhysicalPosition {
283 x: self.x.cast(),
284 y: self.y.cast(),
285 }
286 }
287}
288
289impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalPosition<P> {
290 fn from((x, y): (X, X)) -> PhysicalPosition<P> {
291 PhysicalPosition::new(x.cast(), y.cast())
292 }
293}
294
295impl<P: Pixel, X: Pixel> Into<(X, X)> for PhysicalPosition<P> {
296 fn into(self: Self) -> (X, X) {
297 (self.x.cast(), self.y.cast())
298 }
299}
300
301impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalPosition<P> {
302 fn from([x, y]: [X; 2]) -> PhysicalPosition<P> {
303 PhysicalPosition::new(x.cast(), y.cast())
304 }
305}
306
307impl<P: Pixel, X: Pixel> Into<[X; 2]> for PhysicalPosition<P> {
308 fn into(self: Self) -> [X; 2] {
309 [self.x.cast(), self.y.cast()]
310 }
311}
312
313#[cfg(feature = "mint")]
314impl<P: Pixel> From<mint::Point2<P>> for PhysicalPosition<P> {
315 fn from(mint: mint::Point2<P>) -> Self {
316 Self::new(mint.x, mint.y)
317 }
318}
319
320#[cfg(feature = "mint")]
321impl<P: Pixel> From<PhysicalPosition<P>> for mint::Point2<P> {
322 fn from(winit: PhysicalPosition<P>) -> Self {
323 mint::Point2 {
324 x: winit.x,
325 y: winit.y,
326 }
327 }
328}
329
330#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
332#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
333pub struct LogicalSize<P> {
334 pub width: P,
335 pub height: P,
336}
337
338impl<P> LogicalSize<P> {
339 #[inline]
340 pub const fn new(width: P, height: P) -> Self {
341 LogicalSize { width, height }
342 }
343}
344
345impl<P: Pixel> LogicalSize<P> {
346 #[inline]
347 pub fn from_physical<T: Into<PhysicalSize<X>>, X: Pixel>(
348 physical: T,
349 scale_factor: f64,
350 ) -> Self {
351 physical.into().to_logical(scale_factor)
352 }
353
354 #[inline]
355 pub fn to_physical<X: Pixel>(&self, scale_factor: f64) -> PhysicalSize<X> {
356 assert!(validate_scale_factor(scale_factor));
357 let width = self.width.into() * scale_factor;
358 let height = self.height.into() * scale_factor;
359 PhysicalSize::new(width, height).cast()
360 }
361
362 #[inline]
363 pub fn cast<X: Pixel>(&self) -> LogicalSize<X> {
364 LogicalSize {
365 width: self.width.cast(),
366 height: self.height.cast(),
367 }
368 }
369}
370
371impl<P: Pixel, X: Pixel> From<(X, X)> for LogicalSize<P> {
372 fn from((x, y): (X, X)) -> LogicalSize<P> {
373 LogicalSize::new(x.cast(), y.cast())
374 }
375}
376
377impl<P: Pixel, X: Pixel> Into<(X, X)> for LogicalSize<P> {
378 fn into(self: LogicalSize<P>) -> (X, X) {
379 (self.width.cast(), self.height.cast())
380 }
381}
382
383impl<P: Pixel, X: Pixel> From<[X; 2]> for LogicalSize<P> {
384 fn from([x, y]: [X; 2]) -> LogicalSize<P> {
385 LogicalSize::new(x.cast(), y.cast())
386 }
387}
388
389impl<P: Pixel, X: Pixel> Into<[X; 2]> for LogicalSize<P> {
390 fn into(self: Self) -> [X; 2] {
391 [self.width.cast(), self.height.cast()]
392 }
393}
394
395#[cfg(feature = "mint")]
396impl<P: Pixel> From<mint::Vector2<P>> for LogicalSize<P> {
397 fn from(mint: mint::Vector2<P>) -> Self {
398 Self::new(mint.x, mint.y)
399 }
400}
401
402#[cfg(feature = "mint")]
403impl<P: Pixel> From<LogicalSize<P>> for mint::Vector2<P> {
404 fn from(winit: LogicalSize<P>) -> Self {
405 mint::Vector2 {
406 x: winit.width,
407 y: winit.height,
408 }
409 }
410}
411
412#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
414#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
415pub struct PhysicalSize<P> {
416 pub width: P,
417 pub height: P,
418}
419
420impl<P> PhysicalSize<P> {
421 #[inline]
422 pub const fn new(width: P, height: P) -> Self {
423 PhysicalSize { width, height }
424 }
425}
426
427impl<P: Pixel> PhysicalSize<P> {
428 #[inline]
429 pub fn from_logical<T: Into<LogicalSize<X>>, X: Pixel>(logical: T, scale_factor: f64) -> Self {
430 logical.into().to_physical(scale_factor)
431 }
432
433 #[inline]
434 pub fn to_logical<X: Pixel>(&self, scale_factor: f64) -> LogicalSize<X> {
435 assert!(validate_scale_factor(scale_factor));
436 let width = self.width.into() / scale_factor;
437 let height = self.height.into() / scale_factor;
438 LogicalSize::new(width, height).cast()
439 }
440
441 #[inline]
442 pub fn cast<X: Pixel>(&self) -> PhysicalSize<X> {
443 PhysicalSize {
444 width: self.width.cast(),
445 height: self.height.cast(),
446 }
447 }
448}
449
450impl<P: Pixel, X: Pixel> From<(X, X)> for PhysicalSize<P> {
451 fn from((x, y): (X, X)) -> PhysicalSize<P> {
452 PhysicalSize::new(x.cast(), y.cast())
453 }
454}
455
456impl<P: Pixel, X: Pixel> Into<(X, X)> for PhysicalSize<P> {
457 fn into(self: Self) -> (X, X) {
458 (self.width.cast(), self.height.cast())
459 }
460}
461
462impl<P: Pixel, X: Pixel> From<[X; 2]> for PhysicalSize<P> {
463 fn from([x, y]: [X; 2]) -> PhysicalSize<P> {
464 PhysicalSize::new(x.cast(), y.cast())
465 }
466}
467
468impl<P: Pixel, X: Pixel> Into<[X; 2]> for PhysicalSize<P> {
469 fn into(self: Self) -> [X; 2] {
470 [self.width.cast(), self.height.cast()]
471 }
472}
473
474#[cfg(feature = "mint")]
475impl<P: Pixel> From<mint::Vector2<P>> for PhysicalSize<P> {
476 fn from(mint: mint::Vector2<P>) -> Self {
477 Self::new(mint.x, mint.y)
478 }
479}
480
481#[cfg(feature = "mint")]
482impl<P: Pixel> From<PhysicalSize<P>> for mint::Vector2<P> {
483 fn from(winit: PhysicalSize<P>) -> Self {
484 mint::Vector2 {
485 x: winit.width,
486 y: winit.height,
487 }
488 }
489}
490
491#[derive(Debug, Copy, Clone, PartialEq)]
493#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
494pub enum Size {
495 Physical(PhysicalSize<u32>),
496 Logical(LogicalSize<f64>),
497}
498
499impl Size {
500 pub fn new<S: Into<Size>>(size: S) -> Size {
501 size.into()
502 }
503
504 pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalSize<P> {
505 match *self {
506 Size::Physical(size) => size.to_logical(scale_factor),
507 Size::Logical(size) => size.cast(),
508 }
509 }
510
511 pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalSize<P> {
512 match *self {
513 Size::Physical(size) => size.cast(),
514 Size::Logical(size) => size.to_physical(scale_factor),
515 }
516 }
517}
518
519impl<P: Pixel> From<PhysicalSize<P>> for Size {
520 #[inline]
521 fn from(size: PhysicalSize<P>) -> Size {
522 Size::Physical(size.cast())
523 }
524}
525
526impl<P: Pixel> From<LogicalSize<P>> for Size {
527 #[inline]
528 fn from(size: LogicalSize<P>) -> Size {
529 Size::Logical(size.cast())
530 }
531}
532
533#[derive(Debug, Copy, Clone, PartialEq)]
535#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
536pub enum Position {
537 Physical(PhysicalPosition<i32>),
538 Logical(LogicalPosition<f64>),
539}
540
541impl Position {
542 pub fn new<S: Into<Position>>(position: S) -> Position {
543 position.into()
544 }
545
546 pub fn to_logical<P: Pixel>(&self, scale_factor: f64) -> LogicalPosition<P> {
547 match *self {
548 Position::Physical(position) => position.to_logical(scale_factor),
549 Position::Logical(position) => position.cast(),
550 }
551 }
552
553 pub fn to_physical<P: Pixel>(&self, scale_factor: f64) -> PhysicalPosition<P> {
554 match *self {
555 Position::Physical(position) => position.cast(),
556 Position::Logical(position) => position.to_physical(scale_factor),
557 }
558 }
559}
560
561impl<P: Pixel> From<PhysicalPosition<P>> for Position {
562 #[inline]
563 fn from(position: PhysicalPosition<P>) -> Position {
564 Position::Physical(position.cast())
565 }
566}
567
568impl<P: Pixel> From<LogicalPosition<P>> for Position {
569 #[inline]
570 fn from(position: LogicalPosition<P>) -> Position {
571 Position::Logical(position.cast())
572 }
573}