Skip to content

Commit 0c7083a

Browse files
authored
Add support for the display-p3-linear color space (#2703)
1 parent f6bdc02 commit 0c7083a

File tree

20 files changed

+162
-13
lines changed

20 files changed

+162
-13
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.97.0
2+
3+
* Add support for the `display-p3-linear` color space.
4+
15
## 1.96.0
26

37
* Allow numbers with complex units (more than one numerator unit or more than

lib/src/embedded/protofier.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ final class Protofier {
216216
return SassColor.srgbLinear(channel1, channel2, channel3, alpha);
217217
case ColorSpace.displayP3:
218218
return SassColor.displayP3(channel1, channel2, channel3, alpha);
219+
case ColorSpace.displayP3Linear:
220+
return SassColor.displayP3Linear(
221+
channel1, channel2, channel3, alpha);
219222
case ColorSpace.a98Rgb:
220223
return SassColor.a98Rgb(channel1, channel2, channel3, alpha);
221224
case ColorSpace.prophotoRgb:

lib/src/js/value/color.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ final JSClass colorClass = () {
100100
options.blue,
101101
_handleUndefinedAlpha(options.alpha),
102102
);
103+
case ColorSpace.displayP3Linear:
104+
return SassColor.displayP3Linear(
105+
options.red,
106+
options.green,
107+
options.blue,
108+
_handleUndefinedAlpha(options.alpha),
109+
);
103110
case ColorSpace.a98Rgb:
104111
return SassColor.a98Rgb(
105112
options.red,
@@ -345,6 +352,14 @@ final JSClass colorClass = () {
345352
changedValue('alpha'),
346353
);
347354
break;
355+
case ColorSpace.displayP3Linear:
356+
changedColor = SassColor.displayP3Linear(
357+
changedValue('red'),
358+
changedValue('green'),
359+
changedValue('blue'),
360+
changedValue('alpha'),
361+
);
362+
break;
348363
case ColorSpace.prophotoRgb:
349364
changedColor = SassColor.prophotoRgb(
350365
changedValue('red'),

lib/src/value/color.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,23 @@ class SassColor extends Value {
399399
]) =>
400400
SassColor._forSpace(ColorSpace.displayP3, red, green, blue, alpha);
401401

402+
/// Creates a color in [ColorSpace.displayP3Linear].
403+
///
404+
/// If `null` is passed for [alpha], that indicates that it's a [missing
405+
/// component]. In most cases, this is equivalent to the color being
406+
/// transparent.
407+
///
408+
/// [missing component]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#missing_color_components
409+
///
410+
/// Throws a [RangeError] if [alpha] isn't between `0` and `1`.
411+
factory SassColor.displayP3Linear(
412+
double? red,
413+
double? green,
414+
double? blue, [
415+
double? alpha = 1,
416+
]) =>
417+
SassColor._forSpace(ColorSpace.displayP3Linear, red, green, blue, alpha);
418+
402419
/// Creates a color in [ColorSpace.a98Rgb].
403420
///
404421
/// If `null` is passed for [alpha], that indicates that it's a [missing

lib/src/value/color/space.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import '../../exception.dart';
1010
import '../color.dart';
1111
import 'space/a98_rgb.dart';
1212
import 'space/display_p3.dart';
13+
import 'space/display_p3_linear.dart';
1314
import 'space/hsl.dart';
1415
import 'space/hwb.dart';
1516
import 'space/lab.dart';
@@ -54,6 +55,11 @@ abstract base class ColorSpace {
5455
/// https://www.w3.org/TR/css-color-4/#predefined-display-p3
5556
static const ColorSpace displayP3 = DisplayP3ColorSpace();
5657

58+
/// The display-p3-linear color space.
59+
///
60+
/// https://drafts.csswg.org/css-color/#predefined-display-p3-linear
61+
static const ColorSpace displayP3Linear = DisplayP3LinearColorSpace();
62+
5763
/// The a98-rgb color space.
5864
///
5965
/// https://www.w3.org/TR/css-color-4/#predefined-a98-rgb
@@ -153,6 +159,7 @@ abstract base class ColorSpace {
153159
'srgb' => srgb,
154160
'srgb-linear' => srgbLinear,
155161
'display-p3' => displayP3,
162+
'display-p3-linear' => displayP3Linear,
156163
'a98-rgb' => a98Rgb,
157164
'prophoto-rgb' => prophotoRgb,
158165
'rec2020' => rec2020,

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ final class A98RgbColorSpace extends ColorSpace {
3838
ColorSpace.srgb ||
3939
ColorSpace.rgb =>
4040
linearA98RgbToLinearSrgb,
41-
ColorSpace.displayP3 => linearA98RgbToLinearDisplayP3,
41+
ColorSpace.displayP3 ||
42+
ColorSpace.displayP3Linear =>
43+
linearA98RgbToLinearDisplayP3,
4244
ColorSpace.prophotoRgb => linearA98RgbToLinearProphotoRgb,
4345
ColorSpace.rec2020 => linearA98RgbToLinearRec2020,
4446
ColorSpace.xyzD65 => linearA98RgbToXyzD65,

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
// MIT-style license that can be found in the LICENSE file or at
33
// https://opensource.org/licenses/MIT.
44

5+
// ignore_for_file: avoid_renaming_method_parameters
6+
57
import 'dart:typed_data';
68

79
import 'package:meta/meta.dart';
810

11+
import '../../../util/nullable.dart';
12+
import '../../color.dart';
913
import '../conversions.dart';
10-
import '../space.dart';
1114
import 'utils.dart';
1215

1316
/// The display-p3 color space.
@@ -21,6 +24,18 @@ final class DisplayP3ColorSpace extends ColorSpace {
2124

2225
const DisplayP3ColorSpace() : super('display-p3', rgbChannels);
2326

27+
SassColor convert(ColorSpace dest, double? red, double? green, double? blue,
28+
double? alpha) =>
29+
dest == ColorSpace.displayP3Linear
30+
? SassColor.forSpaceInternal(
31+
dest,
32+
red.andThen(toLinear),
33+
green.andThen(toLinear),
34+
blue.andThen(toLinear),
35+
alpha,
36+
)
37+
: super.convertLinear(dest, red, green, blue, alpha);
38+
2439
@protected
2540
double toLinear(double channel) => srgbAndDisplayP3ToLinear(channel);
2641

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2025 Google Inc. Use of this source code is governed by an
2+
// MIT-style license that can be found in the LICENSE file or at
3+
// https://opensource.org/licenses/MIT.
4+
5+
// ignore_for_file: avoid_renaming_method_parameters
6+
7+
import 'dart:typed_data';
8+
9+
import 'package:meta/meta.dart';
10+
11+
import '../../../util/nullable.dart';
12+
import '../../color.dart';
13+
import '../conversions.dart';
14+
import 'utils.dart';
15+
16+
/// The display-p3-linear color space.
17+
///
18+
/// https://drafts.csswg.org/css-color/#predefined-display-p3-linear
19+
///
20+
/// @nodoc
21+
@internal
22+
final class DisplayP3LinearColorSpace extends ColorSpace {
23+
bool get isBoundedInternal => true;
24+
25+
const DisplayP3LinearColorSpace() : super('display-p3-linear', rgbChannels);
26+
27+
SassColor convert(
28+
ColorSpace dest,
29+
double? red,
30+
double? green,
31+
double? blue,
32+
double? alpha,
33+
) =>
34+
dest == ColorSpace.displayP3
35+
? SassColor.forSpaceInternal(
36+
dest,
37+
red.andThen(srgbAndDisplayP3FromLinear),
38+
green.andThen(srgbAndDisplayP3FromLinear),
39+
blue.andThen(srgbAndDisplayP3FromLinear),
40+
alpha,
41+
)
42+
: super.convert(dest, red, green, blue, alpha);
43+
44+
@protected
45+
double toLinear(double channel) => channel;
46+
47+
@protected
48+
double fromLinear(double channel) => channel;
49+
50+
@protected
51+
Float64List transformationMatrix(ColorSpace dest) => switch (dest) {
52+
ColorSpace.srgbLinear ||
53+
ColorSpace.srgb ||
54+
ColorSpace.rgb =>
55+
linearDisplayP3ToLinearSrgb,
56+
ColorSpace.a98Rgb => linearDisplayP3ToLinearA98Rgb,
57+
ColorSpace.prophotoRgb => linearDisplayP3ToLinearProphotoRgb,
58+
ColorSpace.rec2020 => linearDisplayP3ToLinearRec2020,
59+
ColorSpace.xyzD65 => linearDisplayP3ToXyzD65,
60+
ColorSpace.xyzD50 => linearDisplayP3ToXyzD50,
61+
ColorSpace.lms => linearDisplayP3ToLms,
62+
_ => super.transformationMatrix(dest),
63+
};
64+
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ final class LmsColorSpace extends ColorSpace {
128128
lmsToLinearSrgb,
129129
ColorSpace.a98Rgb => lmsToLinearA98Rgb,
130130
ColorSpace.prophotoRgb => lmsToLinearProphotoRgb,
131-
ColorSpace.displayP3 => lmsToLinearDisplayP3,
131+
ColorSpace.displayP3 ||
132+
ColorSpace.displayP3Linear =>
133+
lmsToLinearDisplayP3,
132134
ColorSpace.rec2020 => lmsToLinearRec2020,
133135
ColorSpace.xyzD65 => lmsToXyzD65,
134136
ColorSpace.xyzD50 => lmsToXyzD50,

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ final class ProphotoRgbColorSpace extends ColorSpace {
4545
ColorSpace.rgb =>
4646
linearProphotoRgbToLinearSrgb,
4747
ColorSpace.a98Rgb => linearProphotoRgbToLinearA98Rgb,
48-
ColorSpace.displayP3 => linearProphotoRgbToLinearDisplayP3,
48+
ColorSpace.displayP3 ||
49+
ColorSpace.displayP3Linear =>
50+
linearProphotoRgbToLinearDisplayP3,
4951
ColorSpace.rec2020 => linearProphotoRgbToLinearRec2020,
5052
ColorSpace.xyzD65 => linearProphotoRgbToXyzD65,
5153
ColorSpace.xyzD50 => linearProphotoRgbToXyzD50,

0 commit comments

Comments
 (0)