Skip to content

Commit 216ceb7

Browse files
authoredMar 23, 2023
Update specs for sass/sass#3497 (#1919)
1 parent e5aa642 commit 216ceb7

File tree

3 files changed

+67
-65
lines changed

3 files changed

+67
-65
lines changed
 

‎lib/src/functions/color.dart

+12-5
Original file line numberDiff line numberDiff line change
@@ -614,11 +614,6 @@ Value _invert(List<Value> arguments) {
614614
}
615615

616616
if (fuzzyEquals(weight, 1)) return inverted;
617-
if (!InterpolationMethod.supportedSpaces.contains(space)) {
618-
throw SassScriptException(
619-
"Color space $space can't be used for interpolation.", "space");
620-
}
621-
622617
return color.interpolate(inverted, InterpolationMethod(space),
623618
weight: 1 - weight);
624619
}
@@ -1290,6 +1285,18 @@ SassColor _colorFromChannels(ColorSpace space, SassNumber? channel0,
12901285
alpha,
12911286
fromRgbFunction ? ColorFormat.rgbFunction : null);
12921287

1288+
case ColorSpace.lab:
1289+
case ColorSpace.lch:
1290+
case ColorSpace.oklab:
1291+
case ColorSpace.oklch:
1292+
return SassColor.forSpaceInternal(
1293+
space,
1294+
_channelFromValue(space.channels[0], channel0)
1295+
.andThen((lightness) => fuzzyClamp(lightness, 0, 100)),
1296+
_channelFromValue(space.channels[1], channel1),
1297+
_channelFromValue(space.channels[2], channel2),
1298+
alpha);
1299+
12931300
default:
12941301
return SassColor.forSpaceInternal(
12951302
space,

‎lib/src/value/color.dart

+53-22
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class SassColor extends Value {
123123
case ColorSpace.oklab:
124124
case ColorSpace.lch:
125125
case ColorSpace.oklch:
126-
return fuzzyEquals(channel0, 0);
126+
return fuzzyEquals(channel0, 0) || fuzzyEquals(channel0, 100);
127127

128128
default:
129129
return false;
@@ -156,11 +156,13 @@ class SassColor extends Value {
156156
switch (space) {
157157
case ColorSpace.lab:
158158
case ColorSpace.oklab:
159-
return fuzzyEquals(channel0, 0);
159+
return fuzzyEquals(channel0, 0) || fuzzyEquals(channel0, 100);
160160

161161
case ColorSpace.lch:
162162
case ColorSpace.oklch:
163-
return fuzzyEquals(channel0, 0) || fuzzyEquals(channel1, 0);
163+
return fuzzyEquals(channel0, 0) ||
164+
fuzzyEquals(channel0, 100) ||
165+
fuzzyEquals(channel1, 0);
164166

165167
default:
166168
return false;
@@ -285,7 +287,7 @@ class SassColor extends Value {
285287
[num? alpha]) =>
286288
SassColor.forSpaceInternal(
287289
ColorSpace.hsl,
288-
hue?.toDouble(),
290+
_normalizeHue(hue?.toDouble()),
289291
saturation.andThen((saturation) =>
290292
fuzzyAssertRange(saturation.toDouble(), 0, 100, "saturation")),
291293
lightness.andThen((lightness) =>
@@ -299,7 +301,7 @@ class SassColor extends Value {
299301
[num? alpha]) =>
300302
SassColor.forSpaceInternal(
301303
ColorSpace.hwb,
302-
hue?.toDouble(),
304+
_normalizeHue(hue?.toDouble()),
303305
whiteness.andThen((whiteness) =>
304306
fuzzyAssertRange(whiteness.toDouble(), 0, 100, "whiteness")),
305307
blackness.andThen((blackness) =>
@@ -367,29 +369,52 @@ class SassColor extends Value {
367369
/// Throws a [RangeError] if [alpha] isn't between `0` and `1`.
368370
factory SassColor.lab(double? lightness, double? a, double? b,
369371
[double? alpha]) =>
370-
SassColor.forSpaceInternal(ColorSpace.lab, lightness, a, b, alpha);
372+
SassColor.forSpaceInternal(
373+
ColorSpace.lab,
374+
lightness.andThen(
375+
(lightness) => fuzzyAssertRange(lightness, 0, 100, "lightness")),
376+
a,
377+
b,
378+
alpha);
371379

372380
/// Creates a color in [ColorSpace.lch].
373381
///
374382
/// Throws a [RangeError] if [alpha] isn't between `0` and `1`.
375383
factory SassColor.lch(double? lightness, double? chroma, double? hue,
376384
[double? alpha]) =>
377-
SassColor.forSpaceInternal(ColorSpace.lch, lightness, chroma, hue, alpha);
385+
SassColor.forSpaceInternal(
386+
ColorSpace.lch,
387+
lightness.andThen(
388+
(lightness) => fuzzyAssertRange(lightness, 0, 100, "lightness")),
389+
chroma,
390+
_normalizeHue(hue),
391+
alpha);
378392

379393
/// Creates a color in [ColorSpace.oklab].
380394
///
381395
/// Throws a [RangeError] if [alpha] isn't between `0` and `1`.
382396
factory SassColor.oklab(double? lightness, double? a, double? b,
383397
[double? alpha]) =>
384-
SassColor.forSpaceInternal(ColorSpace.oklab, lightness, a, b, alpha);
398+
SassColor.forSpaceInternal(
399+
ColorSpace.oklab,
400+
lightness.andThen(
401+
(lightness) => fuzzyAssertRange(lightness, 0, 100, "lightness")),
402+
a,
403+
b,
404+
alpha);
385405

386406
/// Creates a color in [ColorSpace.oklch].
387407
///
388408
/// Throws a [RangeError] if [alpha] isn't between `0` and `1`.
389409
factory SassColor.oklch(double? lightness, double? chroma, double? hue,
390410
[double? alpha]) =>
391411
SassColor.forSpaceInternal(
392-
ColorSpace.oklch, lightness, chroma, hue, alpha);
412+
ColorSpace.oklch,
413+
lightness.andThen(
414+
(lightness) => fuzzyAssertRange(lightness, 0, 100, "lightness")),
415+
chroma,
416+
_normalizeHue(hue),
417+
alpha);
393418

394419
/// Creates a color in the color space named [space].
395420
///
@@ -401,14 +426,17 @@ class SassColor extends Value {
401426
throw RangeError.value(channels.length, "channels.length",
402427
'must be exactly ${space.channels.length} for color space "$space"');
403428
} else {
404-
var clampChannels = space == ColorSpace.hsl || space == ColorSpace.hwb;
429+
var clampChannel0 = space.channels[0].name == "lightness";
430+
var clampChannel12 = space == ColorSpace.hsl || space == ColorSpace.hwb;
405431
return SassColor.forSpaceInternal(
406432
space,
407-
channels[0],
408-
clampChannels
433+
clampChannel0
434+
? channels[0].andThen((value) => fuzzyClamp(value, 0, 100))
435+
: channels[0],
436+
clampChannel12
409437
? channels[1].andThen((value) => fuzzyClamp(value, 0, 100))
410438
: channels[1],
411-
clampChannels
439+
clampChannel12
412440
? channels[2].andThen((value) => fuzzyClamp(value, 0, 100))
413441
: channels[2],
414442
alpha);
@@ -432,6 +460,12 @@ class SassColor extends Value {
432460
"[BUG] Tried to create "
433461
"$_space(${channel0OrNull ?? 'none'}, ${channel1OrNull ?? 'none'}, "
434462
"${channel2OrNull ?? 'none'})");
463+
assert(
464+
space.channels[0].name != "lightness" ||
465+
fuzzyCheckRange(channel0, 0, 100) != null,
466+
"[BUG] Tried to create "
467+
"$_space(${channel0OrNull ?? 'none'}, ${channel1OrNull ?? 'none'}, "
468+
"${channel2OrNull ?? 'none'})");
435469
assert(space != ColorSpace.lms);
436470

437471
_checkChannel(channel0OrNull, space.channels[0].name);
@@ -449,6 +483,12 @@ class SassColor extends Value {
449483
}
450484
}
451485

486+
/// If [hue] isn't null, normalizes it to the range `[0, 360)`.
487+
static double? _normalizeHue(double? hue) {
488+
if (hue == null) return hue;
489+
return (hue % 360 + 360) % 360;
490+
}
491+
452492
/// @nodoc
453493
@internal
454494
T accept<T>(ValueVisitor<T> visitor) => visitor.visitColor(this);
@@ -894,11 +934,6 @@ class SassColor extends Value {
894934
double _interpolateHues(
895935
double hue1, double hue2, HueInterpolationMethod method, double weight) {
896936
// Algorithms from https://www.w3.org/TR/css-color-4/#hue-interpolation
897-
if (method != HueInterpolationMethod.specified) {
898-
hue1 = (hue1 % 360 + 360) % 360;
899-
hue2 = (hue2 % 360 + 360) % 360;
900-
}
901-
902937
switch (method) {
903938
case HueInterpolationMethod.shorter:
904939
var difference = hue2 - hue1;
@@ -925,10 +960,6 @@ class SassColor extends Value {
925960
case HueInterpolationMethod.decreasing:
926961
if (hue1 < hue2) hue1 += 360;
927962
break;
928-
929-
case HueInterpolationMethod.specified:
930-
// Use the hues as-is.
931-
break;
932963
}
933964

934965
return hue1 * weight + hue2 * (1 - weight);

‎lib/src/value/color/interpolation_method.dart

+2-38
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// MIT-style license that can be found in the LICENSE file or at
33
// https://opensource.org/licenses/MIT.
44

5-
import 'package:meta/meta.dart';
6-
75
import '../../exception.dart';
86
import '../../value.dart';
97

@@ -14,23 +12,6 @@ import '../../value.dart';
1412
///
1513
/// {@category Value}
1614
class InterpolationMethod {
17-
/// The set of color spaces that can be used for color interpolation.
18-
///
19-
/// @nodoc
20-
@internal
21-
static const supportedSpaces = {
22-
ColorSpace.srgb,
23-
ColorSpace.srgbLinear,
24-
ColorSpace.lab,
25-
ColorSpace.oklab,
26-
ColorSpace.xyzD50,
27-
ColorSpace.xyzD65,
28-
ColorSpace.hsl,
29-
ColorSpace.hwb,
30-
ColorSpace.lch,
31-
ColorSpace.oklch
32-
};
33-
3415
/// The color space in which to perform the interpolation.
3516
final ColorSpace space;
3617

@@ -41,10 +22,7 @@ class InterpolationMethod {
4122

4223
InterpolationMethod(this.space, [HueInterpolationMethod? hue])
4324
: hue = space.isPolar ? hue ?? HueInterpolationMethod.shorter : null {
44-
if (!supportedSpaces.contains(space)) {
45-
throw ArgumentError(
46-
"Color space $space can't be used for interpolation.");
47-
} else if (!space.isPolar && hue != null) {
25+
if (!space.isPolar && hue != null) {
4826
throw ArgumentError(
4927
"Hue interpolation method may not be set for rectangular color space "
5028
"$space.");
@@ -66,11 +44,6 @@ class InterpolationMethod {
6644

6745
var space = ColorSpace.fromName(
6846
(list.first.assertString(name)..assertUnquoted(name)).text, name);
69-
if (!supportedSpaces.contains(space)) {
70-
throw SassScriptException(
71-
"Color space $space can't be used for interpolation.", name);
72-
}
73-
7447
if (list.length == 1) return InterpolationMethod(space);
7548

7649
var hueMethod = HueInterpolationMethod._fromValue(list[1], name);
@@ -124,14 +97,7 @@ enum HueInterpolationMethod {
12497
/// Angles are adjusted so that `θ₂ - θ₁ ∈ (-360, 0]`.
12598
///
12699
/// https://www.w3.org/TR/css-color-4/#hue-decreasing
127-
decreasing,
128-
129-
/// No fixup is performed.
130-
///
131-
/// Angles are interpolated in the same way as every other component.
132-
///
133-
/// https://www.w3.org/TR/css-color-4/#hue-specified
134-
specified;
100+
decreasing;
135101

136102
/// Parses a SassScript value representing a hue interpolation method, not
137103
/// ending with "hue".
@@ -150,8 +116,6 @@ enum HueInterpolationMethod {
150116
return HueInterpolationMethod.increasing;
151117
case 'decreasing':
152118
return HueInterpolationMethod.decreasing;
153-
case 'specified':
154-
return HueInterpolationMethod.specified;
155119
default:
156120
throw SassScriptException(
157121
'Unknown hue interpolation method $value.', name);

0 commit comments

Comments
 (0)
Please sign in to comment.