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