diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/app_units | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/app_units')
-rw-r--r-- | third_party/rust/app_units/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/app_units/Cargo.toml | 38 | ||||
-rw-r--r-- | third_party/rust/app_units/README.md | 3 | ||||
-rw-r--r-- | third_party/rust/app_units/src/app_unit.rs | 385 | ||||
-rw-r--r-- | third_party/rust/app_units/src/lib.rs | 11 |
5 files changed, 438 insertions, 0 deletions
diff --git a/third_party/rust/app_units/.cargo-checksum.json b/third_party/rust/app_units/.cargo-checksum.json new file mode 100644 index 0000000000..ce26405718 --- /dev/null +++ b/third_party/rust/app_units/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"21306ea1efdf7e5eb1c9a6b4a939a852c14ed2c43f11d3fae8954bc70c06a84c","README.md":"2f4c2188cdcfaa201ecd7c6b1bdb5247a54b534fc50a4e26b339a245cee973a9","src/app_unit.rs":"b782d65bb4211ca23ed54fee6dac3481631994ef30326be5fe99896f3f07309a","src/lib.rs":"9d49fc7ce18db42efae7fb0a728449585714e134d82a01b3070de373d83193f0"},"package":"ad05ebc593047433bada8bc1bf31957b6516dad7bfb5def6f425581f5bcc982a"}
\ No newline at end of file diff --git a/third_party/rust/app_units/Cargo.toml b/third_party/rust/app_units/Cargo.toml new file mode 100644 index 0000000000..bf4d838c9a --- /dev/null +++ b/third_party/rust/app_units/Cargo.toml @@ -0,0 +1,38 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "app_units" +version = "0.7.2" +authors = ["The Servo Project Developers"] +description = "Servo app units type (Au)" +documentation = "https://docs.rs/app_units/" +readme = "README.md" +license = "MPL-2.0" +repository = "https://github.com/servo/app_units" + +[dependencies.num-traits] +version = "0.2" +optional = true + +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true + +[features] +default = [ + "num_traits", + "serde_serialization", +] +num_traits = ["num-traits"] +serde_serialization = ["serde"] diff --git a/third_party/rust/app_units/README.md b/third_party/rust/app_units/README.md new file mode 100644 index 0000000000..db9acf3d6c --- /dev/null +++ b/third_party/rust/app_units/README.md @@ -0,0 +1,3 @@ +# app-units + +[Documentation](https://docs.rs/app_units/) diff --git a/third_party/rust/app_units/src/app_unit.rs b/third_party/rust/app_units/src/app_unit.rs new file mode 100644 index 0000000000..c01bccb9d8 --- /dev/null +++ b/third_party/rust/app_units/src/app_unit.rs @@ -0,0 +1,385 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#[cfg(feature = "num_traits")] +use num_traits::Zero; +#[cfg(feature = "serde_serialization")] +use serde::{Serialize, Deserialize, Deserializer}; + +use std::{fmt, i32, default::Default, ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign}}; + +/// The number of app units in a pixel. +pub const AU_PER_PX: i32 = 60; +/// The minimum number of app units, same as in Gecko. +pub const MIN_AU: Au = Au(- ((1 << 30) - 1)); +/// The maximum number of app units, same as in Gecko. +/// +/// (1 << 30) - 1 lets us add/subtract two Au and check for overflow after the operation. +pub const MAX_AU: Au = Au((1 << 30) - 1); + + +#[repr(transparent)] +#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord, Default)] +#[cfg_attr(feature = "serde_serialization", derive(Serialize))] +/// An App Unit, the fundamental unit of length in Servo. Usually +/// 1/60th of a pixel (see `AU_PER_PX`) +/// +/// Please ensure that the values are between `MIN_AU` and `MAX_AU`. +/// It is safe to construct invalid `Au` values, but it may lead to +/// panics and overflows. +pub struct Au(pub i32); + +impl fmt::Debug for Au { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}px", self.to_f64_px()) + } +} + +#[cfg(feature = "serde_serialization")] +impl<'de> Deserialize<'de> for Au { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Au, D::Error> { + Ok(Au(i32::deserialize(deserializer)?).clamp()) + } +} + +#[cfg(feature = "num_traits")] +impl Zero for Au { + #[inline] + fn zero() -> Au { + Au(0) + } + + #[inline] + fn is_zero(&self) -> bool { + self.0 == 0 + } +} + +impl Add for Au { + type Output = Au; + + #[inline] + fn add(self, other: Au) -> Au { + Au(self.0 + other.0).clamp() + } +} + +impl Sub for Au { + type Output = Au; + + #[inline] + fn sub(self, other: Au) -> Au { + Au(self.0 - other.0).clamp() + } + +} + +impl Mul<Au> for i32 { + type Output = Au; + + #[inline] + fn mul(self, other: Au) -> Au { + if let Some(new) = other.0.checked_mul(self) { + Au(new).clamp() + } else if (self > 0) ^ (other.0 > 0) { + MIN_AU + } else { + MAX_AU + } + } +} + +impl Mul<i32> for Au { + type Output = Au; + + #[inline] + fn mul(self, other: i32) -> Au { + if let Some(new) = self.0.checked_mul(other) { + Au(new).clamp() + } else if (self.0 > 0) ^ (other > 0) { + MIN_AU + } else { + MAX_AU + } + } +} + +impl Div for Au { + type Output = i32; + + #[inline] + fn div(self, other: Au) -> i32 { + self.0 / other.0 + } +} + +impl Div<i32> for Au { + type Output = Au; + + #[inline] + fn div(self, other: i32) -> Au { + Au(self.0 / other) + } +} + +impl Rem for Au { + type Output = Au; + + #[inline] + fn rem(self, other: Au) -> Au { + Au(self.0 % other.0) + } +} + +impl Rem<i32> for Au { + type Output = Au; + + #[inline] + fn rem(self, other: i32) -> Au { + Au(self.0 % other) + } +} + +impl Neg for Au { + type Output = Au; + + #[inline] + fn neg(self) -> Au { + Au(-self.0) + } +} + +impl AddAssign for Au { + #[inline] + fn add_assign(&mut self, other: Au) { + *self = (*self + other).clamp(); + } +} + +impl SubAssign for Au { + #[inline] + fn sub_assign(&mut self, other: Au) { + *self = (*self - other).clamp(); + } +} + +impl MulAssign<i32> for Au { + #[inline] + fn mul_assign(&mut self, other: i32) { + *self = (*self * other).clamp(); + } +} + +impl DivAssign<i32> for Au { + #[inline] + fn div_assign(&mut self, other: i32) { + *self = (*self / other).clamp(); + } +} + +impl Au { + /// FIXME(pcwalton): Workaround for lack of cross crate inlining of newtype structs! + #[inline] + pub fn new(value: i32) -> Au { + Au(value).clamp() + } + + #[inline] + fn clamp(self) -> Self { + Ord::clamp(self, MIN_AU, MAX_AU) + } + + #[inline] + pub fn scale_by(self, factor: f32) -> Au { + let new_float = ((self.0 as f64) * factor as f64).round(); + Au::from_f64_au(new_float) + } + + #[inline] + /// Scale, but truncate (useful for viewport-relative units) + pub fn scale_by_trunc(self, factor: f32) -> Au { + let new_float = ((self.0 as f64) * factor as f64).trunc(); + Au::from_f64_au(new_float) + } + + #[inline] + pub fn from_f64_au(float: f64) -> Self { + // We *must* operate in f64. f32 isn't precise enough to handle MAX_AU + Au(float.clamp(MIN_AU.0 as f64, MAX_AU.0 as f64) as i32) + } + + #[inline] + pub fn from_px(px: i32) -> Au { + Au(px) * AU_PER_PX + } + + /// Round this app unit down to the pixel towards zero and return it. + #[inline] + pub fn to_px(self) -> i32 { + self.0 / AU_PER_PX + } + + /// Ceil this app unit to the appropriate pixel boundary and return it. + #[inline] + pub fn ceil_to_px(self) -> i32 { + ((self.0 as f64) / (AU_PER_PX as f64)).ceil() as i32 + } + + #[inline] + pub fn to_nearest_px(self) -> i32 { + ((self.0 as f64) / (AU_PER_PX as f64)).round() as i32 + } + + #[inline] + pub fn to_nearest_pixel(self, pixels_per_px: f32) -> f32 { + ((self.0 as f32) / (AU_PER_PX as f32) * pixels_per_px).round() / pixels_per_px + } + + #[inline] + pub fn to_f32_px(self) -> f32 { + (self.0 as f32) / (AU_PER_PX as f32) + } + + #[inline] + pub fn to_f64_px(self) -> f64 { + (self.0 as f64) / (AU_PER_PX as f64) + } + + #[inline] + pub fn from_f32_px(px: f32) -> Au { + let float = (px * AU_PER_PX as f32).round(); + Au::from_f64_au(float as f64) + } + + #[inline] + pub fn from_f64_px(px: f64) -> Au { + let float = (px * AU_PER_PX as f64).round(); + Au::from_f64_au(float) + } + + #[inline] + pub fn abs(self) -> Self { + Au(self.0.abs()) + } +} + +#[test] +fn create() { + assert_eq!(Au::zero(), Au(0)); + assert_eq!(Au::default(), Au(0)); + assert_eq!(Au::new(7), Au(7)); +} + +#[test] +fn operations() { + assert_eq!(Au(7) + Au(5), Au(12)); + assert_eq!(MAX_AU + Au(1), MAX_AU); + + assert_eq!(Au(7) - Au(5), Au(2)); + assert_eq!(MIN_AU - Au(1), MIN_AU); + + assert_eq!(Au(7) * 5, Au(35)); + assert_eq!(5 * Au(7), Au(35)); + assert_eq!(MAX_AU * -1, MIN_AU); + assert_eq!(MIN_AU * -1, MAX_AU); + assert_eq!(-1 * MAX_AU, MIN_AU); + assert_eq!(-1 * MIN_AU, MAX_AU); + + assert_eq!((Au(14) / 5) * 5 + Au(14) % 5, Au(14)); + assert_eq!((Au(14) / Au(5)) * Au(5) + Au(14) % Au(5), Au(14)); + + assert_eq!(Au(35) / 5, Au(7)); + assert_eq!(Au(35) % 6, Au(5)); + + assert_eq!(Au(35) / Au(5), 7); + assert_eq!(Au(35) / Au(5), 7); + + assert_eq!(-Au(7), Au(-7)); +} + +#[test] +fn saturate() { + let half = MAX_AU / 2; + assert_eq!(half + half + half + half + half, MAX_AU); + assert_eq!(-half - half - half - half - half, MIN_AU); + assert_eq!(half * -10, MIN_AU); + assert_eq!(-half * 10, MIN_AU); + assert_eq!(half * 10, MAX_AU); + assert_eq!(-half * -10, MAX_AU); +} + +#[test] +fn scale() { + assert_eq!(Au(12).scale_by(1.5), Au(18)); + assert_eq!(Au(12).scale_by(1.7), Au(20)); + assert_eq!(Au(12).scale_by(1.8), Au(22)); + assert_eq!(Au(12).scale_by_trunc(1.8), Au(21)); +} + +#[test] +fn abs() { + assert_eq!(Au(-10).abs(), Au(10)); +} + +#[test] +fn convert() { + assert_eq!(Au::from_px(5), Au(300)); + + assert_eq!(Au(300).to_px(), 5); + assert_eq!(Au(330).to_px(), 5); + assert_eq!(Au(350).to_px(), 5); + assert_eq!(Au(360).to_px(), 6); + + assert_eq!(Au(300).ceil_to_px(), 5); + assert_eq!(Au(310).ceil_to_px(), 6); + assert_eq!(Au(330).ceil_to_px(), 6); + assert_eq!(Au(350).ceil_to_px(), 6); + assert_eq!(Au(360).ceil_to_px(), 6); + + assert_eq!(Au(300).to_nearest_px(), 5); + assert_eq!(Au(310).to_nearest_px(), 5); + assert_eq!(Au(330).to_nearest_px(), 6); + assert_eq!(Au(350).to_nearest_px(), 6); + assert_eq!(Au(360).to_nearest_px(), 6); + + assert_eq!(Au(60).to_nearest_pixel(2.), 1.); + assert_eq!(Au(70).to_nearest_pixel(2.), 1.); + assert_eq!(Au(80).to_nearest_pixel(2.), 1.5); + assert_eq!(Au(90).to_nearest_pixel(2.), 1.5); + assert_eq!(Au(100).to_nearest_pixel(2.), 1.5); + assert_eq!(Au(110).to_nearest_pixel(2.), 2.); + assert_eq!(Au(120).to_nearest_pixel(2.), 2.); + + assert_eq!(Au(300).to_f32_px(), 5.); + assert_eq!(Au(312).to_f32_px(), 5.2); + assert_eq!(Au(330).to_f32_px(), 5.5); + assert_eq!(Au(348).to_f32_px(), 5.8); + assert_eq!(Au(360).to_f32_px(), 6.); + assert_eq!((Au(367).to_f32_px() * 1000.).round(), 6_117.); + assert_eq!((Au(368).to_f32_px() * 1000.).round(), 6_133.); + + assert_eq!(Au(300).to_f64_px(), 5.); + assert_eq!(Au(312).to_f64_px(), 5.2); + assert_eq!(Au(330).to_f64_px(), 5.5); + assert_eq!(Au(348).to_f64_px(), 5.8); + assert_eq!(Au(360).to_f64_px(), 6.); + assert_eq!((Au(367).to_f64_px() * 1000.).round(), 6_117.); + assert_eq!((Au(368).to_f64_px() * 1000.).round(), 6_133.); + + assert_eq!(Au::from_f32_px(5.), Au(300)); + assert_eq!(Au::from_f32_px(5.2), Au(312)); + assert_eq!(Au::from_f32_px(5.5), Au(330)); + assert_eq!(Au::from_f32_px(5.8), Au(348)); + assert_eq!(Au::from_f32_px(6.), Au(360)); + assert_eq!(Au::from_f32_px(6.12), Au(367)); + assert_eq!(Au::from_f32_px(6.13), Au(368)); + + assert_eq!(Au::from_f64_px(5.), Au(300)); + assert_eq!(Au::from_f64_px(5.2), Au(312)); + assert_eq!(Au::from_f64_px(5.5), Au(330)); + assert_eq!(Au::from_f64_px(5.8), Au(348)); + assert_eq!(Au::from_f64_px(6.), Au(360)); + assert_eq!(Au::from_f64_px(6.12), Au(367)); + assert_eq!(Au::from_f64_px(6.13), Au(368)); +} diff --git a/third_party/rust/app_units/src/lib.rs b/third_party/rust/app_units/src/lib.rs new file mode 100644 index 0000000000..eb8cc8beb7 --- /dev/null +++ b/third_party/rust/app_units/src/lib.rs @@ -0,0 +1,11 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! An `Au` is an "App Unit" and represents 1/60th of a CSS pixel. It was +//! originally proposed in 2002 as a standard unit of measure in Gecko. +//! See <https://bugzilla.mozilla.org/show_bug.cgi?id=177805> for more info. + +mod app_unit; + +pub use app_unit::{Au, MIN_AU, MAX_AU, AU_PER_PX}; |