diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/app_units | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
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 | 25 | ||||
-rw-r--r-- | third_party/rust/app_units/README.md | 3 | ||||
-rw-r--r-- | third_party/rust/app_units/src/app_unit.rs | 411 | ||||
-rw-r--r-- | third_party/rust/app_units/src/lib.rs | 14 |
5 files changed, 454 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..a8efec17ea --- /dev/null +++ b/third_party/rust/app_units/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"2b57a8f3f88b35e6ea03b563b2127fe01b90c5d2102910dfb662584e9d72ad26","README.md":"2f4c2188cdcfaa201ecd7c6b1bdb5247a54b534fc50a4e26b339a245cee973a9","src/app_unit.rs":"ab0df325046c8d012202a6a4ec54bbca961aed80529c5cbab4c4c837046a7bf8","src/lib.rs":"594920680604545eed486e6891b9b7d52d3baee3b2d774687fc0ac244331edf5"},"package":"9dadc668390b373e73e4abbfc1f07238b09a25858f2f39c06cebc6d8e141d774"}
\ 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..ff4042d4e6 --- /dev/null +++ b/third_party/rust/app_units/Cargo.toml @@ -0,0 +1,25 @@ +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "app_units" +version = "0.7.0" +authors = ["The Servo Project Developers"] +description = "Servo app units type (Au)" +documentation = "https://docs.rs/app_units/" +license = "MPL-2.0" +repository = "https://github.com/servo/app_units" +[dependencies.num-traits] +version = "0.2" + +[dependencies.serde] +version = "1.0" 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..876582a8f5 --- /dev/null +++ b/third_party/rust/app_units/src/app_unit.rs @@ -0,0 +1,411 @@ +/* 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/. */ + +use num_traits::Zero; +use serde::de::{Deserialize, Deserializer}; +use serde::ser::{Serialize, Serializer}; +use std::default::Default; +use std::fmt; +use std::i32; +use std::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; + +#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Eq, Ord)] +/// 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<'de> Deserialize<'de> for Au { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Au, D::Error> { + Ok(Au(try!(i32::deserialize(deserializer))).clamp()) + } +} + +impl Serialize for Au { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + self.0.serialize(serializer) + } +} + +impl Default for Au { + #[inline] + fn default() -> Au { + Au(0) + } +} + +impl Zero for Au { + #[inline] + fn zero() -> Au { + Au(0) + } + + #[inline] + fn is_zero(&self) -> bool { + self.0 == 0 + } +} + +// (1 << 30) - 1 lets us add/subtract two Au and check for overflow +// after the operation. Gecko uses the same min/max values +pub const MAX_AU: Au = Au((1 << 30) - 1); +pub const MIN_AU: Au = Au(- ((1 << 30) - 1)); + +impl fmt::Debug for Au { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}px", self.to_f64_px()) + } +} + +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; + self.clamp_self(); + } +} + +impl SubAssign for Au { + #[inline] + fn sub_assign(&mut self, other: Au) { + *self = *self - other; + self.clamp_self(); + } +} + +impl MulAssign<i32> for Au { + #[inline] + fn mul_assign(&mut self, other: i32) { + *self = *self * other; + self.clamp_self(); + } +} + +impl DivAssign<i32> for Au { + #[inline] + fn div_assign(&mut self, other: i32) { + *self = *self / other; + self.clamp_self(); + } +} + +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 { + if self.0 > MAX_AU.0 { + MAX_AU + } else if self.0 < MIN_AU.0 { + MIN_AU + } else { + self + } + } + + #[inline] + fn clamp_self(&mut self) { + *self = Au::clamp(*self) + } + + #[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.min(MAX_AU.0 as f64) + .max(MIN_AU.0 as f64) + as i32) + } + + #[inline] + pub fn from_px(px: i32) -> Au { + Au(px) * AU_PER_PX + } + + /// Rounds this app unit down to the pixel towards zero and returns 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..cc48ebd6d0 --- /dev/null +++ b/third_party/rust/app_units/src/lib.rs @@ -0,0 +1,14 @@ +/* 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. + +extern crate num_traits; +extern crate serde; + +mod app_unit; + +pub use app_unit::{Au, MIN_AU, MAX_AU, AU_PER_PX}; |