Make Oklab and Oklch chroma ratios relative to 0.4 (#2642)

This commit is contained in:
frozolotl 2023-11-13 15:48:54 +01:00 committed by GitHub
parent 67422e664b
commit d16ab29068
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 15 deletions

View File

@ -295,8 +295,10 @@ impl Color {
/// A linear Oklab color is represented internally by an array of four
/// components:
/// - lightness ([`ratio`]($ratio))
/// - a ([`float`]($float) in the range `[-0.4..0.4]`)
/// - b ([`float`]($float) in the range `[-0.4..0.4]`)
/// - a ([`float`]($float) in the range `[-0.4..0.4]`
/// or [`ratio`]($ratio) in the range `[-100%..100%]`)
/// - b ([`float`]($float) in the range `[-0.4..0.4]`
/// or [`ratio`]($ratio) in the range `[-100%..100%]`)
/// - alpha ([`ratio`]($ratio))
///
/// These components are also available using the
@ -317,10 +319,10 @@ impl Color {
lightness: RatioComponent,
/// The a ("green/red") component.
#[external]
a: ABComponent,
a: ChromaComponent,
/// The b ("blue/yellow") component.
#[external]
b: ABComponent,
b: ChromaComponent,
/// The alpha component.
#[external]
alpha: RatioComponent,
@ -334,8 +336,8 @@ impl Color {
color.to_oklab()
} else {
let RatioComponent(l) = args.expect("lightness component")?;
let ABComponent(a) = args.expect("A component")?;
let ABComponent(b) = args.expect("B component")?;
let ChromaComponent(a) = args.expect("A component")?;
let ChromaComponent(b) = args.expect("B component")?;
let RatioComponent(alpha) =
args.eat()?.unwrap_or(RatioComponent(Ratio::one()));
Self::Oklab(Oklab::new(
@ -357,7 +359,8 @@ impl Color {
/// A linear Oklch color is represented internally by an array of four
/// components:
/// - lightness ([`ratio`]($ratio))
/// - chroma ([`float`]($float) in the range `[-0.4..0.4]`)
/// - chroma ([`float`]($float) in the range `[0.0..0.4]`
/// or [`ratio`]($ratio) in the range `[0%..100%]`)
/// - hue ([`angle`]($angle))
/// - alpha ([`ratio`]($ratio))
///
@ -379,7 +382,7 @@ impl Color {
lightness: RatioComponent,
/// The chroma component.
#[external]
chroma: ABComponent,
chroma: ChromaComponent,
/// The hue component.
#[external]
hue: Angle,
@ -396,7 +399,7 @@ impl Color {
color.to_oklch()
} else {
let RatioComponent(l) = args.expect("lightness component")?;
let ABComponent(c) = args.expect("chroma component")?;
let ChromaComponent(c) = args.expect("chroma component")?;
let h: Angle = args.expect("hue component")?;
let RatioComponent(alpha) =
args.eat()?.unwrap_or(RatioComponent(Ratio::one()));
@ -1730,15 +1733,17 @@ cast! {
},
}
/// A component that must be a ratio between -40% and 40%.
pub struct ABComponent(Ratio);
/// A component that must either be a value between:
/// - -100% and 100%, in which case it is relative to 0.4.
/// - -0.4 and 0.4, in which case it is taken literally.
pub struct ChromaComponent(Ratio);
cast! {
ABComponent,
v: Ratio => if (-0.4 ..= 0.4).contains(&v.get()) {
Self(v)
ChromaComponent,
v: Ratio => if (-1.0 ..= 1.0).contains(&v.get()) {
Self(v * 0.4)
} else {
bail!("ratio must be between -40% and 40%");
bail!("ratio must be between -100% and 100%");
},
v: f64 => if (-0.4 ..= 0.4).contains(&v) {
Self(Ratio::new(v))

View File

@ -109,6 +109,8 @@
#test-repr(cmyk(4%, 5%, 6%, 7%).components(), (4%, 5%, 6%, 7%))
#test-repr(oklab(10%, 0.2, 0.3).components(), (10%, 0.2, 0.3, 100%))
#test-repr(oklch(10%, 0.2, 90deg).components(), (10%, 0.2, 90deg, 100%))
#test-repr(oklab(10%, 50%, 75%).components(), (10%, 0.2, 0.3, 100%))
#test-repr(oklch(10%, 50%, 90deg).components(), (10%, 0.2, 90deg, 100%))
#test-repr(color.linear-rgb(10%, 20%, 30%).components(), (10%, 20%, 30%, 100%))
#test-repr(color.hsv(10deg, 20%, 30%).components(), (10deg, 20%, 30%, 100%))
#test-repr(color.hsl(10deg, 20%, 30%).components(), (10deg, 20%, 30%, 100%))