mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 09:57:32 +09:00
Issue #3003 - Add CSS lch() color parsing support
This commit is contained in:
parent
30d4aa00c1
commit
b0d43e27e9
4 changed files with 121 additions and 11 deletions
|
|
@ -15,6 +15,8 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace css {
|
namespace css {
|
||||||
|
|
||||||
|
static constexpr float kLabLightnessMax = 100.0f;
|
||||||
|
static constexpr float kLchPercentScaleC = 150.0f;
|
||||||
static constexpr float kOklabPercentScaleAB = 0.4f;
|
static constexpr float kOklabPercentScaleAB = 0.4f;
|
||||||
static constexpr double kRadiansPerDegree = 0.01745329251994329576923690768489;
|
static constexpr double kRadiansPerDegree = 0.01745329251994329576923690768489;
|
||||||
|
|
||||||
|
|
@ -27,6 +29,21 @@ LinearSRGBToEncoded(float aValue)
|
||||||
return 1.055f * std::pow(aValue, 1.0f / 2.4f) - 0.055f;
|
return 1.055f * std::pow(aValue, 1.0f / 2.4f) - 0.055f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline nscolor
|
||||||
|
LinearSRGBToColor(float aLinearR, float aLinearG, float aLinearB,
|
||||||
|
uint8_t aAlpha)
|
||||||
|
{
|
||||||
|
float r = mozilla::clamped(LinearSRGBToEncoded(aLinearR), 0.0f, 1.0f);
|
||||||
|
float g = mozilla::clamped(LinearSRGBToEncoded(aLinearG), 0.0f, 1.0f);
|
||||||
|
float b = mozilla::clamped(LinearSRGBToEncoded(aLinearB), 0.0f, 1.0f);
|
||||||
|
|
||||||
|
return NS_RGBA(
|
||||||
|
NSToIntRound(r * 255.0f),
|
||||||
|
NSToIntRound(g * 255.0f),
|
||||||
|
NSToIntRound(b * 255.0f),
|
||||||
|
aAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
inline nscolor
|
inline nscolor
|
||||||
OklabToSRGBColor(float aL, float aA, float aB, float aAlpha)
|
OklabToSRGBColor(float aL, float aA, float aB, float aAlpha)
|
||||||
{
|
{
|
||||||
|
|
@ -55,15 +72,7 @@ OklabToSRGBColor(float aL, float aA, float aB, float aAlpha)
|
||||||
float linearG = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s;
|
float linearG = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s;
|
||||||
float linearB = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
|
float linearB = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
|
||||||
|
|
||||||
float r = mozilla::clamped(LinearSRGBToEncoded(linearR), 0.0f, 1.0f);
|
return LinearSRGBToColor(linearR, linearG, linearB, alpha);
|
||||||
float g = mozilla::clamped(LinearSRGBToEncoded(linearG), 0.0f, 1.0f);
|
|
||||||
float b = mozilla::clamped(LinearSRGBToEncoded(linearB), 0.0f, 1.0f);
|
|
||||||
|
|
||||||
return NS_RGBA(
|
|
||||||
NSToIntRound(r * 255.0f),
|
|
||||||
NSToIntRound(g * 255.0f),
|
|
||||||
NSToIntRound(b * 255.0f),
|
|
||||||
alpha);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline nscolor
|
inline nscolor
|
||||||
|
|
@ -75,6 +84,70 @@ OklchToSRGBColor(float aL, float aChroma, float aHue, float aAlpha)
|
||||||
return OklabToSRGBColor(aL, a, b, aAlpha);
|
return OklabToSRGBColor(aL, a, b, aAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline nscolor
|
||||||
|
LabToSRGBColor(float aL, float aA, float aB, float aAlpha)
|
||||||
|
{
|
||||||
|
float lightness = mozilla::clamped(aL, 0.0f, kLabLightnessMax);
|
||||||
|
uint8_t alpha =
|
||||||
|
nsStyleUtil::FloatToColorComponent(mozilla::clamped(aAlpha, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
if (lightness <= 0.0f) {
|
||||||
|
return NS_RGBA(0, 0, 0, alpha);
|
||||||
|
}
|
||||||
|
if (lightness >= kLabLightnessMax) {
|
||||||
|
return NS_RGBA(255, 255, 255, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr float kLabEpsilon = 216.0f / 24389.0f;
|
||||||
|
static constexpr float kLabKappa = 24389.0f / 27.0f;
|
||||||
|
static constexpr float kD50WhitePointX = 0.9642956764295677f;
|
||||||
|
static constexpr float kD50WhitePointZ = 0.8251046025104602f;
|
||||||
|
|
||||||
|
float fy = (lightness + 16.0f) / 116.0f;
|
||||||
|
float fx = aA / 500.0f + fy;
|
||||||
|
float fz = fy - aB / 200.0f;
|
||||||
|
|
||||||
|
float fx3 = fx * fx * fx;
|
||||||
|
float fy3 = fy * fy * fy;
|
||||||
|
float fz3 = fz * fz * fz;
|
||||||
|
|
||||||
|
float x = fx3 > kLabEpsilon ? fx3 : (116.0f * fx - 16.0f) / kLabKappa;
|
||||||
|
float y = lightness > kLabKappa * kLabEpsilon ? fy3 : lightness / kLabKappa;
|
||||||
|
float z = fz3 > kLabEpsilon ? fz3 : (116.0f * fz - 16.0f) / kLabKappa;
|
||||||
|
|
||||||
|
x *= kD50WhitePointX;
|
||||||
|
z *= kD50WhitePointZ;
|
||||||
|
|
||||||
|
float adaptedX = 0.955473421488075f * x - 0.02309845494876471f * y +
|
||||||
|
0.06325924320057072f * z;
|
||||||
|
float adaptedY = -0.0283697093338637f * x + 1.0099953980813041f * y +
|
||||||
|
0.021041441191917323f * z;
|
||||||
|
float adaptedZ = 0.012314014864481998f * x - 0.020507649298898964f * y +
|
||||||
|
1.330365926242124f * z;
|
||||||
|
|
||||||
|
float linearR = (12831.0f / 3959.0f) * adaptedX +
|
||||||
|
(-329.0f / 214.0f) * adaptedY +
|
||||||
|
(-1974.0f / 3959.0f) * adaptedZ;
|
||||||
|
float linearG = (-851781.0f / 878810.0f) * adaptedX +
|
||||||
|
(1648619.0f / 878810.0f) * adaptedY +
|
||||||
|
(36519.0f / 878810.0f) * adaptedZ;
|
||||||
|
float linearB = (705.0f / 12673.0f) * adaptedX +
|
||||||
|
(-2585.0f / 12673.0f) * adaptedY +
|
||||||
|
(705.0f / 667.0f) * adaptedZ;
|
||||||
|
|
||||||
|
return LinearSRGBToColor(linearR, linearG, linearB, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline nscolor
|
||||||
|
LchToSRGBColor(float aL, float aChroma, float aHue, float aAlpha)
|
||||||
|
{
|
||||||
|
float chroma = aChroma < 0.0f ? 0.0f : aChroma;
|
||||||
|
double hueRadians = aHue * kRadiansPerDegree;
|
||||||
|
float a = chroma * std::cos(hueRadians);
|
||||||
|
float b = chroma * std::sin(hueRadians);
|
||||||
|
return LabToSRGBColor(aL, a, b, aAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace css
|
} // namespace css
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1237,6 +1237,7 @@ protected:
|
||||||
ComponentType& aA);
|
ComponentType& aA);
|
||||||
bool ParseHSLColor(float& aHue, float& aSaturation, float& aLightness,
|
bool ParseHSLColor(float& aHue, float& aSaturation, float& aLightness,
|
||||||
float& aOpacity);
|
float& aOpacity);
|
||||||
|
bool ParseLCHColor(nscolor& aColor);
|
||||||
bool ParseOKLabColor(nscolor& aColor);
|
bool ParseOKLabColor(nscolor& aColor);
|
||||||
bool ParseOKLCHColor(nscolor& aColor);
|
bool ParseOKLCHColor(nscolor& aColor);
|
||||||
bool ParseOKLabComponent(float& aComponent, float aPercentScale,
|
bool ParseOKLabComponent(float& aComponent, float aPercentScale,
|
||||||
|
|
@ -7623,6 +7624,14 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
|
||||||
SkipUntil(')');
|
SkipUntil(')');
|
||||||
return CSSParseResult::Error;
|
return CSSParseResult::Error;
|
||||||
}
|
}
|
||||||
|
else if (mToken.mIdent.LowerCaseEqualsLiteral("lch")) {
|
||||||
|
if (ParseLCHColor(rgba)) {
|
||||||
|
aValue.SetColorValue(rgba);
|
||||||
|
return CSSParseResult::Ok;
|
||||||
|
}
|
||||||
|
SkipUntil(')');
|
||||||
|
return CSSParseResult::Error;
|
||||||
|
}
|
||||||
else if (mToken.mIdent.LowerCaseEqualsLiteral("oklab")) {
|
else if (mToken.mIdent.LowerCaseEqualsLiteral("oklab")) {
|
||||||
if (ParseOKLabColor(rgba)) {
|
if (ParseOKLabColor(rgba)) {
|
||||||
aValue.SetColorValue(rgba);
|
aValue.SetColorValue(rgba);
|
||||||
|
|
@ -7868,6 +7877,22 @@ CSSParserImpl::ParseOKLabComponent(float& aComponent, float aPercentScale,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CSSParserImpl::ParseLCHColor(nscolor& aColor)
|
||||||
|
{
|
||||||
|
float l, chroma, hue, alpha;
|
||||||
|
|
||||||
|
if (!ParseOKLabComponent(l, kLabLightnessMax, Nothing()) ||
|
||||||
|
!ParseOKLabComponent(chroma, kLchPercentScaleC, Nothing()) ||
|
||||||
|
!ParseHue(hue) ||
|
||||||
|
!ParseColorOpacityAndCloseParen(alpha, '/')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aColor = LchToSRGBColor(l, chroma, hue, alpha);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CSSParserImpl::ParseOKLabColor(nscolor& aColor)
|
CSSParserImpl::ParseOKLabColor(nscolor& aColor)
|
||||||
{
|
{
|
||||||
|
|
@ -8862,6 +8887,7 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
|
||||||
tk->mIdent.LowerCaseEqualsLiteral("hsl") ||
|
tk->mIdent.LowerCaseEqualsLiteral("hsl") ||
|
||||||
tk->mIdent.LowerCaseEqualsLiteral("rgba") ||
|
tk->mIdent.LowerCaseEqualsLiteral("rgba") ||
|
||||||
tk->mIdent.LowerCaseEqualsLiteral("hsla") ||
|
tk->mIdent.LowerCaseEqualsLiteral("hsla") ||
|
||||||
|
tk->mIdent.LowerCaseEqualsLiteral("lch") ||
|
||||||
tk->mIdent.LowerCaseEqualsLiteral("oklab") ||
|
tk->mIdent.LowerCaseEqualsLiteral("oklab") ||
|
||||||
tk->mIdent.LowerCaseEqualsLiteral("oklch") ||
|
tk->mIdent.LowerCaseEqualsLiteral("oklch") ||
|
||||||
tk->mIdent.LowerCaseEqualsLiteral("color-mix"))))
|
tk->mIdent.LowerCaseEqualsLiteral("color-mix"))))
|
||||||
|
|
@ -11117,7 +11143,8 @@ CSSParserImpl::ParseGradientInterpolationMethod()
|
||||||
mToken.mIdent.LowerCaseEqualsLiteral("oklab")) {
|
mToken.mIdent.LowerCaseEqualsLiteral("oklab")) {
|
||||||
isPolarColorSpace = false;
|
isPolarColorSpace = false;
|
||||||
} else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl") ||
|
} else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl") ||
|
||||||
mToken.mIdent.LowerCaseEqualsLiteral("oklch")) {
|
mToken.mIdent.LowerCaseEqualsLiteral("oklch") ||
|
||||||
|
mToken.mIdent.LowerCaseEqualsLiteral("lch")) {
|
||||||
isPolarColorSpace = true;
|
isPolarColorSpace = true;
|
||||||
} else {
|
} else {
|
||||||
return CSSParseResult::Error;
|
return CSSParseResult::Error;
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,7 @@ var validGradientAndElementValues = [
|
||||||
"linear-gradient(.414rad, red, blue)",
|
"linear-gradient(.414rad, red, blue)",
|
||||||
"linear-gradient(90deg in srgb, yellow, purple)",
|
"linear-gradient(90deg in srgb, yellow, purple)",
|
||||||
"linear-gradient(90deg in hsl, yellow, purple)",
|
"linear-gradient(90deg in hsl, yellow, purple)",
|
||||||
|
"linear-gradient(90deg in lch, yellow, purple)",
|
||||||
"linear-gradient(90deg in oklch, yellow, purple)",
|
"linear-gradient(90deg in oklch, yellow, purple)",
|
||||||
"linear-gradient(in oklab, yellow, purple)",
|
"linear-gradient(in oklab, yellow, purple)",
|
||||||
|
|
||||||
|
|
@ -4302,7 +4303,8 @@ var gCSSProperties = {
|
||||||
"hsl(0rad, 0%, 0%)",
|
"hsl(0rad, 0%, 0%)",
|
||||||
"hsl(0turn, 0%, 0%)",
|
"hsl(0turn, 0%, 0%)",
|
||||||
"hsl(1turn, 0%, 0%)",
|
"hsl(1turn, 0%, 0%)",
|
||||||
/* oklab() and oklch(). */
|
/* lch(), oklab(), and oklch(). */
|
||||||
|
"lch(0 0 0)",
|
||||||
"oklab(0 0 0)",
|
"oklab(0 0 0)",
|
||||||
"oklch(0 0 0)",
|
"oklch(0 0 0)",
|
||||||
],
|
],
|
||||||
|
|
@ -4327,6 +4329,7 @@ var gCSSProperties = {
|
||||||
"hsl(0.5grad 400% 500% / 9.0)",
|
"hsl(0.5grad 400% 500% / 9.0)",
|
||||||
"hsl(33rad 100% 90% / 4)",
|
"hsl(33rad 100% 90% / 4)",
|
||||||
"hsl(0.33turn, 40%, 40%, 10%)",
|
"hsl(0.33turn, 40%, 40%, 10%)",
|
||||||
|
"lch(70% 50 180deg / 40%)",
|
||||||
"oklab(100% 0 0)",
|
"oklab(100% 0 0)",
|
||||||
"oklab(60% 0.1 -0.1 / 75%)",
|
"oklab(60% 0.1 -0.1 / 75%)",
|
||||||
"oklch(70% 0.2 180deg / 40%)",
|
"oklch(70% 0.2 180deg / 40%)",
|
||||||
|
|
@ -4361,6 +4364,8 @@ var gCSSProperties = {
|
||||||
"rgb(0, 0, 0 /)",
|
"rgb(0, 0, 0 /)",
|
||||||
"hsl(0 0% 0% /)",
|
"hsl(0 0% 0% /)",
|
||||||
"hsl(0, 0%, 0% /)",
|
"hsl(0, 0%, 0% /)",
|
||||||
|
"lch(0, 0 0)",
|
||||||
|
"lch(0 0 / 1)",
|
||||||
"oklab(0, 0 0)",
|
"oklab(0, 0 0)",
|
||||||
"oklab(0 0 / 1)",
|
"oklab(0 0 / 1)",
|
||||||
"oklch(0, 0 0)",
|
"oklch(0, 0 0)",
|
||||||
|
|
|
||||||
|
|
@ -399,6 +399,11 @@ var noframe_container = document.getElementById("content");
|
||||||
["hsla(0deg 0% 0% / 0.5)", "rgba(0, 0, 0, 0.5)"],
|
["hsla(0deg 0% 0% / 0.5)", "rgba(0, 0, 0, 0.5)"],
|
||||||
["hsl(0 0% 0% / 1)", "rgb(0, 0, 0)"],
|
["hsl(0 0% 0% / 1)", "rgb(0, 0, 0)"],
|
||||||
["hsl(0 0% 0% / 0.5)", "rgba(0, 0, 0, 0.5)"],
|
["hsl(0 0% 0% / 0.5)", "rgba(0, 0, 0, 0.5)"],
|
||||||
|
["lch(0 0 0 / 1)", "rgb(0, 0, 0)"],
|
||||||
|
["lch(100% 0 0 / 0.5)", "rgba(255, 255, 255, 0.5)"],
|
||||||
|
["lch(52.2345% 72.2 56.2 / 1)", "rgb(198, 93, 6)"],
|
||||||
|
["lch(29.69% 45.553% 327.1 / 1)", "rgb(129, 0, 129)"],
|
||||||
|
["lch(150% 50 60 / 1)", "rgb(255, 255, 255)"],
|
||||||
["oklab(0 0 0 / 1)", "rgb(0, 0, 0)"],
|
["oklab(0 0 0 / 1)", "rgb(0, 0, 0)"],
|
||||||
["oklab(0 0 0 / 0.5)", "rgba(0, 0, 0, 0.5)"],
|
["oklab(0 0 0 / 0.5)", "rgba(0, 0, 0, 0.5)"],
|
||||||
["oklab(150% 0.5 0.2 / 1)", "rgb(255, 0, 0)"],
|
["oklab(150% 0.5 0.2 / 1)", "rgb(255, 0, 0)"],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue