Remove decorum

This commit is contained in:
Laurenz 2021-11-22 15:50:35 +01:00
parent 0a974d86ba
commit 02f114d072
18 changed files with 248 additions and 94 deletions

View File

@ -19,7 +19,6 @@ debug = 0
opt-level = 2
[dependencies]
decorum = { version = "0.3.1", default-features = false, features = ["serialize-serde"] }
fxhash = "0.2.1"
image = { version = "0.23", default-features = false, features = ["png", "jpeg"] }
itertools = "0.10"

View File

@ -17,7 +17,7 @@ pub enum Align {
impl Align {
/// The axis this alignment belongs to if it is specific.
pub fn axis(self) -> Option<SpecAxis> {
pub const fn axis(self) -> Option<SpecAxis> {
match self {
Self::Left => Some(SpecAxis::Horizontal),
Self::Top => Some(SpecAxis::Vertical),
@ -28,7 +28,7 @@ impl Align {
}
/// The inverse alignment.
pub fn inv(self) -> Self {
pub const fn inv(self) -> Self {
match self {
Self::Left => Self::Right,
Self::Top => Self::Bottom,

View File

@ -3,12 +3,12 @@ use super::*;
/// An angle.
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Serialize, Deserialize)]
pub struct Angle(N64);
pub struct Angle(Scalar);
impl Angle {
/// The zero angle.
pub fn zero() -> Self {
Self(N64::from(0.0))
pub const fn zero() -> Self {
Self(Scalar(0.0))
}
/// Create an angle from a number of radians.
@ -22,8 +22,8 @@ impl Angle {
}
/// Create an angle from a number of raw units.
pub fn raw(raw: f64) -> Self {
Self(N64::from(raw))
pub const fn raw(raw: f64) -> Self {
Self(Scalar(raw))
}
/// Convert this to a number of radians.
@ -37,13 +37,13 @@ impl Angle {
}
/// Get the value of this angle in raw units.
pub fn to_raw(self) -> f64 {
self.0.into()
pub const fn to_raw(self) -> f64 {
(self.0).0
}
/// Create an angle from a value in a unit.
pub fn with_unit(val: f64, unit: AngularUnit) -> Self {
Self(N64::from(val * unit.raw_scale()))
Self(Scalar(val * unit.raw_scale()))
}
/// Get the value of this length in unit.

View File

@ -15,7 +15,7 @@ pub enum Dir {
impl Dir {
/// The side this direction starts at.
pub fn start(self) -> Side {
pub const fn start(self) -> Side {
match self {
Self::LTR => Side::Left,
Self::RTL => Side::Right,
@ -25,7 +25,7 @@ impl Dir {
}
/// The side this direction ends at.
pub fn end(self) -> Side {
pub const fn end(self) -> Side {
match self {
Self::LTR => Side::Right,
Self::RTL => Side::Left,
@ -35,7 +35,7 @@ impl Dir {
}
/// The specific axis this direction belongs to.
pub fn axis(self) -> SpecAxis {
pub const fn axis(self) -> SpecAxis {
match self {
Self::LTR | Self::RTL => SpecAxis::Horizontal,
Self::TTB | Self::BTT => SpecAxis::Vertical,
@ -45,7 +45,7 @@ impl Dir {
/// Whether this direction points into the positive coordinate direction.
///
/// The positive directions are left-to-right and top-to-bottom.
pub fn is_positive(self) -> bool {
pub const fn is_positive(self) -> bool {
match self {
Self::LTR | Self::TTB => true,
Self::RTL | Self::BTT => false,
@ -56,12 +56,12 @@ impl Dir {
///
/// - `1.0` if the direction is positive.
/// - `-1.0` if the direction is negative.
pub fn factor(self) -> f64 {
pub const fn factor(self) -> f64 {
if self.is_positive() { 1.0 } else { -1.0 }
}
/// The inverse direction.
pub fn inv(self) -> Self {
pub const fn inv(self) -> Self {
match self {
Self::LTR => Self::RTL,
Self::RTL => Self::LTR,

View File

@ -5,27 +5,27 @@ use super::*;
/// `1em` is the same as the font size.
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Serialize, Deserialize)]
pub struct Em(N64);
pub struct Em(Scalar);
impl Em {
/// The zero length.
pub fn zero() -> Self {
Self(N64::from(0.0))
pub const fn zero() -> Self {
Self(Scalar(0.0))
}
/// The font size.
pub fn one() -> Self {
Self(N64::from(1.0))
pub const fn one() -> Self {
Self(Scalar(1.0))
}
/// Create an font-relative length.
pub fn new(em: f64) -> Self {
Self(N64::from(em))
pub const fn new(em: f64) -> Self {
Self(Scalar(em))
}
/// Create font units at the given units per em.
pub fn from_units(units: impl Into<f64>, units_per_em: f64) -> Self {
Self(N64::from(units.into() / units_per_em))
Self(Scalar(units.into() / units_per_em))
}
/// Convert to a length at the given font size.
@ -34,8 +34,8 @@ impl Em {
}
/// The number of em units.
pub fn get(self) -> f64 {
self.0.into()
pub const fn get(self) -> f64 {
(self.0).0
}
/// Whether the length is zero.

View File

@ -2,27 +2,27 @@ use super::*;
/// A fractional length.
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Fractional(N64);
pub struct Fractional(Scalar);
impl Fractional {
/// Takes up zero space: `0fr`.
pub fn zero() -> Self {
Self(N64::from(0.0))
pub const fn zero() -> Self {
Self(Scalar(0.0))
}
/// Takes up as much space as all other items with this fractional size: `1fr`.
pub fn one() -> Self {
Self(N64::from(1.0))
pub const fn one() -> Self {
Self(Scalar(1.0))
}
/// Create a new fractional value.
pub fn new(ratio: f64) -> Self {
Self(N64::from(ratio))
pub const fn new(ratio: f64) -> Self {
Self(Scalar(ratio))
}
/// Get the underlying ratio.
pub fn get(self) -> f64 {
self.0.into()
pub const fn get(self) -> f64 {
(self.0).0
}
/// Whether the ratio is zero.

View File

@ -11,7 +11,7 @@ pub struct Gen<T> {
impl<T> Gen<T> {
/// Create a new instance from the two components.
pub fn new(inline: T, block: T) -> Self {
pub const fn new(inline: T, block: T) -> Self {
Self { inline, block }
}

View File

@ -4,17 +4,17 @@ use super::*;
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct Length(N64);
pub struct Length(Scalar);
impl Length {
/// The zero length.
pub fn zero() -> Self {
Self(N64::from(0.0))
pub const fn zero() -> Self {
Self(Scalar(0.0))
}
/// The inifinite length.
pub fn inf() -> Self {
Self(N64::from(f64::INFINITY))
pub const fn inf() -> Self {
Self(Scalar(f64::INFINITY))
}
/// Create a length from a number of points.
@ -38,8 +38,8 @@ impl Length {
}
/// Create a length from a number of raw units.
pub fn raw(raw: f64) -> Self {
Self(N64::from(raw))
pub const fn raw(raw: f64) -> Self {
Self(Scalar(raw))
}
/// Convert this to a number of points.
@ -63,13 +63,13 @@ impl Length {
}
/// Get the value of this length in raw units.
pub fn to_raw(self) -> f64 {
self.0.into()
pub const fn to_raw(self) -> f64 {
(self.0).0
}
/// Create a length from a value in a unit.
pub fn with_unit(val: f64, unit: LengthUnit) -> Self {
Self(N64::from(val * unit.raw_scale()))
Self(Scalar(val * unit.raw_scale()))
}
/// Get the value of this length in unit.
@ -79,17 +79,17 @@ impl Length {
/// Whether the length is zero.
pub fn is_zero(self) -> bool {
self.0 == 0.0
self.to_raw() == 0.0
}
/// Whether the length is finite.
pub fn is_finite(self) -> bool {
self.0.into_inner().is_finite()
self.to_raw().is_finite()
}
/// Whether the length is infinite.
pub fn is_infinite(self) -> bool {
self.0.into_inner().is_infinite()
self.to_raw().is_infinite()
}
/// The absolute value of the this length.
@ -211,14 +211,14 @@ assign_impl!(Length *= f64);
assign_impl!(Length /= f64);
impl Sum for Length {
fn sum<I: Iterator<Item = Length>>(iter: I) -> Self {
iter.fold(Length::zero(), Add::add)
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
Self(iter.map(|s| s.0).sum())
}
}
impl<'a> Sum<&'a Length> for Length {
fn sum<I: Iterator<Item = &'a Length>>(iter: I) -> Self {
iter.copied().fold(Length::zero(), Add::add)
impl<'a> Sum<&'a Self> for Length {
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
Self(iter.map(|s| s.0).sum())
}
}

View File

@ -11,7 +11,7 @@ pub struct Linear {
impl Linear {
/// The zero linear.
pub fn zero() -> Self {
pub const fn zero() -> Self {
Self {
rel: Relative::zero(),
abs: Length::zero(),
@ -19,7 +19,7 @@ impl Linear {
}
/// The linear with a relative part of `100%` and no absolute part.
pub fn one() -> Self {
pub const fn one() -> Self {
Self {
rel: Relative::one(),
abs: Length::zero(),
@ -27,7 +27,7 @@ impl Linear {
}
/// Create a new linear.
pub fn new(rel: Relative, abs: Length) -> Self {
pub const fn new(rel: Relative, abs: Length) -> Self {
Self { rel, abs }
}

View File

@ -14,6 +14,7 @@ mod paint;
mod path;
mod point;
mod relative;
mod scalar;
mod sides;
mod size;
mod spec;
@ -30,16 +31,18 @@ pub use paint::*;
pub use path::*;
pub use point::*;
pub use relative::*;
pub use scalar::*;
pub use sides::*;
pub use size::*;
pub use spec::*;
use std::cmp::Ordering;
use std::f64::consts::PI;
use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::iter::Sum;
use std::ops::*;
use decorum::N64;
use serde::{Deserialize, Serialize};
/// Generic access to a structure's components.

View File

@ -16,7 +16,7 @@ pub enum PathElement {
impl Path {
/// Create an empty path.
pub fn new() -> Self {
pub const fn new() -> Self {
Self(vec![])
}

View File

@ -11,22 +11,22 @@ pub struct Point {
impl Point {
/// The origin point.
pub fn zero() -> Self {
pub const fn zero() -> Self {
Self { x: Length::zero(), y: Length::zero() }
}
/// Create a new point from x and y coordinate.
pub fn new(x: Length, y: Length) -> Self {
pub const fn new(x: Length, y: Length) -> Self {
Self { x, y }
}
/// Create an instance with two equal components.
pub fn splat(value: Length) -> Self {
pub const fn splat(value: Length) -> Self {
Self { x: value, y: value }
}
/// Convert to the generic representation.
pub fn to_gen(self, block: SpecAxis) -> Gen<Length> {
pub const fn to_gen(self, block: SpecAxis) -> Gen<Length> {
match block {
SpecAxis::Horizontal => Gen::new(self.y, self.x),
SpecAxis::Vertical => Gen::new(self.x, self.y),

View File

@ -5,27 +5,27 @@ use super::*;
/// _Note_: `50%` is represented as `0.5` here, but stored as `50.0` in the
/// corresponding [literal](crate::syntax::ast::LitKind::Percent).
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Relative(N64);
pub struct Relative(Scalar);
impl Relative {
/// A ratio of `0%` represented as `0.0`.
pub fn zero() -> Self {
Self(N64::from(0.0))
pub const fn zero() -> Self {
Self(Scalar(0.0))
}
/// A ratio of `100%` represented as `1.0`.
pub fn one() -> Self {
Self(N64::from(1.0))
pub const fn one() -> Self {
Self(Scalar(1.0))
}
/// Create a new relative value.
pub fn new(ratio: f64) -> Self {
Self(N64::from(ratio))
pub const fn new(ratio: f64) -> Self {
Self(Scalar(ratio))
}
/// Get the underlying ratio.
pub fn get(self) -> f64 {
self.0.into()
pub const fn get(self) -> f64 {
(self.0).0
}
/// Resolve this relative to the given `length`.

152
src/geom/scalar.rs Normal file
View File

@ -0,0 +1,152 @@
use super::*;
/// A 64-bit float that implements `Eq`, `Ord` and `Hash`.
///
/// Panics if its `NaN` during any of those operations.
#[derive(Default, Copy, Clone, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Scalar(pub f64);
impl From<f64> for Scalar {
fn from(float: f64) -> Self {
Self(float)
}
}
impl From<Scalar> for f64 {
fn from(scalar: Scalar) -> Self {
scalar.0
}
}
impl Debug for Scalar {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl Ord for Scalar {
fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(&other).expect("float is NaN")
}
}
impl PartialOrd for Scalar {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
fn lt(&self, other: &Self) -> bool {
self.0 < other.0
}
fn le(&self, other: &Self) -> bool {
self.0 <= other.0
}
fn gt(&self, other: &Self) -> bool {
self.0 > other.0
}
fn ge(&self, other: &Self) -> bool {
self.0 >= other.0
}
}
impl Eq for Scalar {}
impl PartialEq for Scalar {
fn eq(&self, other: &Self) -> bool {
assert!(!self.0.is_nan() && !other.0.is_nan(), "float is NaN");
self.0 == other.0
}
}
impl PartialEq<f64> for Scalar {
fn eq(&self, other: &f64) -> bool {
self == &Self(*other)
}
}
impl Hash for Scalar {
fn hash<H: Hasher>(&self, state: &mut H) {
debug_assert!(!self.0.is_nan(), "float is NaN");
self.0.to_bits().hash(state);
}
}
impl Neg for Scalar {
type Output = Self;
fn neg(self) -> Self::Output {
Self(-self.0)
}
}
impl<T: Into<Self>> Add<T> for Scalar {
type Output = Self;
fn add(self, rhs: T) -> Self::Output {
Self(self.0 + rhs.into().0)
}
}
impl<T: Into<Self>> AddAssign<T> for Scalar {
fn add_assign(&mut self, rhs: T) {
self.0 += rhs.into().0;
}
}
impl<T: Into<Self>> Sub<T> for Scalar {
type Output = Self;
fn sub(self, rhs: T) -> Self::Output {
Self(self.0 - rhs.into().0)
}
}
impl<T: Into<Self>> SubAssign<T> for Scalar {
fn sub_assign(&mut self, rhs: T) {
self.0 -= rhs.into().0;
}
}
impl<T: Into<Self>> Mul<T> for Scalar {
type Output = Self;
fn mul(self, rhs: T) -> Self::Output {
Self(self.0 * rhs.into().0)
}
}
impl<T: Into<Self>> MulAssign<T> for Scalar {
fn mul_assign(&mut self, rhs: T) {
self.0 *= rhs.into().0;
}
}
impl<T: Into<Self>> Div<T> for Scalar {
type Output = Self;
fn div(self, rhs: T) -> Self::Output {
Self(self.0 / rhs.into().0)
}
}
impl<T: Into<Self>> DivAssign<T> for Scalar {
fn div_assign(&mut self, rhs: T) {
self.0 /= rhs.into().0;
}
}
impl Sum for Scalar {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
Self(iter.map(|s| s.0).sum())
}
}
impl<'a> Sum<&'a Self> for Scalar {
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
Self(iter.map(|s| s.0).sum())
}
}

View File

@ -15,7 +15,7 @@ pub struct Sides<T> {
impl<T> Sides<T> {
/// Create a new instance from the four components.
pub fn new(left: T, top: T, right: T, bottom: T) -> Self {
pub const fn new(left: T, top: T, right: T, bottom: T) -> Self {
Self { left, top, right, bottom }
}

View File

@ -11,17 +11,17 @@ pub struct Size {
impl Size {
/// The zero size.
pub fn zero() -> Self {
pub const fn zero() -> Self {
Self { w: Length::zero(), h: Length::zero() }
}
/// Create a new size from width and height.
pub fn new(w: Length, h: Length) -> Self {
pub const fn new(w: Length, h: Length) -> Self {
Self { w, h }
}
/// Create an instance with two equal components.
pub fn splat(v: Length) -> Self {
pub const fn splat(v: Length) -> Self {
Self { w: v, h: v }
}
@ -41,17 +41,17 @@ impl Size {
}
/// Convert to a point.
pub fn to_point(self) -> Point {
pub const fn to_point(self) -> Point {
Point::new(self.w, self.h)
}
/// Convert to a Spec.
pub fn to_spec(self) -> Spec<Length> {
pub const fn to_spec(self) -> Spec<Length> {
Spec::new(self.w, self.h)
}
/// Convert to the generic representation.
pub fn to_gen(self, block: SpecAxis) -> Gen<Length> {
pub const fn to_gen(self, block: SpecAxis) -> Gen<Length> {
match block {
SpecAxis::Horizontal => Gen::new(self.h, self.w),
SpecAxis::Vertical => Gen::new(self.w, self.h),

View File

@ -11,7 +11,7 @@ pub struct Spec<T> {
impl<T> Spec<T> {
/// Create a new instance from the two components.
pub fn new(x: T, y: T) -> Self {
pub const fn new(x: T, y: T) -> Self {
Self { x, y }
}

View File

@ -2,11 +2,11 @@ use std::cmp::Reverse;
use std::collections::HashMap;
use std::rc::Rc;
use decorum::N32;
use itertools::Itertools;
use super::{Constrained, Regions};
use crate::frame::Frame;
use crate::geom::Scalar;
const TEMP_LEN: usize = 5;
const TEMP_LAST: usize = TEMP_LEN - 1;
@ -135,28 +135,27 @@ impl LayoutCache {
.0;
for entries in self.frames.values_mut() {
entries.retain(|e| e.cooldown() < threshold);
entries.retain(|f| f.cooldown() < threshold);
}
}
EvictionPolicy::LeastFrequentlyUsed => {
let threshold = self
.entries()
.map(|f| N32::from(f.hits() as f32 / f.age() as f32))
.map(|f| Scalar(f.hits() as f64 / f.age() as f64))
.k_smallest(len - self.max_size)
.last()
.unwrap();
.unwrap()
.0;
for entries in self.frames.values_mut() {
entries.retain(|f| {
f.hits() as f32 / f.age() as f32 > threshold.into_inner()
});
entries.retain(|f| f.hits() as f64 / f.age() as f64 > threshold);
}
}
EvictionPolicy::Random => {
// Fraction of items that should be kept.
let threshold = self.max_size as f32 / len as f32;
let threshold = self.max_size as f64 / len as f64;
for entries in self.frames.values_mut() {
entries.retain(|_| rand::random::<f32>() > threshold);
entries.retain(|_| rand::random::<f64>() > threshold);
}
}
EvictionPolicy::Patterns => {
@ -170,15 +169,16 @@ impl LayoutCache {
let threshold = self
.entries()
.filter(|f| !f.properties().must_keep())
.map(|f| N32::from(f.hits() as f32 / f.age() as f32))
.map(|f| Scalar(f.hits() as f64 / f.age() as f64))
.k_smallest((len - kept) - remaining_capacity)
.last()
.unwrap();
.unwrap()
.0;
for (_, entries) in self.frames.iter_mut() {
for entries in self.frames.values_mut() {
entries.retain(|f| {
f.properties().must_keep()
|| f.hits() as f32 / f.age() as f32 > threshold.into_inner()
|| f.hits() as f64 / f.age() as f64 > threshold
});
}
}