Skip to content

Commit 09bc009

Browse files
committed
[css-color] move color interpolation from color-5 to color-4, see #5883
1 parent dd01b5d commit 09bc009

File tree

2 files changed

+164
-162
lines changed

2 files changed

+164
-162
lines changed

css-color-4/Overview.bs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4353,6 +4353,170 @@ Simple alpha compositing</h3>
43534353
When drawing, implementations must handle alpha
43544354
according to the rules in <a href="https://www.w3.org/TR/compositing-1/#simplealphacompositing">Section 5.1 Simple alpha compositing</a> of [[!Compositing]].
43554355

4356+
Interpolation {#interpolation}
4357+
===================================
4358+
4359+
Color interpolation happens with
4360+
gradients,
4361+
compositing,
4362+
filters,
4363+
transitions,
4364+
animations, and
4365+
color mixing and color modification functions.
4366+
4367+
In general, interpolation between <<color>> values of the same [=colorspace=]
4368+
occurs by linearly interpolating each component of the computed value of the color
4369+
separately, in that colorspace.
4370+
This provides Web compatibility; legacy sRGB content interpolates in the sRGB space by default.
4371+
4372+
4373+
Interpolating to or from ''<color>/currentcolor'' is possible.
4374+
The numerical value used for this purpose is the used value.
4375+
4376+
ISSUE: Computed value needs to be able to represent
4377+
combinations of ''currentColor'' and an actual color.
4378+
Consider the value of 'text-emphasis-color' in
4379+
<code>div { text-emphasis: circle; transition: all 2s; }<br>
4380+
div:hover { text-emphasis-color: lime; }<br>
4381+
em { color: red; }</code>
4382+
See <a href="https://github.com/w3c/csswg-drafts/issues/445">Issue 445</a>.
4383+
4384+
Color space for interpolation {#interpolation-space}
4385+
------------------------------
4386+
4387+
Issue: Should gamut mapping occur before or after interpolation?
4388+
4389+
If colors are not in the same color space,
4390+
they are first converted to Lab
4391+
and then interpolated as Lab colors.
4392+
Host syntax can override the interpolation color space and specify which color space is used for interpolation.
4393+
For example, 'color-mix' and 'color-adjust' override the default to LCH.
4394+
4395+
4396+
Interpolating with alpha {#interpolation-alpha}
4397+
------------------------
4398+
4399+
When the colors to be interpolated are not fully opaque,
4400+
they are transformed into <dfn export>premultiplied color values</dfn>
4401+
as follows:
4402+
4403+
* For [=rectangular orthogonal color=] coordinate systems,
4404+
all component values are multiplied by the alpha value
4405+
* For [=cylindrical polar color=] coordinate systems,
4406+
the hue angle is not premultiplied,
4407+
but the other two axes are premultiplied.
4408+
4409+
To obtain a color value from a premultipled color value,
4410+
each component which had been premultiplied
4411+
is divided by the interpolated alpha value.
4412+
4413+
<div class="example" id="ex-premultiplied-srgb">
4414+
For example, to interpolate the two sRGB colors
4415+
<span class="swatch" style="--color: rgb(24%, 12%, 98%, 0.4)"></span> rgb(24% 12% 98% / 0.4)
4416+
and
4417+
<span class="swatch" style="--color: rgb(62% 26% 64% / 0.6)"></span> rgb(62% 26% 64% / 0.6)
4418+
they would first be converted to premultiplied form
4419+
[9.6% 4.8% 39.2% ]
4420+
and
4421+
[37.2% 15.6% 38.4%]
4422+
before interpolation.
4423+
4424+
The midpoint of linearly interpolating these colors
4425+
would be [23.4% 10.2% 38.8%]
4426+
which, with an alpha value of 0.5,
4427+
is <span class="swatch" style="--color: rgb(46.8%, 21.4%, 77.6%, 0.5)"></span> rgb(46.8% 20.4% 77.6% / 0.5)
4428+
when premultiplication is undone.
4429+
</div>
4430+
4431+
<div class="example" id="ex-premultiplied-lab">
4432+
To interpolate two colors in lab
4433+
<span class="swatch" style="--color: rgb(76%, 62%, 03%, 0.4)"></span> rgb(76% 62% 03% / 0.4)
4434+
and
4435+
<span class="swatch" style="--color: rgb(91.56%, 3.87%, 74.09%, 0.6)"></span> color(display-p3 0.84 0.19 0.72 / 0.6)
4436+
they are first converted to lab
4437+
<span class="swatch" style="--color: rgb(76%, 62%, 03%, 0.4)"></span> lab(66.927% 4.873 68.622 / 0.4)
4438+
<span class="swatch" style="--color: rgb(91.56%, 3.87%, 74.09%, 0.6)"></span> lab(53.503% 82.672 -33.901 / 0.6)
4439+
then the L, a and b coordinates are premultiplied before interpolation
4440+
[26.771% 1.949 27.449]
4441+
and
4442+
[32.102% 49.603 -20.341].
4443+
4444+
The midpoint of linearly interpolating these would be
4445+
[29.4365% 25.776 3.554]
4446+
which, with an alpha value of 0.5,
4447+
is <span class="swatch" style="--color: rgb(87.604%, 38.956%, 51.753%, 0.5)"></span> lab(58.873% 51.552 7.108) / 0.5)
4448+
when premultiplication is undone.
4449+
</div>
4450+
4451+
Issue(445):
4452+
4453+
Hue interpolation {#hue-interpolation}
4454+
-------------------
4455+
4456+
Issue(4928): How to handle achromatic interpolation?
4457+
4458+
For color functions with a hue angle (LCH, HSL, HWB etc), there are multiple ways to interpolate.
4459+
We typically want to avoid arcs over 360 for the difference between the angles, as they are rarely desirable,
4460+
so in most cases angles are fixed up prior to interpolation so that per-component interpolation is done over less than 360 degrees, often less than 180.
4461+
4462+
Host syntax can specify any of the following algorithms for hue interpolation
4463+
(angles in the following are in degrees, but the logic is the same regardless of how they are specified).
4464+
4465+
Unless the type of hue interpolation is ''specified'', both angles need to be constrained to [0, 360) prior to interpolation.
4466+
One way to do this is <code><i>θ</i> = ((<i>θ</i> % 360) + 360) % 360</code>.
4467+
4468+
: ''shorter''
4469+
:: Angles are adjusted so that θ₂ - θ₁ ∈ [-180, 180]. In pseudo-Javascript:
4470+
<pre>
4471+
if (θ₂ - θ₁ > 180) {
4472+
θ₁ += 360;
4473+
}
4474+
else if (θ₂ - θ₁ < -180) {
4475+
θ₂ += 360;
4476+
}
4477+
</pre>
4478+
4479+
: ''longer''
4480+
:: Angles are adjusted so that |θ₂ - θ₁| ∈ {0, [180, 360)}. In pseudo-Javascript:
4481+
<pre>
4482+
if (0 < θ₂ - θ₁ < 180) {
4483+
θ₁ += 360;
4484+
}
4485+
else if (-180 < θ₂ - θ₁ < 0) {
4486+
θ₂ += 360;
4487+
}
4488+
</pre>
4489+
4490+
: ''increasing''
4491+
:: Angles are adjusted so that θ₂ - θ₁ ∈ [0, 360). In pseudo-Javascript:
4492+
<pre>
4493+
if (θ₂ < θ₁) {
4494+
θ₂ += 360;
4495+
}
4496+
</pre>
4497+
4498+
: ''decreasing''
4499+
:: Angles are adjusted so that θ₂ - θ₁ ∈ (-360, 0]. In pseudo-Javascript:
4500+
<pre>
4501+
if (θ₁ < θ₂) {
4502+
θ₁ += 360;
4503+
}
4504+
</pre>
4505+
4506+
: ''specified''
4507+
:: No fixup is performed. Angles are interpolated in the same way as every other component.
4508+
4509+
Unless otherwise specified, if no specific hue interpolation algorithm is selected by the host syntax, the default is ''shorter''.
4510+
4511+
If one of the angles has the value NaN,
4512+
then for interpolation, NaN is replaced
4513+
by the value of the other hue angle.
4514+
If both angles have the value NaN,
4515+
then for interpolation, NaN is replaced
4516+
by the value 0 for both angles.
4517+
4518+
Issue(5277): How do these work when interpolating between multiple colors?
4519+
43564520

43574521
<h2 id="sample">
43584522
Default Style Rules</h2>

css-color-5/Overview.bs

Lines changed: 0 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -746,169 +746,7 @@ When an origin color is present, the following keywords can also be used in this
746746
</pre>
747747
</div>
748748

749-
Interpolation {#interpolation}
750-
===================================
751-
752-
Color interpolation happens with
753-
gradients,
754-
compositing,
755-
filters,
756-
transitions,
757-
animations, and
758-
color mixing and color modification functions.
759-
760-
In general, interpolation between <<color>> values of the same [=colorspace=]
761-
occurs by linearly interpolating each component of the computed value of the color
762-
separately, in that colorspace.
763-
This provides Web compatibility; legacy sRGB content interpolates in the sRGB space by default.
764-
765-
766-
Interpolating to or from ''<color>/currentcolor'' is possible.
767-
The numerical value used for this purpose is the used value.
768-
769-
ISSUE: Computed value needs to be able to represent
770-
combinations of ''currentColor'' and an actual color.
771-
Consider the value of 'text-emphasis-color' in
772-
<code>div { text-emphasis: circle; transition: all 2s; }<br>
773-
div:hover { text-emphasis-color: lime; }<br>
774-
em { color: red; }</code>
775-
See <a href="https://github.com/w3c/csswg-drafts/issues/445">Issue 445</a>.
776-
777-
Color space for interpolation {#interpolation-space}
778-
------------------------------
779-
780-
Issue: Should gamut mapping occur before or after interpolation?
781-
782-
If colors are not in the same color space,
783-
they are first converted to Lab
784-
and then interpolated as Lab colors.
785-
Host syntax can override the interpolation color space and specify which color space is used for interpolation.
786-
For example, 'color-mix' and 'color-adjust' override the default to LCH.
787-
788-
789-
Interpolating with alpha {#interpolation-alpha}
790-
------------------------
791-
792-
When the colors to be interpolated are not fully opaque,
793-
they are transformed into <dfn export>premultiplied color values</dfn>
794-
as follows:
795-
796-
* For [=rectangular orthogonal color=] coordinate systems,
797-
all component values are multiplied by the alpha value
798-
* For [=cylindrical polar color=] coordinate systems,
799-
the hue angle is not premultiplied,
800-
but the other two axes are premultiplied.
801-
802-
To obtain a color value from a premultipled color value,
803-
each component which had been premultiplied
804-
is divided by the interpolated alpha value.
805-
806-
<div class="example" id="ex-premultiplied-srgb">
807-
For example, to interpolate the two sRGB colors
808-
<span class="swatch" style="--color: rgb(24%, 12%, 98%, 0.4)"></span> rgb(24% 12% 98% / 0.4)
809-
and
810-
<span class="swatch" style="--color: rgb(62% 26% 64% / 0.6)"></span> rgb(62% 26% 64% / 0.6)
811-
they would first be converted to premultiplied form
812-
[9.6% 4.8% 39.2% ]
813-
and
814-
[37.2% 15.6% 38.4%]
815-
before interpolation.
816-
817-
The midpoint of linearly interpolating these colors
818-
would be [23.4% 10.2% 38.8%]
819-
which, with an alpha value of 0.5,
820-
is <span class="swatch" style="--color: rgb(46.8%, 21.4%, 77.6%, 0.5)"></span> rgb(46.8% 20.4% 77.6% / 0.5)
821-
when premultiplication is undone.
822-
</div>
823-
824-
<div class="example" id="ex-premultiplied-lab">
825-
To interpolate two colors in lab
826-
<span class="swatch" style="--color: rgb(76%, 62%, 03%, 0.4)"></span> rgb(76% 62% 03% / 0.4)
827-
and
828-
<span class="swatch" style="--color: rgb(91.56%, 3.87%, 74.09%, 0.6)"></span> color(display-p3 0.84 0.19 0.72 / 0.6)
829-
they are first converted to lab
830-
<span class="swatch" style="--color: rgb(76%, 62%, 03%, 0.4)"></span> lab(66.927% 4.873 68.622 / 0.4)
831-
<span class="swatch" style="--color: rgb(91.56%, 3.87%, 74.09%, 0.6)"></span> lab(53.503% 82.672 -33.901 / 0.6)
832-
then the L, a and b coordinates are premultiplied before interpolation
833-
[26.771% 1.949 27.449]
834-
and
835-
[32.102% 49.603 -20.341].
836-
837-
The midpoint of linearly interpolating these would be
838-
[29.4365% 25.776 3.554]
839-
which, with an alpha value of 0.5,
840-
is <span class="swatch" style="--color: rgb(87.604%, 38.956%, 51.753%, 0.5)"></span> lab(58.873% 51.552 7.108) / 0.5)
841-
when premultiplication is undone.
842-
</div>
843-
844-
Issue(445):
845-
846-
Hue interpolation {#hue-interpolation}
847-
-------------------
848-
849-
Issue(4928): How to handle achromatic interpolation?
850-
851-
For color functions with a hue angle (LCH, HSL, HWB etc), there are multiple ways to interpolate.
852-
We typically want to avoid arcs over 360 for the difference between the angles, as they are rarely desirable,
853-
so in most cases angles are fixed up prior to interpolation so that per-component interpolation is done over less than 360 degrees, often less than 180.
854-
855-
Host syntax can specify any of the following algorithms for hue interpolation
856-
(angles in the following are in degrees, but the logic is the same regardless of how they are specified).
857-
858-
Unless the type of hue interpolation is ''specified'', both angles need to be constrained to [0, 360) prior to interpolation.
859-
One way to do this is <code><i>θ</i> = ((<i>θ</i> % 360) + 360) % 360</code>.
860-
861-
: ''shorter''
862-
:: Angles are adjusted so that θ₂ - θ₁ ∈ [-180, 180]. In pseudo-Javascript:
863-
<pre>
864-
if (θ₂ - θ₁ > 180) {
865-
θ₁ += 360;
866-
}
867-
else if (θ₂ - θ₁ < -180) {
868-
θ₂ += 360;
869-
}
870-
</pre>
871-
872-
: ''longer''
873-
:: Angles are adjusted so that |θ₂ - θ₁| ∈ {0, [180, 360)}. In pseudo-Javascript:
874-
<pre>
875-
if (0 < θ₂ - θ₁ < 180) {
876-
θ₁ += 360;
877-
}
878-
else if (-180 < θ₂ - θ₁ < 0) {
879-
θ₂ += 360;
880-
}
881-
</pre>
882-
883-
: ''increasing''
884-
:: Angles are adjusted so that θ₂ - θ₁ ∈ [0, 360). In pseudo-Javascript:
885-
<pre>
886-
if (θ₂ < θ₁) {
887-
θ₂ += 360;
888-
}
889-
</pre>
890-
891-
: ''decreasing''
892-
:: Angles are adjusted so that θ₂ - θ₁ ∈ (-360, 0]. In pseudo-Javascript:
893-
<pre>
894-
if (θ₁ < θ₂) {
895-
θ₁ += 360;
896-
}
897-
</pre>
898-
899-
: ''specified''
900-
:: No fixup is performed. Angles are interpolated in the same way as every other component.
901-
902-
Unless otherwise specified, if no specific hue interpolation algorithm is selected by the host syntax, the default is ''shorter''.
903-
904-
If one of the angles has the value NaN,
905-
then for interpolation, NaN is replaced
906-
by the value of the other hue angle.
907-
If both angles have the value NaN,
908-
then for interpolation, NaN is replaced
909-
by the value 0 for both angles.
910749

911-
Issue(5277): How do these work when interpolating between multiple colors?
912750

913751
Security and Privacy Considerations {#SecPriv}
914752
===================================

0 commit comments

Comments
 (0)