Skip to content

Commit 67a1109

Browse files
authored
Use a negative-safe cube root in LMS conversions (#2121)
See w3c/csswg-drafts#9477
1 parent 95a0ec5 commit 67a1109

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

lib/src/value/color/space/lms.dart

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ class LmsColorSpace extends ColorSpace {
3737
switch (dest) {
3838
case ColorSpace.oklab:
3939
// Algorithm from https://drafts.csswg.org/css-color-4/#color-conversion-code
40-
var longScaled = math.pow(long, 1 / 3);
41-
var mediumScaled = math.pow(medium, 1 / 3);
42-
var shortScaled = math.pow(short, 1 / 3);
40+
var longScaled = _cubeRootPreservingSign(long);
41+
var mediumScaled = _cubeRootPreservingSign(medium);
42+
var shortScaled = _cubeRootPreservingSign(short);
4343
var lightness = lmsToOklab[0] * longScaled +
4444
lmsToOklab[1] * mediumScaled +
4545
lmsToOklab[2] * shortScaled;
@@ -62,9 +62,9 @@ class LmsColorSpace extends ColorSpace {
6262
// This is equivalent to converting to OKLab and then to OKLCH, but we
6363
// do it inline to avoid extra list allocations since we expect
6464
// conversions to and from OKLCH to be very common.
65-
var longScaled = math.pow(long, 1 / 3);
66-
var mediumScaled = math.pow(medium, 1 / 3);
67-
var shortScaled = math.pow(short, 1 / 3);
65+
var longScaled = _cubeRootPreservingSign(long);
66+
var mediumScaled = _cubeRootPreservingSign(medium);
67+
var shortScaled = _cubeRootPreservingSign(short);
6868
return labToLch(
6969
dest,
7070
lmsToOklab[0] * longScaled +
@@ -83,6 +83,11 @@ class LmsColorSpace extends ColorSpace {
8383
}
8484
}
8585

86+
/// Returns the cube root of the absolute value of [number] with the same sign
87+
/// as [number].
88+
double _cubeRootPreservingSign(double number) =>
89+
math.pow(number.abs(), 1 / 3) * number.sign;
90+
8691
@protected
8792
double toLinear(double channel) => channel;
8893

0 commit comments

Comments
 (0)