Improve number display (#2936)

This commit is contained in:
Malo 2023-12-14 14:21:25 +01:00 committed by GitHub
parent 9024121905
commit 7adeb49652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 51 additions and 20 deletions

View File

@ -51,7 +51,7 @@ impl f64 {
impl Repr for f64 {
fn repr(&self) -> EcoString {
repr::format_float(*self, None, "")
repr::format_float(*self, None, true, "")
}
}

View File

@ -53,7 +53,7 @@ impl i64 {
impl Repr for i64 {
fn repr(&self) -> EcoString {
repr::format_int_with_base(*self, 10)
eco_format!("{:?}", self)
}
}

View File

@ -74,20 +74,51 @@ pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
/// Converts a float to a string representation with a specific precision and a
/// suffix, all with a single allocation.
pub fn format_float(mut value: f64, precision: Option<u8>, suffix: &str) -> EcoString {
pub fn format_float(
mut value: f64,
precision: Option<u8>,
force_separator: bool,
suffix: &str,
) -> EcoString {
if let Some(p) = precision {
let offset = 10_f64.powi(p as i32);
value = (value * offset).round() / offset;
}
// Debug for f64 always prints a decimal separator, while Display only does
// when necessary.
if value.is_nan() {
"NaN".into()
} else if value.is_sign_negative() {
eco_format!("{}{}{}", MINUS_SIGN, value.abs(), suffix)
} else if force_separator {
eco_format!("{:?}{}", value, suffix)
} else {
eco_format!("{}{}", value, suffix)
}
}
/// Converts a float to a string representation with a precision of three
/// decimal places. This is intended to be used as part of a larger structure
/// containing multiple float components, such as colors.
pub fn format_float_component(value: f64) -> EcoString {
format_float(value, Some(3), false, "")
}
/// Converts a float to a string representation with a precision of two decimal
/// places, followed by a unit.
pub fn format_float_with_unit(value: f64, unit: &str) -> EcoString {
format_float(value, Some(2), false, unit)
}
/// Converts a float to a string that can be used to display the float as text.
pub fn display_float(value: f64) -> EcoString {
if value.is_nan() {
"NaN".into()
} else if value < 0.0 {
eco_format!("{}{}", MINUS_SIGN, value.abs())
} else {
eco_format!("{}", value.abs())
}
}
/// Format pieces separated with commas and a final "and" or "or".
pub fn separated_list(pieces: &[impl AsRef<str>], last: &str) -> String {
let mut buf = String::new();

View File

@ -762,7 +762,7 @@ pub enum ToStr {
cast! {
ToStr,
v: i64 => Self::Int(v),
v: f64 => Self::Str(repr::format_float(v, None, "").into()),
v: f64 => Self::Str(repr::display_float(v).into()),
v: Version => Self::Str(format_str!("{}", v)),
v: Bytes => Self::Str(
std::str::from_utf8(&v)

View File

@ -202,7 +202,7 @@ impl Value {
match self {
Self::None => Content::empty(),
Self::Int(v) => TextElem::packed(repr::format_int_with_base(v, 10)),
Self::Float(v) => TextElem::packed(repr::format_float(v, None, "")),
Self::Float(v) => TextElem::packed(repr::display_float(v)),
Self::Str(v) => TextElem::packed(v),
Self::Version(v) => TextElem::packed(eco_format!("{v}")),
Self::Symbol(v) => TextElem::packed(v.get()),

View File

@ -148,7 +148,7 @@ impl Debug for Abs {
impl Repr for Abs {
fn repr(&self) -> EcoString {
repr::format_float(self.to_pt(), Some(2), "pt")
repr::format_float_with_unit(self.to_pt(), "pt")
}
}

View File

@ -135,7 +135,7 @@ impl Debug for Angle {
impl Repr for Angle {
fn repr(&self) -> EcoString {
repr::format_float(self.to_deg(), Some(2), "deg")
repr::format_float_with_unit(self.to_deg(), "deg")
}
}

View File

@ -85,7 +85,7 @@ impl Debug for Em {
impl Repr for Em {
fn repr(&self) -> EcoString {
repr::format_float(self.get(), None, "em")
repr::format_float_with_unit(self.get(), "em")
}
}

View File

@ -79,7 +79,7 @@ impl Debug for Fr {
impl Repr for Fr {
fn repr(&self) -> EcoString {
repr::format_float(self.get(), Some(2), "fr")
repr::format_float_with_unit(self.get(), "fr")
}
}

View File

@ -76,7 +76,7 @@ impl Debug for Ratio {
impl Repr for Ratio {
fn repr(&self) -> EcoString {
repr::format_float(self.get() * 100.0, Some(2), "%")
repr::format_float_with_unit(self.get() * 100.0, "%")
}
}

View File

@ -1472,15 +1472,15 @@ impl Repr for Color {
eco_format!(
"oklab({}, {}, {})",
Ratio::new(c.l as _).repr(),
repr::format_float(c.a as _, Some(3), ""),
repr::format_float(c.b as _, Some(3), ""),
repr::format_float_component(c.a as _),
repr::format_float_component(c.b as _),
)
} else {
eco_format!(
"oklab({}, {}, {}, {})",
Ratio::new(c.l as _).repr(),
repr::format_float(c.a as _, Some(3), ""),
repr::format_float(c.b as _, Some(3), ""),
repr::format_float_component(c.a as _),
repr::format_float_component(c.b as _),
Ratio::new(c.alpha as _).repr(),
)
}
@ -1490,14 +1490,14 @@ impl Repr for Color {
eco_format!(
"oklch({}, {}, {})",
Ratio::new(c.l as _).repr(),
repr::format_float(c.chroma as _, Some(3), ""),
repr::format_float_component(c.chroma as _),
hue_angle(c.hue.into_degrees()).repr(),
)
} else {
eco_format!(
"oklch({}, {}, {}, {})",
Ratio::new(c.l as _).repr(),
repr::format_float(c.chroma as _, Some(3), ""),
repr::format_float_component(c.chroma as _),
hue_angle(c.hue.into_degrees()).repr(),
Ratio::new(c.alpha as _).repr(),
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -76,7 +76,7 @@
#test((5em + 6in).abs.inches(), 6.0)
---
// Error: 2-21 cannot convert a length with non-zero em units (`6pt + 10.5em`) to pt
// Error: 2-21 cannot convert a length with non-zero em units (`-6pt + 10.5em`) to pt
// Hint: 2-21 use `length.abs.pt()` instead to ignore its em component
#(10.5em - 6pt).pt()
@ -86,7 +86,7 @@
#(3em).cm()
---
// Error: 2-20 cannot convert a length with non-zero em units (`226.77pt + 93em`) to mm
// Error: 2-20 cannot convert a length with non-zero em units (`-226.77pt + 93em`) to mm
// Hint: 2-20 use `length.abs.mm()` instead to ignore its em component
#(93em - 80mm).mm()