1 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9 
10 use super::UnknownUnit;
11 use approxord::{max, min};
12 #[cfg(feature = "mint")]
13 use mint;
14 use length::Length;
15 use scale::Scale;
16 use vector::{Vector2D, vec2, BoolVector2D};
17 use vector::{Vector3D, vec3, BoolVector3D};
18 use num::*;
19 
20 use num_traits::{NumCast, Signed};
21 use core::fmt;
22 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
23 use core::marker::PhantomData;
24 use core::cmp::{Eq, PartialEq};
25 use core::hash::{Hash};
26 #[cfg(feature = "serde")]
27 use serde;
28 
29 /// A 2d size tagged with a unit.
30 #[repr(C)]
31 pub struct Size2D<T, U> {
32     /// The extent of the element in the `U` units along the `x` axis (usually horizontal).
33     pub width: T,
34     /// The extent of the element in the `U` units along the `y` axis (usually vertical).
35     pub height: T,
36     #[doc(hidden)]
37     pub _unit: PhantomData<U>,
38 }
39 
40 impl<T: Copy, U> Copy for Size2D<T, U> {}
41 
42 impl<T: Clone, U> Clone for Size2D<T, U> {
clone(&self) -> Self43     fn clone(&self) -> Self {
44         Size2D {
45             width: self.width.clone(),
46             height: self.height.clone(),
47             _unit: PhantomData,
48         }
49     }
50 }
51 
52 #[cfg(feature = "serde")]
53 impl<'de, T, U> serde::Deserialize<'de> for Size2D<T, U>
54     where T: serde::Deserialize<'de>
55 {
56     /// Deserializes 2d size from tuple of width and height.
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>57     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58         where D: serde::Deserializer<'de>
59     {
60         let (width, height) = serde::Deserialize::deserialize(deserializer)?;
61         Ok(Size2D { width, height, _unit: PhantomData })
62     }
63 }
64 
65 #[cfg(feature = "serde")]
66 impl<T, U> serde::Serialize for Size2D<T, U>
67     where T: serde::Serialize
68 {
69     /// Serializes 2d size to tuple of width and height.
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer70     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71         where S: serde::Serializer
72     {
73         (&self.width, &self.height).serialize(serializer)
74     }
75 }
76 
77 impl<T, U> Eq for Size2D<T, U> where T: Eq {}
78 
79 impl<T, U> PartialEq for Size2D<T, U>
80     where T: PartialEq
81 {
eq(&self, other: &Self) -> bool82     fn eq(&self, other: &Self) -> bool {
83         self.width == other.width && self.height == other.height
84     }
85 }
86 
87 impl<T, U> Hash for Size2D<T, U>
88     where T: Hash
89 {
hash<H: ::core::hash::Hasher>(&self, h: &mut H)90     fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
91         self.width.hash(h);
92         self.height.hash(h);
93     }
94 }
95 
96 impl<T: fmt::Debug, U> fmt::Debug for Size2D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result97     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98         fmt::Debug::fmt(&self.width, f)?;
99         write!(f, "x")?;
100         fmt::Debug::fmt(&self.height, f)
101     }
102 }
103 
104 impl<T: fmt::Display, U> fmt::Display for Size2D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result105     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106         write!(f, "(")?;
107         fmt::Display::fmt(&self.width, f)?;
108         write!(f, "x")?;
109         fmt::Display::fmt(&self.height, f)?;
110         write!(f, ")")
111     }
112 }
113 
114 impl<T: Default, U> Default for Size2D<T, U> {
default() -> Self115     fn default() -> Self {
116         Size2D::new(Default::default(), Default::default())
117     }
118 }
119 
120 
121 impl<T, U> Size2D<T, U> {
122     /// The same as [`Zero::zero()`] but available without importing trait.
123     ///
124     /// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero
125     #[inline]
zero() -> Self where T: Zero,126     pub fn zero() -> Self
127     where
128         T: Zero,
129     {
130         Size2D::new(Zero::zero(), Zero::zero())
131     }
132 
133     /// Constructor taking scalar values.
134     #[inline]
new(width: T, height: T) -> Self135     pub const fn new(width: T, height: T) -> Self {
136         Size2D {
137             width,
138             height,
139             _unit: PhantomData,
140         }
141     }
142     /// Constructor taking scalar strongly typed lengths.
143     #[inline]
from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self144     pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
145         Size2D::new(width.0, height.0)
146     }
147 
148     /// Tag a unitless value with units.
149     #[inline]
from_untyped(p: Size2D<T, UnknownUnit>) -> Self150     pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
151         Size2D::new(p.width, p.height)
152     }
153 }
154 
155 impl<T: Copy, U> Size2D<T, U> {
156     /// Return this size as an array of two elements (width, then height).
157     #[inline]
to_array(&self) -> [T; 2]158     pub fn to_array(&self) -> [T; 2] {
159         [self.width, self.height]
160     }
161 
162     /// Return this size as a tuple of two elements (width, then height).
163     #[inline]
to_tuple(&self) -> (T, T)164     pub fn to_tuple(&self) -> (T, T) {
165         (self.width, self.height)
166     }
167 
168     /// Return this size as a vector with width and height.
169     #[inline]
to_vector(&self) -> Vector2D<T, U>170     pub fn to_vector(&self) -> Vector2D<T, U> {
171         vec2(self.width, self.height)
172     }
173 
174     /// Drop the units, preserving only the numeric value.
175     #[inline]
to_untyped(&self) -> Size2D<T, UnknownUnit>176     pub fn to_untyped(&self) -> Size2D<T, UnknownUnit> {
177         self.cast_unit()
178     }
179 
180     /// Cast the unit
181     #[inline]
cast_unit<V>(&self) -> Size2D<T, V>182     pub fn cast_unit<V>(&self) -> Size2D<T, V> {
183         Size2D::new(self.width, self.height)
184     }
185 
186     /// Rounds each component to the nearest integer value.
187     ///
188     /// This behavior is preserved for negative values (unlike the basic cast).
189     ///
190     /// ```rust
191     /// # use euclid::size2;
192     /// enum Mm {}
193     ///
194     /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).round(), size2::<_, Mm>(0.0, -1.0))
195     /// ```
196     #[inline]
197     #[must_use]
round(&self) -> Self where T: Round,198     pub fn round(&self) -> Self
199     where
200         T: Round,
201     {
202         Size2D::new(self.width.round(), self.height.round())
203     }
204 
205     /// Rounds each component to the smallest integer equal or greater than the original value.
206     ///
207     /// This behavior is preserved for negative values (unlike the basic cast).
208     ///
209     /// ```rust
210     /// # use euclid::size2;
211     /// enum Mm {}
212     ///
213     /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).ceil(), size2::<_, Mm>(0.0, 0.0))
214     /// ```
215     #[inline]
216     #[must_use]
ceil(&self) -> Self where T: Ceil,217     pub fn ceil(&self) -> Self
218     where
219         T: Ceil,
220     {
221         Size2D::new(self.width.ceil(), self.height.ceil())
222     }
223 
224     /// Rounds each component to the biggest integer equal or lower than the original value.
225     ///
226     /// This behavior is preserved for negative values (unlike the basic cast).
227     ///
228     /// ```rust
229     /// # use euclid::size2;
230     /// enum Mm {}
231     ///
232     /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).floor(), size2::<_, Mm>(-1.0, -1.0))
233     /// ```
234     #[inline]
235     #[must_use]
floor(&self) -> Self where T: Floor,236     pub fn floor(&self) -> Self
237     where
238         T: Floor,
239     {
240         Size2D::new(self.width.floor(), self.height.floor())
241     }
242 
243     /// Returns result of multiplication of both components
area(&self) -> T::Output where T: Mul,244     pub fn area(&self) -> T::Output
245     where
246         T: Mul,
247     {
248         self.width * self.height
249     }
250 
251     /// Linearly interpolate each component between this size and another size.
252     ///
253     /// # Example
254     ///
255     /// ```rust
256     /// use euclid::size2;
257     /// use euclid::default::Size2D;
258     ///
259     /// let from: Size2D<_> = size2(0.0, 10.0);
260     /// let to:  Size2D<_> = size2(8.0, -4.0);
261     ///
262     /// assert_eq!(from.lerp(to, -1.0), size2(-8.0,  24.0));
263     /// assert_eq!(from.lerp(to,  0.0), size2( 0.0,  10.0));
264     /// assert_eq!(from.lerp(to,  0.5), size2( 4.0,   3.0));
265     /// assert_eq!(from.lerp(to,  1.0), size2( 8.0,  -4.0));
266     /// assert_eq!(from.lerp(to,  2.0), size2(16.0, -18.0));
267     /// ```
268     #[inline]
lerp(&self, other: Self, t: T) -> Self where T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,269     pub fn lerp(&self, other: Self, t: T) -> Self
270     where
271         T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
272     {
273         let one_t = T::one() - t;
274         (*self) * one_t + other * t
275     }
276 }
277 
278 impl<T: NumCast + Copy, U> Size2D<T, U> {
279     /// Cast from one numeric representation to another, preserving the units.
280     ///
281     /// When casting from floating point to integer coordinates, the decimals are truncated
282     /// as one would expect from a simple cast, but this behavior does not always make sense
283     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
284     #[inline]
cast<NewT: NumCast>(&self) -> Size2D<NewT, U>285     pub fn cast<NewT: NumCast>(&self) -> Size2D<NewT, U> {
286         self.try_cast().unwrap()
287     }
288 
289     /// Fallible cast from one numeric representation to another, preserving the units.
290     ///
291     /// When casting from floating point to integer coordinates, the decimals are truncated
292     /// as one would expect from a simple cast, but this behavior does not always make sense
293     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
try_cast<NewT: NumCast>(&self) -> Option<Size2D<NewT, U>>294     pub fn try_cast<NewT: NumCast>(&self) -> Option<Size2D<NewT, U>> {
295         match (NumCast::from(self.width), NumCast::from(self.height)) {
296             (Some(w), Some(h)) => Some(Size2D::new(w, h)),
297             _ => None,
298         }
299     }
300 
301     // Convenience functions for common casts
302 
303     /// Cast into an `f32` size.
304     #[inline]
to_f32(&self) -> Size2D<f32, U>305     pub fn to_f32(&self) -> Size2D<f32, U> {
306         self.cast()
307     }
308 
309     /// Cast into an `f64` size.
310     #[inline]
to_f64(&self) -> Size2D<f64, U>311     pub fn to_f64(&self) -> Size2D<f64, U> {
312         self.cast()
313     }
314 
315     /// Cast into an `uint` size, truncating decimals if any.
316     ///
317     /// When casting from floating point sizes, it is worth considering whether
318     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
319     /// the desired conversion behavior.
320     #[inline]
to_usize(&self) -> Size2D<usize, U>321     pub fn to_usize(&self) -> Size2D<usize, U> {
322         self.cast()
323     }
324 
325     /// Cast into an `u32` size, truncating decimals if any.
326     ///
327     /// When casting from floating point sizes, it is worth considering whether
328     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
329     /// the desired conversion behavior.
330     #[inline]
to_u32(&self) -> Size2D<u32, U>331     pub fn to_u32(&self) -> Size2D<u32, U> {
332         self.cast()
333     }
334 
335     /// Cast into an `u64` size, truncating decimals if any.
336     ///
337     /// When casting from floating point sizes, it is worth considering whether
338     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
339     /// the desired conversion behavior.
340     #[inline]
to_u64(&self) -> Size2D<u64, U>341     pub fn to_u64(&self) -> Size2D<u64, U> {
342         self.cast()
343     }
344 
345     /// Cast into an `i32` size, truncating decimals if any.
346     ///
347     /// When casting from floating point sizes, it is worth considering whether
348     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
349     /// the desired conversion behavior.
350     #[inline]
to_i32(&self) -> Size2D<i32, U>351     pub fn to_i32(&self) -> Size2D<i32, U> {
352         self.cast()
353     }
354 
355     /// Cast into an `i64` size, truncating decimals if any.
356     ///
357     /// When casting from floating point sizes, it is worth considering whether
358     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
359     /// the desired conversion behavior.
360     #[inline]
to_i64(&self) -> Size2D<i64, U>361     pub fn to_i64(&self) -> Size2D<i64, U> {
362         self.cast()
363     }
364 }
365 
366 impl<T: Signed, U> Size2D<T, U> {
367     /// Computes the absolute value of each component.
368     ///
369     /// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`.
370     ///
371     /// For signed integers, `::MIN` will be returned for component if the component is `::MIN`.
abs(&self) -> Self372     pub fn abs(&self) -> Self {
373         size2(self.width.abs(), self.height.abs())
374     }
375 
376     /// Returns `true` if both components is positive and `false` any component is zero or negative.
is_positive(&self) -> bool377     pub fn is_positive(&self) -> bool {
378         self.width.is_positive() && self.height.is_positive()
379     }
380 }
381 
382 impl<T: PartialOrd, U> Size2D<T, U> {
383     /// Returns the size each component of which are minimum of this size and another.
384     #[inline]
min(self, other: Self) -> Self385     pub fn min(self, other: Self) -> Self {
386         size2(
387             min(self.width,  other.width),
388             min(self.height, other.height),
389         )
390     }
391 
392     /// Returns the size each component of which are maximum of this size and another.
393     #[inline]
max(self, other: Self) -> Self394     pub fn max(self, other: Self) -> Self {
395         size2(
396             max(self.width,  other.width),
397             max(self.height, other.height),
398         )
399     }
400 
401     /// Returns the size each component of which clamped by corresponding
402     /// components of `start` and `end`.
403     ///
404     /// Shortcut for `self.max(start).min(end)`.
405     #[inline]
clamp(&self, start: Self, end: Self) -> Self where T: Copy,406     pub fn clamp(&self, start: Self, end: Self) -> Self
407     where
408         T: Copy,
409     {
410         self.max(start).min(end)
411     }
412 
413     /// Returns vector with results of "greater then" operation on each component.
greater_than(&self, other: Self) -> BoolVector2D414     pub fn greater_than(&self, other: Self) -> BoolVector2D {
415         BoolVector2D {
416             x: self.width > other.width,
417             y: self.height > other.height,
418         }
419     }
420 
421     /// Returns vector with results of "lower then" operation on each component.
lower_than(&self, other: Self) -> BoolVector2D422     pub fn lower_than(&self, other: Self) -> BoolVector2D {
423         BoolVector2D {
424             x: self.width < other.width,
425             y: self.height < other.height,
426         }
427     }
428 
429     /// Returns `true` if any component of size is zero or negative.
is_empty_or_negative(&self) -> bool where T: Zero,430     pub fn is_empty_or_negative(&self) -> bool
431     where
432         T: Zero,
433     {
434         let zero = T::zero();
435         self.width <= zero || self.height <= zero
436     }
437 }
438 
439 impl<T: PartialEq, U> Size2D<T, U> {
440     /// Returns vector with results of "equal" operation on each component.
equal(&self, other: Self) -> BoolVector2D441     pub fn equal(&self, other: Self) -> BoolVector2D {
442         BoolVector2D {
443             x: self.width == other.width,
444             y: self.height == other.height,
445         }
446     }
447 
448     /// Returns vector with results of "not equal" operation on each component.
not_equal(&self, other: Self) -> BoolVector2D449     pub fn not_equal(&self, other: Self) -> BoolVector2D {
450         BoolVector2D {
451             x: self.width != other.width,
452             y: self.height != other.height,
453         }
454     }
455 }
456 
457 
458 impl<T: Round, U> Round for Size2D<T, U> {
459     /// See [`Size2D::round()`](#method.round).
460     #[inline]
round(self) -> Self461     fn round(self) -> Self {
462         (&self).round()
463     }
464 }
465 
466 impl<T: Ceil, U> Ceil for Size2D<T, U> {
467     /// See [`Size2D::ceil()`](#method.ceil).
468     #[inline]
ceil(self) -> Self469     fn ceil(self) -> Self {
470         (&self).ceil()
471     }
472 }
473 
474 impl<T: Floor, U> Floor for Size2D<T, U> {
475     /// See [`Size2D::floor()`](#method.floor).
476     #[inline]
floor(self) -> Self477     fn floor(self) -> Self {
478         (&self).floor()
479     }
480 }
481 
482 impl<T: Zero, U> Zero for Size2D<T, U> {
483     #[inline]
zero() -> Self484     fn zero() -> Self {
485         Size2D::new(Zero::zero(), Zero::zero())
486     }
487 }
488 
489 
490 impl<T: Neg, U> Neg for Size2D<T, U> {
491     type Output = Size2D<T::Output, U>;
492 
493     #[inline]
neg(self) -> Self::Output494     fn neg(self) -> Self::Output {
495         Size2D::new(-self.width, -self.height)
496     }
497 }
498 
499 
500 impl<T: Add, U> Add for Size2D<T, U> {
501     type Output = Size2D<T::Output, U>;
502 
503     #[inline]
add(self, other: Self) -> Self::Output504     fn add(self, other: Self) -> Self::Output {
505         Size2D::new(self.width + other.width, self.height + other.height)
506     }
507 }
508 
509 impl<T: AddAssign, U> AddAssign for Size2D<T, U> {
510     #[inline]
add_assign(&mut self, other: Self)511     fn add_assign(&mut self, other: Self) {
512         self.width  += other.width;
513         self.height += other.height;
514     }
515 }
516 
517 
518 impl<T: Sub, U> Sub for Size2D<T, U> {
519     type Output = Size2D<T::Output, U>;
520 
521     #[inline]
sub(self, other: Self) -> Self::Output522     fn sub(self, other: Self) -> Self::Output {
523         Size2D::new(self.width - other.width, self.height - other.height)
524     }
525 }
526 
527 impl<T: SubAssign, U> SubAssign for Size2D<T, U> {
528     #[inline]
sub_assign(&mut self, other: Self)529     fn sub_assign(&mut self, other: Self) {
530         self.width  -= other.width;
531         self.height -= other.height;
532     }
533 }
534 
535 
536 impl<T: Clone + Mul, U> Mul<T> for Size2D<T, U> {
537     type Output = Size2D<T::Output, U>;
538 
539     #[inline]
mul(self, scale: T) -> Self::Output540     fn mul(self, scale: T) -> Self::Output {
541         Size2D::new(self.width * scale.clone(), self.height * scale)
542     }
543 }
544 
545 impl<T: Clone + MulAssign, U> MulAssign<T> for Size2D<T, U> {
546     #[inline]
mul_assign(&mut self, other: T)547     fn mul_assign(&mut self, other: T) {
548         self.width  *= other.clone();
549         self.height *= other;
550     }
551 }
552 
553 impl<T: Clone + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size2D<T, U1> {
554     type Output = Size2D<T::Output, U2>;
555 
556     #[inline]
mul(self, scale: Scale<T, U1, U2>) -> Self::Output557     fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
558         Size2D::new(self.width * scale.0.clone(), self.height * scale.0)
559     }
560 }
561 
562 impl<T: Clone + MulAssign, U> MulAssign<Scale<T, U, U>> for Size2D<T, U> {
563     #[inline]
mul_assign(&mut self, other: Scale<T, U, U>)564     fn mul_assign(&mut self, other: Scale<T, U, U>) {
565         *self *= other.0;
566     }
567 }
568 
569 
570 impl<T: Clone + Div, U> Div<T> for Size2D<T, U> {
571     type Output = Size2D<T::Output, U>;
572 
573     #[inline]
div(self, scale: T) -> Self::Output574     fn div(self, scale: T) -> Self::Output {
575         Size2D::new(self.width / scale.clone(), self.height / scale)
576     }
577 }
578 
579 impl<T: Clone + DivAssign, U> DivAssign<T> for Size2D<T, U> {
580     #[inline]
div_assign(&mut self, other: T)581     fn div_assign(&mut self, other: T) {
582         self.width  /= other.clone();
583         self.height /= other;
584     }
585 }
586 
587 impl<T: Clone + Div, U1, U2> Div<Scale<T, U1, U2>> for Size2D<T, U2> {
588     type Output = Size2D<T::Output, U1>;
589 
590     #[inline]
div(self, scale: Scale<T, U1, U2>) -> Self::Output591     fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
592         Size2D::new(self.width / scale.0.clone(), self.height / scale.0)
593     }
594 }
595 
596 impl<T: Clone + DivAssign, U> DivAssign<Scale<T, U, U>> for Size2D<T, U> {
597     #[inline]
div_assign(&mut self, other: Scale<T, U, U>)598     fn div_assign(&mut self, other: Scale<T, U, U>) {
599         *self /= other.0;
600     }
601 }
602 
603 
604 /// Shorthand for `Size2D::new(w, h)`.
605 #[inline]
size2<T, U>(w: T, h: T) -> Size2D<T, U>606 pub const fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
607     Size2D::new(w, h)
608 }
609 
610 #[cfg(feature = "mint")]
611 impl<T, U> From<mint::Vector2<T>> for Size2D<T, U> {
612     #[inline]
from(v: mint::Vector2<T>) -> Self613     fn from(v: mint::Vector2<T>) -> Self {
614         Size2D {
615             width: v.x,
616             height: v.y,
617             _unit: PhantomData,
618         }
619     }
620 }
621 #[cfg(feature = "mint")]
622 impl<T, U> Into<mint::Vector2<T>> for Size2D<T, U> {
623     #[inline]
into(self) -> mint::Vector2<T>624     fn into(self) -> mint::Vector2<T> {
625         mint::Vector2 {
626             x: self.width,
627             y: self.height,
628         }
629     }
630 }
631 
632 impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
633     #[inline]
from(v: Vector2D<T, U>) -> Self634     fn from(v: Vector2D<T, U>) -> Self {
635         size2(v.x, v.y)
636     }
637 }
638 
639 impl<T, U> Into<[T; 2]> for Size2D<T, U> {
640     #[inline]
into(self) -> [T; 2]641     fn into(self) -> [T; 2] {
642         [self.width, self.height]
643     }
644 }
645 
646 impl<T, U> From<[T; 2]> for Size2D<T, U> {
647     #[inline]
from([w, h]: [T; 2]) -> Self648     fn from([w, h]: [T; 2]) -> Self {
649         size2(w, h)
650     }
651 }
652 
653 impl<T, U> Into<(T, T)> for Size2D<T, U> {
654     #[inline]
into(self) -> (T, T)655     fn into(self) -> (T, T) {
656         (self.width, self.height)
657     }
658 }
659 
660 impl<T, U> From<(T, T)> for Size2D<T, U> {
661     #[inline]
from(tuple: (T, T)) -> Self662     fn from(tuple: (T, T)) -> Self {
663         size2(tuple.0, tuple.1)
664     }
665 }
666 
667 #[cfg(test)]
668 mod size2d {
669     use default::Size2D;
670     #[cfg(feature = "mint")]
671     use mint;
672 
673     #[test]
test_area()674     pub fn test_area() {
675         let p = Size2D::new(1.5, 2.0);
676         assert_eq!(p.area(), 3.0);
677     }
678 
679     #[cfg(feature = "mint")]
680     #[test]
test_mint()681     pub fn test_mint() {
682         let s1 = Size2D::new(1.0, 2.0);
683         let sm: mint::Vector2<_> = s1.into();
684         let s2 = Size2D::from(sm);
685 
686         assert_eq!(s1, s2);
687     }
688 
689     mod ops {
690         use default::Size2D;
691         use scale::Scale;
692 
693         pub enum Mm {}
694         pub enum Cm {}
695 
696         pub type Size2DMm<T> = crate::Size2D<T, Mm>;
697         pub type Size2DCm<T> = crate::Size2D<T, Cm>;
698 
699         #[test]
test_neg()700         pub fn test_neg() {
701             assert_eq!(-Size2D::new( 1.0,  2.0), Size2D::new(-1.0, -2.0));
702             assert_eq!(-Size2D::new( 0.0,  0.0), Size2D::new(-0.0, -0.0));
703             assert_eq!(-Size2D::new(-1.0, -2.0), Size2D::new( 1.0,  2.0));
704         }
705 
706 
707         #[test]
test_add()708         pub fn test_add() {
709             let s1 = Size2D::new(1.0, 2.0);
710             let s2 = Size2D::new(3.0, 4.0);
711             assert_eq!(s1 + s2, Size2D::new(4.0, 6.0));
712 
713             let s1 = Size2D::new(1.0, 2.0);
714             let s2 = Size2D::new(0.0, 0.0);
715             assert_eq!(s1 + s2, Size2D::new(1.0, 2.0));
716 
717             let s1 = Size2D::new(1.0, 2.0);
718             let s2 = Size2D::new(-3.0, -4.0);
719             assert_eq!(s1 + s2, Size2D::new(-2.0, -2.0));
720 
721             let s1 = Size2D::new(0.0, 0.0);
722             let s2 = Size2D::new(0.0, 0.0);
723             assert_eq!(s1 + s2, Size2D::new(0.0, 0.0));
724         }
725 
726         #[test]
test_add_assign()727         pub fn test_add_assign() {
728             let mut s = Size2D::new(1.0, 2.0);
729             s += Size2D::new(3.0, 4.0);
730             assert_eq!(s, Size2D::new(4.0, 6.0));
731 
732             let mut s = Size2D::new(1.0, 2.0);
733             s += Size2D::new(0.0, 0.0);
734             assert_eq!(s, Size2D::new(1.0, 2.0));
735 
736             let mut s = Size2D::new(1.0, 2.0);
737             s += Size2D::new(-3.0, -4.0);
738             assert_eq!(s, Size2D::new(-2.0, -2.0));
739 
740             let mut s = Size2D::new(0.0, 0.0);
741             s += Size2D::new(0.0, 0.0);
742             assert_eq!(s, Size2D::new(0.0, 0.0));
743         }
744 
745         #[test]
test_sub()746         pub fn test_sub() {
747             let s1 = Size2D::new(1.0, 2.0);
748             let s2 = Size2D::new(3.0, 4.0);
749             assert_eq!(s1 - s2, Size2D::new(-2.0, -2.0));
750 
751             let s1 = Size2D::new(1.0, 2.0);
752             let s2 = Size2D::new(0.0, 0.0);
753             assert_eq!(s1 - s2, Size2D::new(1.0, 2.0));
754 
755             let s1 = Size2D::new(1.0, 2.0);
756             let s2 = Size2D::new(-3.0, -4.0);
757             assert_eq!(s1 - s2, Size2D::new(4.0, 6.0));
758 
759             let s1 = Size2D::new(0.0, 0.0);
760             let s2 = Size2D::new(0.0, 0.0);
761             assert_eq!(s1 - s2, Size2D::new(0.0, 0.0));
762         }
763 
764         #[test]
test_sub_assign()765         pub fn test_sub_assign() {
766             let mut s = Size2D::new(1.0, 2.0);
767             s -= Size2D::new(3.0, 4.0);
768             assert_eq!(s, Size2D::new(-2.0, -2.0));
769 
770             let mut s = Size2D::new(1.0, 2.0);
771             s -= Size2D::new(0.0, 0.0);
772             assert_eq!(s, Size2D::new(1.0, 2.0));
773 
774             let mut s = Size2D::new(1.0, 2.0);
775             s -= Size2D::new(-3.0, -4.0);
776             assert_eq!(s, Size2D::new(4.0, 6.0));
777 
778             let mut s = Size2D::new(0.0, 0.0);
779             s -= Size2D::new(0.0, 0.0);
780             assert_eq!(s, Size2D::new(0.0, 0.0));
781         }
782 
783 
784         #[test]
test_mul_scalar()785         pub fn test_mul_scalar() {
786             let s1: Size2D<f32> = Size2D::new(3.0, 5.0);
787 
788             let result = s1 * 5.0;
789 
790             assert_eq!(result, Size2D::new(15.0, 25.0));
791         }
792 
793         #[test]
test_mul_assign_scalar()794         pub fn test_mul_assign_scalar() {
795             let mut s1 = Size2D::new(3.0, 5.0);
796 
797             s1 *= 5.0;
798 
799             assert_eq!(s1, Size2D::new(15.0, 25.0));
800         }
801 
802         #[test]
test_mul_scale()803         pub fn test_mul_scale() {
804             let s1 = Size2DMm::new(1.0, 2.0);
805             let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
806 
807             let result = s1 * cm_per_mm;
808 
809             assert_eq!(result, Size2DCm::new(0.1, 0.2));
810         }
811 
812         #[test]
test_mul_assign_scale()813         pub fn test_mul_assign_scale() {
814             let mut s1 = Size2DMm::new(1.0, 2.0);
815             let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
816 
817             s1 *= scale;
818 
819             assert_eq!(s1, Size2DMm::new(0.1, 0.2));
820         }
821 
822 
823         #[test]
test_div_scalar()824         pub fn test_div_scalar() {
825             let s1: Size2D<f32> = Size2D::new(15.0, 25.0);
826 
827             let result = s1 / 5.0;
828 
829             assert_eq!(result, Size2D::new(3.0, 5.0));
830         }
831 
832         #[test]
test_div_assign_scalar()833         pub fn test_div_assign_scalar() {
834             let mut s1: Size2D<f32> = Size2D::new(15.0, 25.0);
835 
836             s1 /= 5.0;
837 
838             assert_eq!(s1, Size2D::new(3.0, 5.0));
839         }
840 
841         #[test]
test_div_scale()842         pub fn test_div_scale() {
843             let s1 = Size2DCm::new(0.1, 0.2);
844             let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
845 
846             let result = s1 / cm_per_mm;
847 
848             assert_eq!(result, Size2DMm::new(1.0, 2.0));
849         }
850 
851         #[test]
test_div_assign_scale()852         pub fn test_div_assign_scale() {
853             let mut s1 = Size2DMm::new(0.1, 0.2);
854             let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
855 
856             s1 /= scale;
857 
858             assert_eq!(s1, Size2DMm::new(1.0, 2.0));
859         }
860     }
861 }
862 
863 
864 
865 /// A 3d size tagged with a unit.
866 #[repr(C)]
867 pub struct Size3D<T, U> {
868     /// The extent of the element in the `U` units along the `x` axis.
869     pub width: T,
870     /// The extent of the element in the `U` units along the `y` axis.
871     pub height: T,
872     /// The extent of the element in the `U` units along the `z` axis.
873     pub depth: T,
874     #[doc(hidden)]
875     pub _unit: PhantomData<U>,
876 }
877 
878 impl<T: Copy, U> Copy for Size3D<T, U> {}
879 
880 impl<T: Clone, U> Clone for Size3D<T, U> {
clone(&self) -> Self881     fn clone(&self) -> Self {
882         Size3D {
883             width: self.width.clone(),
884             height: self.height.clone(),
885             depth: self.depth.clone(),
886             _unit: PhantomData,
887         }
888     }
889 }
890 
891 #[cfg(feature = "serde")]
892 impl<'de, T, U> serde::Deserialize<'de> for Size3D<T, U>
893     where T: serde::Deserialize<'de>
894 {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>895     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
896         where D: serde::Deserializer<'de>
897     {
898         let (width, height, depth) = serde::Deserialize::deserialize(deserializer)?;
899         Ok(Size3D { width, height, depth, _unit: PhantomData })
900     }
901 }
902 
903 #[cfg(feature = "serde")]
904 impl<T, U> serde::Serialize for Size3D<T, U>
905     where T: serde::Serialize
906 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer907     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
908         where S: serde::Serializer
909     {
910         (&self.width, &self.height, &self.depth).serialize(serializer)
911     }
912 }
913 
914 impl<T, U> Eq for Size3D<T, U> where T: Eq {}
915 
916 impl<T, U> PartialEq for Size3D<T, U>
917     where T: PartialEq
918 {
eq(&self, other: &Self) -> bool919     fn eq(&self, other: &Self) -> bool {
920         self.width == other.width && self.height == other.height && self.depth == other.depth
921     }
922 }
923 
924 impl<T, U> Hash for Size3D<T, U>
925     where T: Hash
926 {
hash<H: ::core::hash::Hasher>(&self, h: &mut H)927     fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
928         self.width.hash(h);
929         self.height.hash(h);
930         self.depth.hash(h);
931     }
932 }
933 
934 impl<T: fmt::Debug, U> fmt::Debug for Size3D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result935     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
936         fmt::Debug::fmt(&self.width, f)?;
937         write!(f, "x")?;
938         fmt::Debug::fmt(&self.height, f)?;
939         write!(f, "x")?;
940         fmt::Debug::fmt(&self.depth, f)
941     }
942 }
943 
944 impl<T: fmt::Display, U> fmt::Display for Size3D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result945     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
946         write!(f, "(")?;
947         fmt::Display::fmt(&self.width, f)?;
948         write!(f, "x")?;
949         fmt::Display::fmt(&self.height, f)?;
950         write!(f, "x")?;
951         fmt::Display::fmt(&self.depth, f)?;
952         write!(f, ")")
953     }
954 }
955 
956 impl<T: Default, U> Default for Size3D<T, U> {
default() -> Self957     fn default() -> Self {
958         Size3D::new(Default::default(), Default::default(), Default::default())
959     }
960 }
961 
962 
963 impl<T, U> Size3D<T, U> {
964     /// The same as [`Zero::zero()`] but available without importing trait.
965     ///
966     /// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero
zero() -> Self where T: Zero,967     pub fn zero() -> Self
968     where
969         T: Zero,
970     {
971         Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
972     }
973 
974     /// Constructor taking scalar values.
975     #[inline]
new(width: T, height: T, depth: T) -> Self976     pub const fn new(width: T, height: T, depth: T) -> Self {
977         Size3D {
978             width,
979             height,
980             depth,
981             _unit: PhantomData,
982         }
983     }
984 
985     /// Constructor taking scalar strongly typed lengths.
986     #[inline]
from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self987     pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
988         Size3D::new(width.0, height.0, depth.0)
989     }
990 
991     /// Tag a unitless value with units.
992     #[inline]
from_untyped(p: Size3D<T, UnknownUnit>) -> Self993     pub fn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
994         Size3D::new(p.width, p.height, p.depth)
995     }
996 }
997 
998 impl<T: Copy, U> Size3D<T, U> {
999     /// Return this size as an array of three elements (width, then height, then depth).
1000     #[inline]
to_array(&self) -> [T; 3]1001     pub fn to_array(&self) -> [T; 3] {
1002         [self.width, self.height, self.depth]
1003     }
1004 
1005     /// Return this size as an array of three elements (width, then height, then depth).
1006     #[inline]
to_tuple(&self) -> (T, T, T)1007     pub fn to_tuple(&self) -> (T, T, T) {
1008         (self.width, self.height, self.depth)
1009     }
1010 
1011     /// Return this size as a vector with width, height and depth.
1012     #[inline]
to_vector(&self) -> Vector3D<T, U>1013     pub fn to_vector(&self) -> Vector3D<T, U> {
1014         vec3(self.width, self.height, self.depth)
1015     }
1016 
1017     /// Drop the units, preserving only the numeric value.
1018     #[inline]
to_untyped(&self) -> Size3D<T, UnknownUnit>1019     pub fn to_untyped(&self) -> Size3D<T, UnknownUnit> {
1020         self.cast_unit()
1021     }
1022 
1023     /// Cast the unit
1024     #[inline]
cast_unit<V>(&self) -> Size3D<T, V>1025     pub fn cast_unit<V>(&self) -> Size3D<T, V> {
1026         Size3D::new(self.width, self.height, self.depth)
1027     }
1028 
1029     /// Rounds each component to the nearest integer value.
1030     ///
1031     /// This behavior is preserved for negative values (unlike the basic cast).
1032     ///
1033     /// ```rust
1034     /// # use euclid::size3;
1035     /// enum Mm {}
1036     ///
1037     /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).round(), size3::<_, Mm>(0.0, -1.0, 0.0))
1038     /// ```
1039     #[inline]
1040     #[must_use]
round(&self) -> Self where T: Round,1041     pub fn round(&self) -> Self
1042     where
1043         T: Round,
1044     {
1045         Size3D::new(self.width.round(), self.height.round(), self.depth.round())
1046     }
1047 
1048     /// Rounds each component to the smallest integer equal or greater than the original value.
1049     ///
1050     /// This behavior is preserved for negative values (unlike the basic cast).
1051     ///
1052     /// ```rust
1053     /// # use euclid::size3;
1054     /// enum Mm {}
1055     ///
1056     /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).ceil(), size3::<_, Mm>(0.0, 0.0, 1.0))
1057     /// ```
1058     #[inline]
1059     #[must_use]
ceil(&self) -> Self where T: Ceil,1060     pub fn ceil(&self) -> Self
1061     where
1062         T: Ceil,
1063     {
1064         Size3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
1065     }
1066 
1067     /// Rounds each component to the biggest integer equal or lower than the original value.
1068     ///
1069     /// This behavior is preserved for negative values (unlike the basic cast).
1070     ///
1071     /// ```rust
1072     /// # use euclid::size3;
1073     /// enum Mm {}
1074     ///
1075     /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).floor(), size3::<_, Mm>(-1.0, -1.0, 0.0))
1076     /// ```
1077     #[inline]
1078     #[must_use]
floor(&self) -> Self where T: Floor,1079     pub fn floor(&self) -> Self
1080     where
1081         T: Floor,
1082     {
1083         Size3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
1084     }
1085 
1086     /// Returns result of multiplication of all components
volume(&self) -> T where T: Mul<Output = T>1087     pub fn volume(&self) -> T
1088     where
1089         T: Mul<Output = T>
1090     {
1091         self.width * self.height * self.depth
1092     }
1093 
1094     /// Linearly interpolate between this size and another size.
1095     ///
1096     /// # Example
1097     ///
1098     /// ```rust
1099     /// use euclid::size3;
1100     /// use euclid::default::Size3D;
1101     ///
1102     /// let from: Size3D<_> = size3(0.0, 10.0, -1.0);
1103     /// let to:  Size3D<_> = size3(8.0, -4.0,  0.0);
1104     ///
1105     /// assert_eq!(from.lerp(to, -1.0), size3(-8.0,  24.0, -2.0));
1106     /// assert_eq!(from.lerp(to,  0.0), size3( 0.0,  10.0, -1.0));
1107     /// assert_eq!(from.lerp(to,  0.5), size3( 4.0,   3.0, -0.5));
1108     /// assert_eq!(from.lerp(to,  1.0), size3( 8.0,  -4.0,  0.0));
1109     /// assert_eq!(from.lerp(to,  2.0), size3(16.0, -18.0,  1.0));
1110     /// ```
1111     #[inline]
lerp(&self, other: Self, t: T) -> Self where T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,1112     pub fn lerp(&self, other: Self, t: T) -> Self
1113     where
1114         T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
1115     {
1116         let one_t = T::one() - t;
1117         (*self) * one_t + other * t
1118     }
1119 }
1120 
1121 impl<T: NumCast + Copy, U> Size3D<T, U> {
1122     /// Cast from one numeric representation to another, preserving the units.
1123     ///
1124     /// When casting from floating point to integer coordinates, the decimals are truncated
1125     /// as one would expect from a simple cast, but this behavior does not always make sense
1126     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
1127     #[inline]
cast<NewT: NumCast>(&self) -> Size3D<NewT, U>1128     pub fn cast<NewT: NumCast>(&self) -> Size3D<NewT, U> {
1129         self.try_cast().unwrap()
1130     }
1131 
1132     /// Fallible cast from one numeric representation to another, preserving the units.
1133     ///
1134     /// When casting from floating point to integer coordinates, the decimals are truncated
1135     /// as one would expect from a simple cast, but this behavior does not always make sense
1136     /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
try_cast<NewT: NumCast>(&self) -> Option<Size3D<NewT, U>>1137     pub fn try_cast<NewT: NumCast>(&self) -> Option<Size3D<NewT, U>> {
1138         match (NumCast::from(self.width), NumCast::from(self.height), NumCast::from(self.depth)) {
1139             (Some(w), Some(h), Some(d)) => Some(Size3D::new(w, h, d)),
1140             _ => None,
1141         }
1142     }
1143 
1144     // Convenience functions for common casts
1145 
1146     /// Cast into an `f32` size.
1147     #[inline]
to_f32(&self) -> Size3D<f32, U>1148     pub fn to_f32(&self) -> Size3D<f32, U> {
1149         self.cast()
1150     }
1151 
1152     /// Cast into an `f64` size.
1153     #[inline]
to_f64(&self) -> Size3D<f64, U>1154     pub fn to_f64(&self) -> Size3D<f64, U> {
1155         self.cast()
1156     }
1157 
1158     /// Cast into an `uint` size, truncating decimals if any.
1159     ///
1160     /// When casting from floating point sizes, it is worth considering whether
1161     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1162     /// the desired conversion behavior.
1163     #[inline]
to_usize(&self) -> Size3D<usize, U>1164     pub fn to_usize(&self) -> Size3D<usize, U> {
1165         self.cast()
1166     }
1167 
1168     /// Cast into an `u32` size, truncating decimals if any.
1169     ///
1170     /// When casting from floating point sizes, it is worth considering whether
1171     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1172     /// the desired conversion behavior.
1173     #[inline]
to_u32(&self) -> Size3D<u32, U>1174     pub fn to_u32(&self) -> Size3D<u32, U> {
1175         self.cast()
1176     }
1177 
1178     /// Cast into an `i32` size, truncating decimals if any.
1179     ///
1180     /// When casting from floating point sizes, it is worth considering whether
1181     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1182     /// the desired conversion behavior.
1183     #[inline]
to_i32(&self) -> Size3D<i32, U>1184     pub fn to_i32(&self) -> Size3D<i32, U> {
1185         self.cast()
1186     }
1187 
1188     /// Cast into an `i64` size, truncating decimals if any.
1189     ///
1190     /// When casting from floating point sizes, it is worth considering whether
1191     /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1192     /// the desired conversion behavior.
1193     #[inline]
to_i64(&self) -> Size3D<i64, U>1194     pub fn to_i64(&self) -> Size3D<i64, U> {
1195         self.cast()
1196     }
1197 }
1198 
1199 impl<T: Signed, U> Size3D<T, U> {
1200     /// Computes the absolute value of each component.
1201     ///
1202     /// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`.
1203     ///
1204     /// For signed integers, `::MIN` will be returned for component if the component is `::MIN`.
abs(&self) -> Self1205     pub fn abs(&self) -> Self {
1206         size3(self.width.abs(), self.height.abs(), self.depth.abs())
1207     }
1208 
1209     /// Returns `true` if all components is positive and `false` any component is zero or negative.
is_positive(&self) -> bool1210     pub fn is_positive(&self) -> bool {
1211         self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
1212     }
1213 }
1214 
1215 impl<T: PartialOrd, U> Size3D<T, U> {
1216     /// Returns the size each component of which are minimum of this size and another.
1217     #[inline]
min(self, other: Self) -> Self1218     pub fn min(self, other: Self) -> Self {
1219         size3(
1220             min(self.width,  other.width),
1221             min(self.height, other.height),
1222             min(self.depth,  other.depth),
1223         )
1224     }
1225 
1226     /// Returns the size each component of which are maximum of this size and another.
1227     #[inline]
max(self, other: Self) -> Self1228     pub fn max(self, other: Self) -> Self {
1229         size3(
1230             max(self.width,  other.width),
1231             max(self.height, other.height),
1232             max(self.depth,  other.depth),
1233         )
1234     }
1235 
1236     /// Returns the size each component of which clamped by corresponding
1237     /// components of `start` and `end`.
1238     ///
1239     /// Shortcut for `self.max(start).min(end)`.
1240     #[inline]
clamp(&self, start: Self, end: Self) -> Self where T: Copy,1241     pub fn clamp(&self, start: Self, end: Self) -> Self
1242     where
1243         T: Copy,
1244     {
1245         self.max(start).min(end)
1246     }
1247 
1248     /// Returns vector with results of "greater than" operation on each component.
greater_than(&self, other: Self) -> BoolVector3D1249     pub fn greater_than(&self, other: Self) -> BoolVector3D {
1250         BoolVector3D {
1251             x: self.width > other.width,
1252             y: self.height > other.height,
1253             z: self.depth > other.depth,
1254         }
1255     }
1256 
1257     /// Returns vector with results of "lower than" operation on each component.
lower_than(&self, other: Self) -> BoolVector3D1258     pub fn lower_than(&self, other: Self) -> BoolVector3D {
1259         BoolVector3D {
1260             x: self.width < other.width,
1261             y: self.height < other.height,
1262             z: self.depth < other.depth,
1263         }
1264     }
1265 
1266     /// Returns `true` if any component of size is zero or negative.
is_empty_or_negative(&self) -> bool where T: Zero,1267     pub fn is_empty_or_negative(&self) -> bool
1268     where
1269         T: Zero,
1270     {
1271         let zero = T::zero();
1272         self.width <= zero || self.height <= zero || self.depth <= zero
1273     }
1274 }
1275 
1276 impl<T: PartialEq, U> Size3D<T, U> {
1277     /// Returns vector with results of "equal" operation on each component.
equal(&self, other: Self) -> BoolVector3D1278     pub fn equal(&self, other: Self) -> BoolVector3D {
1279         BoolVector3D {
1280             x: self.width == other.width,
1281             y: self.height == other.height,
1282             z: self.depth == other.depth,
1283         }
1284     }
1285 
1286     /// Returns vector with results of "not equal" operation on each component.
not_equal(&self, other: Self) -> BoolVector3D1287     pub fn not_equal(&self, other: Self) -> BoolVector3D {
1288         BoolVector3D {
1289             x: self.width != other.width,
1290             y: self.height != other.height,
1291             z: self.depth != other.depth,
1292         }
1293     }
1294 }
1295 
1296 
1297 impl<T: Round, U> Round for Size3D<T, U> {
1298     /// See [`Size3D::round()`](#method.round).
1299     #[inline]
round(self) -> Self1300     fn round(self) -> Self {
1301         (&self).round()
1302     }
1303 }
1304 
1305 impl<T: Ceil, U> Ceil for Size3D<T, U> {
1306     /// See [`Size3D::ceil()`](#method.ceil).
1307     #[inline]
ceil(self) -> Self1308     fn ceil(self) -> Self {
1309         (&self).ceil()
1310     }
1311 }
1312 
1313 impl<T: Floor, U> Floor for Size3D<T, U> {
1314     /// See [`Size3D::floor()`](#method.floor).
1315     #[inline]
floor(self) -> Self1316     fn floor(self) -> Self {
1317         (&self).floor()
1318     }
1319 }
1320 
1321 impl<T: Zero, U> Zero for Size3D<T, U> {
1322     #[inline]
zero() -> Self1323     fn zero() -> Self {
1324         Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
1325     }
1326 }
1327 
1328 
1329 impl<T: Neg, U> Neg for Size3D<T, U> {
1330     type Output = Size3D<T::Output, U>;
1331 
1332     #[inline]
neg(self) -> Self::Output1333     fn neg(self) -> Self::Output {
1334         Size3D::new(-self.width, -self.height, -self.depth)
1335     }
1336 }
1337 
1338 
1339 impl<T: Add, U> Add for Size3D<T, U> {
1340     type Output = Size3D<T::Output, U>;
1341 
1342     #[inline]
add(self, other: Self) -> Self::Output1343     fn add(self, other: Self) -> Self::Output {
1344         Size3D::new(self.width + other.width, self.height + other.height, self.depth + other.depth)
1345     }
1346 }
1347 
1348 impl<T: AddAssign, U> AddAssign for Size3D<T, U> {
1349     #[inline]
add_assign(&mut self, other: Self)1350     fn add_assign(&mut self, other: Self) {
1351         self.width  += other.width;
1352         self.height += other.height;
1353         self.depth  += other.depth;
1354     }
1355 }
1356 
1357 
1358 impl<T: Sub, U> Sub for Size3D<T, U> {
1359     type Output = Size3D<T::Output, U>;
1360 
1361     #[inline]
sub(self, other: Self) -> Self::Output1362     fn sub(self, other: Self) -> Self::Output {
1363         Size3D::new(self.width - other.width, self.height - other.height, self.depth - other.depth)
1364     }
1365 }
1366 
1367 impl<T: SubAssign, U> SubAssign for Size3D<T, U> {
1368     #[inline]
sub_assign(&mut self, other: Self)1369     fn sub_assign(&mut self, other: Self) {
1370         self.width  -= other.width;
1371         self.height -= other.height;
1372         self.depth  -= other.depth;
1373     }
1374 }
1375 
1376 
1377 impl<T: Clone + Mul, U> Mul<T> for Size3D<T, U> {
1378     type Output = Size3D<T::Output, U>;
1379 
1380     #[inline]
mul(self, scale: T) -> Self::Output1381     fn mul(self, scale: T) -> Self::Output {
1382         Size3D::new(
1383             self.width  * scale.clone(),
1384             self.height * scale.clone(),
1385             self.depth  * scale
1386         )
1387     }
1388 }
1389 
1390 impl<T: Clone + MulAssign, U> MulAssign<T> for Size3D<T, U> {
1391     #[inline]
mul_assign(&mut self, other: T)1392     fn mul_assign(&mut self, other: T) {
1393         self.width  *= other.clone();
1394         self.height *= other.clone();
1395         self.depth  *= other;
1396     }
1397 }
1398 
1399 impl<T: Clone + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size3D<T, U1> {
1400     type Output = Size3D<T::Output, U2>;
1401 
1402     #[inline]
mul(self, scale: Scale<T, U1, U2>) -> Self::Output1403     fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
1404         Size3D::new(
1405             self.width  * scale.0.clone(),
1406             self.height * scale.0.clone(),
1407             self.depth  * scale.0
1408         )
1409     }
1410 }
1411 
1412 impl<T: Clone + MulAssign, U> MulAssign<Scale<T, U, U>> for Size3D<T, U> {
1413     #[inline]
mul_assign(&mut self, other: Scale<T, U, U>)1414     fn mul_assign(&mut self, other: Scale<T, U, U>) {
1415         *self *= other.0;
1416     }
1417 }
1418 
1419 
1420 impl<T: Clone + Div, U> Div<T> for Size3D<T, U> {
1421     type Output = Size3D<T::Output, U>;
1422 
1423     #[inline]
div(self, scale: T) -> Self::Output1424     fn div(self, scale: T) -> Self::Output {
1425         Size3D::new(
1426             self.width  / scale.clone(),
1427             self.height / scale.clone(),
1428             self.depth  / scale
1429         )
1430     }
1431 }
1432 
1433 impl<T: Clone + DivAssign, U> DivAssign<T> for Size3D<T, U> {
1434     #[inline]
div_assign(&mut self, other: T)1435     fn div_assign(&mut self, other: T) {
1436         self.width  /= other.clone();
1437         self.height /= other.clone();
1438         self.depth  /= other;
1439     }
1440 }
1441 
1442 impl<T: Clone + Div, U1, U2> Div<Scale<T, U1, U2>> for Size3D<T, U2> {
1443     type Output = Size3D<T::Output, U1>;
1444 
1445     #[inline]
div(self, scale: Scale<T, U1, U2>) -> Self::Output1446     fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
1447         Size3D::new(
1448             self.width  / scale.0.clone(),
1449             self.height / scale.0.clone(),
1450             self.depth  / scale.0
1451         )
1452     }
1453 }
1454 
1455 impl<T: Clone + DivAssign, U> DivAssign<Scale<T, U, U>> for Size3D<T, U> {
1456     #[inline]
div_assign(&mut self, other: Scale<T, U, U>)1457     fn div_assign(&mut self, other: Scale<T, U, U>) {
1458         *self /= other.0;
1459     }
1460 }
1461 
1462 
1463 #[cfg(feature = "mint")]
1464 impl<T, U> From<mint::Vector3<T>> for Size3D<T, U> {
1465     #[inline]
from(v: mint::Vector3<T>) -> Self1466     fn from(v: mint::Vector3<T>) -> Self {
1467         size3(v.x, v.y, v.z)
1468     }
1469 }
1470 #[cfg(feature = "mint")]
1471 impl<T, U> Into<mint::Vector3<T>> for Size3D<T, U> {
1472     #[inline]
into(self) -> mint::Vector3<T>1473     fn into(self) -> mint::Vector3<T> {
1474         mint::Vector3 {
1475             x: self.width,
1476             y: self.height,
1477             z: self.depth,
1478         }
1479     }
1480 }
1481 
1482 impl<T, U> From<Vector3D<T, U>> for Size3D<T, U> {
1483     #[inline]
from(v: Vector3D<T, U>) -> Self1484     fn from(v: Vector3D<T, U>) -> Self {
1485         size3(v.x, v.y, v.z)
1486     }
1487 }
1488 
1489 impl<T, U> Into<[T; 3]> for Size3D<T, U> {
1490     #[inline]
into(self) -> [T; 3]1491     fn into(self) -> [T; 3] {
1492         [self.width, self.height, self.depth]
1493     }
1494 }
1495 
1496 impl<T, U> From<[T; 3]> for Size3D<T, U> {
1497     #[inline]
from([w, h, d]: [T; 3]) -> Self1498     fn from([w, h, d]: [T; 3]) -> Self {
1499         size3(w, h, d)
1500     }
1501 }
1502 
1503 impl<T, U> Into<(T, T, T)> for Size3D<T, U> {
1504     #[inline]
into(self) -> (T, T, T)1505     fn into(self) -> (T, T, T) {
1506         (self.width, self.height, self.depth)
1507     }
1508 }
1509 
1510 impl<T, U> From<(T, T, T)> for Size3D<T, U> {
1511     #[inline]
from(tuple: (T, T, T)) -> Self1512     fn from(tuple: (T, T, T)) -> Self {
1513         size3(tuple.0, tuple.1, tuple.2)
1514     }
1515 }
1516 
1517 
1518 /// Shorthand for `Size3D::new(w, h, d)`.
1519 #[inline]
size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U>1520 pub const fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
1521     Size3D::new(w, h, d)
1522 }
1523 
1524 #[cfg(test)]
1525 mod size3d {
1526     mod ops {
1527         use default::Size3D;
1528         use scale::Scale;
1529 
1530         pub enum Mm {}
1531         pub enum Cm {}
1532 
1533         pub type Size3DMm<T> = crate::Size3D<T, Mm>;
1534         pub type Size3DCm<T> = crate::Size3D<T, Cm>;
1535 
1536         #[test]
test_neg()1537         pub fn test_neg() {
1538             assert_eq!(-Size3D::new( 1.0,  2.0,  3.0), Size3D::new(-1.0, -2.0, -3.0));
1539             assert_eq!(-Size3D::new( 0.0,  0.0,  0.0), Size3D::new(-0.0, -0.0, -0.0));
1540             assert_eq!(-Size3D::new(-1.0, -2.0, -3.0), Size3D::new( 1.0,  2.0,  3.0));
1541         }
1542 
1543 
1544         #[test]
test_add()1545         pub fn test_add() {
1546             let s1 = Size3D::new(1.0, 2.0, 3.0);
1547             let s2 = Size3D::new(4.0, 5.0, 6.0);
1548             assert_eq!(s1 + s2, Size3D::new(5.0, 7.0, 9.0));
1549 
1550             let s1 = Size3D::new(1.0, 2.0, 3.0);
1551             let s2 = Size3D::new(0.0, 0.0, 0.0);
1552             assert_eq!(s1 + s2, Size3D::new(1.0, 2.0, 3.0));
1553 
1554             let s1 = Size3D::new( 1.0,  2.0,  3.0);
1555             let s2 = Size3D::new(-4.0, -5.0, -6.0);
1556             assert_eq!(s1 + s2, Size3D::new(-3.0, -3.0, -3.0));
1557 
1558             let s1 = Size3D::new(0.0, 0.0, 0.0);
1559             let s2 = Size3D::new(0.0, 0.0, 0.0);
1560             assert_eq!(s1 + s2, Size3D::new(0.0, 0.0, 0.0));
1561         }
1562 
1563         #[test]
test_add_assign()1564         pub fn test_add_assign() {
1565             let mut s = Size3D::new(1.0, 2.0, 3.0);
1566             s += Size3D::new(4.0, 5.0, 6.0);
1567             assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1568 
1569             let mut s = Size3D::new(1.0, 2.0, 3.0);
1570             s += Size3D::new(0.0, 0.0, 0.0);
1571             assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1572 
1573             let mut s = Size3D::new( 1.0,  2.0,  3.0);
1574             s += Size3D::new(-4.0, -5.0, -6.0);
1575             assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1576 
1577             let mut s = Size3D::new(0.0, 0.0, 0.0);
1578             s += Size3D::new(0.0, 0.0, 0.0);
1579             assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1580         }
1581 
1582         #[test]
test_sub()1583         pub fn test_sub() {
1584             let s1 = Size3D::new(1.0, 2.0, 3.0);
1585             let s2 = Size3D::new(4.0, 5.0, 6.0);
1586             assert_eq!(s1 - s2, Size3D::new(-3.0, -3.0, -3.0));
1587 
1588             let s1 = Size3D::new(1.0, 2.0, 3.0);
1589             let s2 = Size3D::new(0.0, 0.0, 0.0);
1590             assert_eq!(s1 - s2, Size3D::new(1.0, 2.0, 3.0));
1591 
1592             let s1 = Size3D::new( 1.0,  2.0,  3.0);
1593             let s2 = Size3D::new(-4.0, -5.0, -6.0);
1594             assert_eq!(s1 - s2, Size3D::new(5.0, 7.0, 9.0));
1595 
1596             let s1 = Size3D::new(0.0, 0.0, 0.0);
1597             let s2 = Size3D::new(0.0, 0.0, 0.0);
1598             assert_eq!(s1 - s2, Size3D::new(0.0, 0.0, 0.0));
1599         }
1600 
1601         #[test]
test_sub_assign()1602         pub fn test_sub_assign() {
1603             let mut s = Size3D::new(1.0, 2.0, 3.0);
1604             s -= Size3D::new(4.0, 5.0, 6.0);
1605             assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1606 
1607             let mut s = Size3D::new(1.0, 2.0, 3.0);
1608             s -= Size3D::new(0.0, 0.0, 0.0);
1609             assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1610 
1611             let mut s = Size3D::new( 1.0,  2.0,  3.0);
1612             s -= Size3D::new(-4.0, -5.0, -6.0);
1613             assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1614 
1615             let mut s = Size3D::new(0.0, 0.0, 0.0);
1616             s -= Size3D::new(0.0, 0.0, 0.0);
1617             assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1618         }
1619 
1620 
1621         #[test]
test_mul_scalar()1622         pub fn test_mul_scalar() {
1623             let s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1624 
1625             let result = s1 * 5.0;
1626 
1627             assert_eq!(result, Size3D::new(15.0, 25.0, 35.0));
1628         }
1629 
1630         #[test]
test_mul_assign_scalar()1631         pub fn test_mul_assign_scalar() {
1632             let mut s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1633 
1634             s1 *= 5.0;
1635 
1636             assert_eq!(s1, Size3D::new(15.0, 25.0, 35.0));
1637         }
1638 
1639         #[test]
test_mul_scale()1640         pub fn test_mul_scale() {
1641             let s1 = Size3DMm::new(1.0, 2.0, 3.0);
1642             let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1643 
1644             let result = s1 * cm_per_mm;
1645 
1646             assert_eq!(result, Size3DCm::new(0.1, 0.2, 0.3));
1647         }
1648 
1649         #[test]
test_mul_assign_scale()1650         pub fn test_mul_assign_scale() {
1651             let mut s1 = Size3DMm::new(1.0, 2.0, 3.0);
1652             let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1653 
1654             s1 *= scale;
1655 
1656             assert_eq!(s1, Size3DMm::new(0.1, 0.2, 0.3));
1657         }
1658 
1659 
1660         #[test]
test_div_scalar()1661         pub fn test_div_scalar() {
1662             let s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1663 
1664             let result = s1 / 5.0;
1665 
1666             assert_eq!(result, Size3D::new(3.0, 5.0, 7.0));
1667         }
1668 
1669         #[test]
test_div_assign_scalar()1670         pub fn test_div_assign_scalar() {
1671             let mut s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1672 
1673             s1 /= 5.0;
1674 
1675             assert_eq!(s1, Size3D::new(3.0, 5.0, 7.0));
1676         }
1677 
1678         #[test]
test_div_scale()1679         pub fn test_div_scale() {
1680             let s1 = Size3DCm::new(0.1, 0.2, 0.3);
1681             let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1682 
1683             let result = s1 / cm_per_mm;
1684 
1685             assert_eq!(result, Size3DMm::new(1.0, 2.0, 3.0));
1686         }
1687 
1688         #[test]
test_div_assign_scale()1689         pub fn test_div_assign_scale() {
1690             let mut s1 = Size3DMm::new(0.1, 0.2, 0.3);
1691             let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1692 
1693             s1 /= scale;
1694 
1695             assert_eq!(s1, Size3DMm::new(1.0, 2.0, 3.0));
1696         }
1697     }
1698 }