Skip to content

Commit

Permalink
[Color 4] Require an explicit gamut mapping method
Browse files Browse the repository at this point in the history
  • Loading branch information
nex3 committed Apr 13, 2024
1 parent 5551422 commit f94c8dc
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 23 deletions.
7 changes: 7 additions & 0 deletions accepted/color-4-new-spaces.changes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Draft 1.14

* Add a mandatory `$method` parameter to `color.to-gamut()` for
forwards-compatibility with better gamut-mapping algorithms.

* Add `clip` as a gamut-mapping algorithm.

## Draft 1.13

* Remove definitions of powerless channels that are no longer present in CSS
Expand Down
80 changes: 57 additions & 23 deletions accepted/color-4-new-spaces.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CSS Color Level 4, New Color Spaces: Draft 1.13
# CSS Color Level 4, New Color Spaces: Draft 1.14

*([Issue](https://github.com/sass/sass/issues/2831))*

Expand Down Expand Up @@ -508,14 +508,27 @@ and mapping in Sass color functions:

#### Gamut Mapping

Browsers currently use channel-clipping rather than the proposed
[css gamut mapping algorithm][css-mapping] to handle colors that cannot be
shown correctly on a given display. We've decided to provide `color.to-gamut()`
as a way for authors to opt-into the proposed behavior, aware that browsers
may eventually choose to provide a different algorithm. If that happens, we
will consider adding an additional algorithm-selection argument. However, the
primary goal of this function is not to match CSS behavior, but to provide a
better mapping than the default channel-clipping.
Browsers currently use channel-clipping rather than the proposed [css gamut
mapping algorithm][css-mapping] to handle colors that cannot be shown correctly
on a given display. Moreover, there is still active discussion among the CSS
working group and browser vendors about what the best gamut mapping algorithm
is, with the currently-specified algorithm widely considered to be sub-optimal.
As such, we want to avoid baking it in as the default for Sass such that any
change would require a deprecation period.

At the same time, we expect gamut-mapping to be very useful for Sass authors
working with wide-gamut color spaces, enough so that we want it to be available
without needing to wait on the CSSWG to come to a consensus on the best
algorithm. To that end, we've decided to provide `color.to-gamut()` but
_require_ a `$method` argument for forwards-compatibility with better gamut
mapping algorithms.

Initially, there will only be two available arguments for `$method`:
`local-minde`, the gamut mapping algorithm specified in Color 4 at the time this
spec is written, and `clip` which will just clip any channel values that are
out-of-range for a given color space. However, we expect to expand this to
additional algorithms in the future, and to eventually make it optional and have
its default match the behavior of CSS.

#### CSS Color 5

Expand Down Expand Up @@ -1016,28 +1029,46 @@ The individual conversion algorithms are:
> available 'in-gamut' color. Gamut mapping is the process of finding an
> in-gamut color with the least objectionable change in visual appearance.
Gamut mapping in Sass follows the [CSS gamut mapping algorithm][css-mapping].
This procedure accepts a color `origin`, and a [known color space]
`destination`. It returns the result of a [CSS gamut map][css-map] procedure,
converted back into the original color space.
Gamut mapping color `origin`, a [known color space] `destination`, and an
unquoted string `method`. It returns a color in `origin`'s color space.

* Let `origin-space` be `origin`'s color space.

* If either `origin-space` or `destination` is not a [known color space], throw
an error.

* Let `mapped` be the result of [CSS gamut mapping][css-mapping] `origin`
color, with an origin color space of `origin-space`, and destination of
`destination`.
* Let `color` be the result of [converting] `origin` into `destination`.

* If `method` is not one of the methods defined below, throw an error.

* Let `mapped` be the result of running the method defined below whose name
matches `method`. If no such method matches, throw an error.

* Return the result of [converting] `mapped` into `origin-space`.

#### `local-minde`

The `local-minde` gamut mapping procedure in Sass follows the 13 February 2024
draft of CSS Color Module Level 4. It returns the result of [CSS gamut
mapping][css-mapping] `origin` with an origin color space of `origin-space` and
destination of `destination`.

> This algorithm implements a relative colorimetric intent, and colors inside
> the destination gamut are unchanged. Since the process is lossy, authors
> should be encouraged to let the browser handle gamut mapping when possible.
> the destination gamut are unchanged.
#### `clip`

[css-mapping]: https://www.w3.org/TR/css-color-4/#css-gamut-mapping-algorithm
[css-map]: https://www.w3.org/TR/css-color-4/#css-gamut-map
The `clip` gamut mapping procedure is not expected to produce good-looking
results, but it can be useful to match the current behavior of browsers.

* Let `new-color` be a copy of `color`.

* For each `channel` in `destination`:

* If `channel` is bounded, set `new-color`'s `channel` value to the result of
clamping the original value within `channel`'s minimum and maximum values.

* Return `new-color`.

### Parsing Color Components

Expand Down Expand Up @@ -1626,11 +1657,14 @@ is-in-gamut($color, $space: null)
### `color.to-gamut()`

```
to-gamut($color, $space: null)
to-gamut($color, $space: null, $method: null)
```

* If `$color` is not a color, throw an error.

* If `$method` is not an unquoted string whose value is either `local-minde` or
`clip`, throw an error.

* If `$space` is null:

* Let `origin-space` be the result of calling `color.space($color)`.
Expand All @@ -1641,8 +1675,8 @@ to-gamut($color, $space: null)
* Otherwise, let `target-space` be the result of [looking up a known color
space] named `$space`.

* Return the result of [gamut mapping] `$color` with a `target-space`
destination.
* Return the result of [gamut mapping] `$color` with destination `target-space`
and method `$method`.

[gamut mapping]: #gamut-mapping

Expand Down

0 comments on commit f94c8dc

Please sign in to comment.