// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms.
use core::cmp::{Eq, PartialEq}; use core::fmt; use core::hash::Hash; use core::iter::Sum; use core::marker::PhantomData; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
#[cfg(feature = "bytemuck")] use bytemuck::{Pod, Zeroable}; #[cfg(feature = "mint")] use mint; use num_traits::{Float, NumCast, Signed}; #[cfg(feature = "serde")] use serde;
/// A 2d size tagged with a unit. #[repr(C)] pubstruct Size2D<T, U> { /// The extent of the element in the `U` units along the `x` axis (usually horizontal). pub width: T, /// The extent of the element in the `U` units along the `y` axis (usually vertical). pub height: T, #[doc(hidden)] pub _unit: PhantomData<U>,
}
impl<T, U> Size2D<T, U> { /// The same as [`Zero::zero()`] but available without importing trait. /// /// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero #[inline] pubfn zero() -> Self where
T: Zero,
{
Size2D::new(Zero::zero(), Zero::zero())
}
/// Constructor setting all components to the same value. #[inline] pubfn splat(v: T) -> Self where
T: Clone,
{
Size2D {
width: v.clone(),
height: v,
_unit: PhantomData,
}
}
/// Tag a unitless value with units. #[inline] pubfn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
Size2D::new(p.width, p.height)
}
}
impl<T: Copy, U> Size2D<T, U> { /// Return this size as an array of two elements (width, then height). #[inline] pubfn to_array(self) -> [T; 2] {
[self.width, self.height]
}
/// Return this size as a tuple of two elements (width, then height). #[inline] pubfn to_tuple(self) -> (T, T) {
(self.width, self.height)
}
/// Return this size as a vector with width and height. #[inline] pubfn to_vector(self) -> Vector2D<T, U> {
vec2(self.width, self.height)
}
/// Drop the units, preserving only the numeric value. #[inline] pubfn to_untyped(self) -> Size2D<T, UnknownUnit> { self.cast_unit()
}
/// Cast the unit #[inline] pubfn cast_unit<V>(self) -> Size2D<T, V> {
Size2D::new(self.width, self.height)
}
/// Rounds each component to the nearest integer value. /// /// This behavior is preserved for negative values (unlike the basic cast). /// /// ```rust /// # use euclid::size2; /// enum Mm {} /// /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).round(), size2::<_, Mm>(0.0, -1.0)) /// ``` #[inline] #[must_use] pubfn round(self) -> Self where
T: Round,
{
Size2D::new(self.width.round(), self.height.round())
}
/// Rounds each component to the smallest integer equal or greater than the original value. /// /// This behavior is preserved for negative values (unlike the basic cast). /// /// ```rust /// # use euclid::size2; /// enum Mm {} /// /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).ceil(), size2::<_, Mm>(0.0, 0.0)) /// ``` #[inline] #[must_use] pubfn ceil(self) -> Self where
T: Ceil,
{
Size2D::new(self.width.ceil(), self.height.ceil())
}
/// Rounds each component to the biggest integer equal or lower than the original value. /// /// This behavior is preserved for negative values (unlike the basic cast). /// /// ```rust /// # use euclid::size2; /// enum Mm {} /// /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).floor(), size2::<_, Mm>(-1.0, -1.0)) /// ``` #[inline] #[must_use] pubfn floor(self) -> Self where
T: Floor,
{
Size2D::new(self.width.floor(), self.height.floor())
}
/// Returns result of multiplication of both components pubfn area(self) -> T::Output where
T: Mul,
{ self.width * self.height
}
/// Linearly interpolate each component between this size and another size. /// /// # Example /// /// ```rust /// use euclid::size2; /// use euclid::default::Size2D; /// /// let from: Size2D<_> = size2(0.0, 10.0); /// let to: Size2D<_> = size2(8.0, -4.0); /// /// assert_eq!(from.lerp(to, -1.0), size2(-8.0, 24.0)); /// assert_eq!(from.lerp(to, 0.0), size2( 0.0, 10.0)); /// assert_eq!(from.lerp(to, 0.5), size2( 4.0, 3.0)); /// assert_eq!(from.lerp(to, 1.0), size2( 8.0, -4.0)); /// assert_eq!(from.lerp(to, 2.0), size2(16.0, -18.0)); /// ``` #[inline] pubfn lerp(self, other: Self, t: T) -> Self where
T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
{ let one_t = T::one() - t; self * one_t + other * t
}
}
impl<T: NumCast + Copy, U> Size2D<T, U> { /// Cast from one numeric representation to another, preserving the units. /// /// When casting from floating point to integer coordinates, the decimals are truncated /// as one would expect from a simple cast, but this behavior does not always make sense /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. #[inline] pubfn cast<NewT: NumCast>(self) -> Size2D<NewT, U> { self.try_cast().unwrap()
}
/// Fallible cast from one numeric representation to another, preserving the units. /// /// When casting from floating point to integer coordinates, the decimals are truncated /// as one would expect from a simple cast, but this behavior does not always make sense /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. pubfn try_cast<NewT: NumCast>(self) -> Option<Size2D<NewT, U>> { match (NumCast::from(self.width), NumCast::from(self.height)) {
(Some(w), Some(h)) => Some(Size2D::new(w, h)),
_ => None,
}
}
// Convenience functions for common casts
/// Cast into an `f32` size. #[inline] pubfn to_f32(self) -> Size2D<f32, U> { self.cast()
}
/// Cast into an `f64` size. #[inline] pubfn to_f64(self) -> Size2D<f64, U> { self.cast()
}
/// Cast into an `uint` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_usize(self) -> Size2D<usize, U> { self.cast()
}
/// Cast into an `u32` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_u32(self) -> Size2D<u32, U> { self.cast()
}
/// Cast into an `u64` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_u64(self) -> Size2D<u64, U> { self.cast()
}
/// Cast into an `i32` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_i32(self) -> Size2D<i32, U> { self.cast()
}
/// Cast into an `i64` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_i64(self) -> Size2D<i64, U> { self.cast()
}
}
impl<T: Float, U> Size2D<T, U> { /// Returns true if all members are finite. #[inline] pubfn is_finite(self) -> bool { self.width.is_finite() && self.height.is_finite()
}
}
impl<T: Signed, U> Size2D<T, U> { /// Computes the absolute value of each component. /// /// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`. /// /// For signed integers, `::MIN` will be returned for component if the component is `::MIN`. pubfn abs(self) -> Self {
size2(self.width.abs(), self.height.abs())
}
/// Returns `true` if both components is positive and `false` any component is zero or negative. pubfn is_positive(self) -> bool { self.width.is_positive() && self.height.is_positive()
}
}
impl<T: PartialOrd, U> Size2D<T, U> { /// Returns the size each component of which are minimum of this size and another. #[inline] pubfn min(self, other: Self) -> Self {
size2(min(self.width, other.width), min(self.height, other.height))
}
/// Returns the size each component of which are maximum of this size and another. #[inline] pubfn max(self, other: Self) -> Self {
size2(max(self.width, other.width), max(self.height, other.height))
}
/// Returns the size each component of which clamped by corresponding /// components of `start` and `end`. /// /// Shortcut for `self.max(start).min(end)`. #[inline] pubfn clamp(self, start: Self, end: Self) -> Self where
T: Copy,
{ self.max(start).min(end)
}
// Returns true if this size is larger or equal to the other size in all dimensions. #[inline] pubfn contains(self, other: Self) -> bool { self.width >= other.width && self.height >= other.height
}
/// Returns vector with results of "greater then" operation on each component. pubfn greater_than(self, other: Self) -> BoolVector2D {
BoolVector2D {
x: self.width > other.width,
y: self.height > other.height,
}
}
/// Returns vector with results of "lower then" operation on each component. pubfn lower_than(self, other: Self) -> BoolVector2D {
BoolVector2D {
x: self.width < other.width,
y: self.height < other.height,
}
}
/// Returns `true` if any component of size is zero, negative, or NaN. pubfn is_empty(self) -> bool where
T: Zero,
{ let zero = T::zero(); // The condition is expressed this way so that we return true in // the presence of NaN.
!(self.width > zero && self.height > zero)
}
}
impl<T: PartialEq, U> Size2D<T, U> { /// Returns vector with results of "equal" operation on each component. pubfn equal(self, other: Self) -> BoolVector2D {
BoolVector2D {
x: self.width == other.width,
y: self.height == other.height,
}
}
/// Returns vector with results of "not equal" operation on each component. pubfn not_equal(self, other: Self) -> BoolVector2D {
BoolVector2D {
x: self.width != other.width,
y: self.height != other.height,
}
}
}
impl<T: Round, U> Round for Size2D<T, U> { /// See [`Size2D::round()`](#method.round). #[inline] fn round(self) -> Self { self.round()
}
}
impl<T: Ceil, U> Ceil for Size2D<T, U> { /// See [`Size2D::ceil()`](#method.ceil). #[inline] fn ceil(self) -> Self { self.ceil()
}
}
impl<T: Floor, U> Floor for Size2D<T, U> { /// See [`Size2D::floor()`](#method.floor). #[inline] fn floor(self) -> Self { self.floor()
}
}
impl<T: Zero, U> Zero for Size2D<T, U> { #[inline] fn zero() -> Self {
Size2D::new(Zero::zero(), Zero::zero())
}
}
impl<T: Neg, U> Neg for Size2D<T, U> { type Output = Size2D<T::Output, U>;
/// A 3d size tagged with a unit. #[repr(C)] pubstruct Size3D<T, U> { /// The extent of the element in the `U` units along the `x` axis. pub width: T, /// The extent of the element in the `U` units along the `y` axis. pub height: T, /// The extent of the element in the `U` units along the `z` axis. pub depth: T, #[doc(hidden)] pub _unit: PhantomData<U>,
}
impl<T, U> Size3D<T, U> { /// The same as [`Zero::zero()`] but available without importing trait. /// /// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero pubfn zero() -> Self where
T: Zero,
{
Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
}
/// Constructor setting all components to the same value. #[inline] pubfn splat(v: T) -> Self where
T: Clone,
{
Size3D {
width: v.clone(),
height: v.clone(),
depth: v,
_unit: PhantomData,
}
}
/// Tag a unitless value with units. #[inline] pubfn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
Size3D::new(p.width, p.height, p.depth)
}
}
impl<T: Copy, U> Size3D<T, U> { /// Return this size as an array of three elements (width, then height, then depth). #[inline] pubfn to_array(self) -> [T; 3] {
[self.width, self.height, self.depth]
}
/// Return this size as an array of three elements (width, then height, then depth). #[inline] pubfn to_tuple(self) -> (T, T, T) {
(self.width, self.height, self.depth)
}
/// Return this size as a vector with width, height and depth. #[inline] pubfn to_vector(self) -> Vector3D<T, U> {
vec3(self.width, self.height, self.depth)
}
/// Drop the units, preserving only the numeric value. #[inline] pubfn to_untyped(self) -> Size3D<T, UnknownUnit> { self.cast_unit()
}
/// Cast the unit #[inline] pubfn cast_unit<V>(self) -> Size3D<T, V> {
Size3D::new(self.width, self.height, self.depth)
}
/// Rounds each component to the nearest integer value. /// /// This behavior is preserved for negative values (unlike the basic cast). /// /// ```rust /// # use euclid::size3; /// enum Mm {} /// /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).round(), size3::<_, Mm>(0.0, -1.0, 0.0)) /// ``` #[inline] #[must_use] pubfn round(self) -> Self where
T: Round,
{
Size3D::new(self.width.round(), self.height.round(), self.depth.round())
}
/// Rounds each component to the smallest integer equal or greater than the original value. /// /// This behavior is preserved for negative values (unlike the basic cast). /// /// ```rust /// # use euclid::size3; /// enum Mm {} /// /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).ceil(), size3::<_, Mm>(0.0, 0.0, 1.0)) /// ``` #[inline] #[must_use] pubfn ceil(self) -> Self where
T: Ceil,
{
Size3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
}
/// Rounds each component to the biggest integer equal or lower than the original value. /// /// This behavior is preserved for negative values (unlike the basic cast). /// /// ```rust /// # use euclid::size3; /// enum Mm {} /// /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).floor(), size3::<_, Mm>(-1.0, -1.0, 0.0)) /// ``` #[inline] #[must_use] pubfn floor(self) -> Self where
T: Floor,
{
Size3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
}
/// Returns result of multiplication of all components pubfn volume(self) -> T where
T: Mul<Output = T>,
{ self.width * self.height * self.depth
}
/// Linearly interpolate between this size and another size. /// /// # Example /// /// ```rust /// use euclid::size3; /// use euclid::default::Size3D; /// /// let from: Size3D<_> = size3(0.0, 10.0, -1.0); /// let to: Size3D<_> = size3(8.0, -4.0, 0.0); /// /// assert_eq!(from.lerp(to, -1.0), size3(-8.0, 24.0, -2.0)); /// assert_eq!(from.lerp(to, 0.0), size3( 0.0, 10.0, -1.0)); /// assert_eq!(from.lerp(to, 0.5), size3( 4.0, 3.0, -0.5)); /// assert_eq!(from.lerp(to, 1.0), size3( 8.0, -4.0, 0.0)); /// assert_eq!(from.lerp(to, 2.0), size3(16.0, -18.0, 1.0)); /// ``` #[inline] pubfn lerp(self, other: Self, t: T) -> Self where
T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
{ let one_t = T::one() - t; self * one_t + other * t
}
}
impl<T: NumCast + Copy, U> Size3D<T, U> { /// Cast from one numeric representation to another, preserving the units. /// /// When casting from floating point to integer coordinates, the decimals are truncated /// as one would expect from a simple cast, but this behavior does not always make sense /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. #[inline] pubfn cast<NewT: NumCast>(self) -> Size3D<NewT, U> { self.try_cast().unwrap()
}
/// Fallible cast from one numeric representation to another, preserving the units. /// /// When casting from floating point to integer coordinates, the decimals are truncated /// as one would expect from a simple cast, but this behavior does not always make sense /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting. pubfn try_cast<NewT: NumCast>(self) -> Option<Size3D<NewT, U>> { match (
NumCast::from(self.width),
NumCast::from(self.height),
NumCast::from(self.depth),
) {
(Some(w), Some(h), Some(d)) => Some(Size3D::new(w, h, d)),
_ => None,
}
}
// Convenience functions for common casts
/// Cast into an `f32` size. #[inline] pubfn to_f32(self) -> Size3D<f32, U> { self.cast()
}
/// Cast into an `f64` size. #[inline] pubfn to_f64(self) -> Size3D<f64, U> { self.cast()
}
/// Cast into an `uint` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_usize(self) -> Size3D<usize, U> { self.cast()
}
/// Cast into an `u32` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_u32(self) -> Size3D<u32, U> { self.cast()
}
/// Cast into an `i32` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_i32(self) -> Size3D<i32, U> { self.cast()
}
/// Cast into an `i64` size, truncating decimals if any. /// /// When casting from floating point sizes, it is worth considering whether /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain /// the desired conversion behavior. #[inline] pubfn to_i64(self) -> Size3D<i64, U> { self.cast()
}
}
impl<T: Float, U> Size3D<T, U> { /// Returns true if all members are finite. #[inline] pubfn is_finite(self) -> bool { self.width.is_finite() && self.height.is_finite() && self.depth.is_finite()
}
}
impl<T: Signed, U> Size3D<T, U> { /// Computes the absolute value of each component. /// /// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`. /// /// For signed integers, `::MIN` will be returned for component if the component is `::MIN`. pubfn abs(self) -> Self {
size3(self.width.abs(), self.height.abs(), self.depth.abs())
}
/// Returns `true` if all components is positive and `false` any component is zero or negative. pubfn is_positive(self) -> bool { self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
}
}
impl<T: PartialOrd, U> Size3D<T, U> { /// Returns the size each component of which are minimum of this size and another. #[inline] pubfn min(self, other: Self) -> Self {
size3(
min(self.width, other.width),
min(self.height, other.height),
min(self.depth, other.depth),
)
}
/// Returns the size each component of which are maximum of this size and another. #[inline] pubfn max(self, other: Self) -> Self {
size3(
max(self.width, other.width),
max(self.height, other.height),
max(self.depth, other.depth),
)
}
/// Returns the size each component of which clamped by corresponding /// components of `start` and `end`. /// /// Shortcut for `self.max(start).min(end)`. #[inline] pubfn clamp(self, start: Self, end: Self) -> Self where
T: Copy,
{ self.max(start).min(end)
}
// Returns true if this size is larger or equal to the other size in all dimensions. #[inline] pubfn contains(self, other: Self) -> bool { self.width >= other.width && self.height >= other.height && self.depth >= other.depth
}
/// Returns vector with results of "greater than" operation on each component. pubfn greater_than(self, other: Self) -> BoolVector3D {
BoolVector3D {
x: self.width > other.width,
y: self.height > other.height,
z: self.depth > other.depth,
}
}
/// Returns vector with results of "lower than" operation on each component. pubfn lower_than(self, other: Self) -> BoolVector3D {
BoolVector3D {
x: self.width < other.width,
y: self.height < other.height,
z: self.depth < other.depth,
}
}
/// Returns `true` if any component of size is zero, negative or NaN. pubfn is_empty(self) -> bool where
T: Zero,
{ let zero = T::zero();
!(self.width > zero && self.height > zero && self.depth > zero)
}
}
impl<T: PartialEq, U> Size3D<T, U> { /// Returns vector with results of "equal" operation on each component. pubfn equal(self, other: Self) -> BoolVector3D {
BoolVector3D {
x: self.width == other.width,
y: self.height == other.height,
z: self.depth == other.depth,
}
}
/// Returns vector with results of "not equal" operation on each component. pubfn not_equal(self, other: Self) -> BoolVector3D {
BoolVector3D {
x: self.width != other.width,
y: self.height != other.height,
z: self.depth != other.depth,
}
}
}
impl<T: Round, U> Round for Size3D<T, U> { /// See [`Size3D::round()`](#method.round). #[inline] fn round(self) -> Self { self.round()
}
}
impl<T: Ceil, U> Ceil for Size3D<T, U> { /// See [`Size3D::ceil()`](#method.ceil). #[inline] fn ceil(self) -> Self { self.ceil()
}
}
impl<T: Floor, U> Floor for Size3D<T, U> { /// See [`Size3D::floor()`](#method.floor). #[inline] fn floor(self) -> Self { self.floor()
}
}
impl<T: Zero, U> Zero for Size3D<T, U> { #[inline] fn zero() -> Self {
Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
}
}
impl<T: Neg, U> Neg for Size3D<T, U> { type Output = Size3D<T::Output, U>;
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.29Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.