mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 18:07:31 +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 css {
|
||||
|
||||
static constexpr float kLabLightnessMax = 100.0f;
|
||||
static constexpr float kLchPercentScaleC = 150.0f;
|
||||
static constexpr float kOklabPercentScaleAB = 0.4f;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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 linearB = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s;
|
||||
|
||||
float r = mozilla::clamped(LinearSRGBToEncoded(linearR), 0.0f, 1.0f);
|
||||
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);
|
||||
return LinearSRGBToColor(linearR, linearG, linearB, alpha);
|
||||
}
|
||||
|
||||
inline nscolor
|
||||
|
|
@ -75,6 +84,70 @@ OklchToSRGBColor(float aL, float aChroma, float aHue, float 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 mozilla
|
||||
|
||||
|
|
|
|||
|
|
@ -1237,6 +1237,7 @@ protected:
|
|||
ComponentType& aA);
|
||||
bool ParseHSLColor(float& aHue, float& aSaturation, float& aLightness,
|
||||
float& aOpacity);
|
||||
bool ParseLCHColor(nscolor& aColor);
|
||||
bool ParseOKLabColor(nscolor& aColor);
|
||||
bool ParseOKLCHColor(nscolor& aColor);
|
||||
bool ParseOKLabComponent(float& aComponent, float aPercentScale,
|
||||
|
|
@ -7623,6 +7624,14 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
|
|||
SkipUntil(')');
|
||||
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")) {
|
||||
if (ParseOKLabColor(rgba)) {
|
||||
aValue.SetColorValue(rgba);
|
||||
|
|
@ -7868,6 +7877,22 @@ CSSParserImpl::ParseOKLabComponent(float& aComponent, float aPercentScale,
|
|||
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
|
||||
CSSParserImpl::ParseOKLabColor(nscolor& aColor)
|
||||
{
|
||||
|
|
@ -8862,6 +8887,7 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
|
|||
tk->mIdent.LowerCaseEqualsLiteral("hsl") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("rgba") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("hsla") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("lch") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("oklab") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("oklch") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("color-mix"))))
|
||||
|
|
@ -11117,7 +11143,8 @@ CSSParserImpl::ParseGradientInterpolationMethod()
|
|||
mToken.mIdent.LowerCaseEqualsLiteral("oklab")) {
|
||||
isPolarColorSpace = false;
|
||||
} else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl") ||
|
||||
mToken.mIdent.LowerCaseEqualsLiteral("oklch")) {
|
||||
mToken.mIdent.LowerCaseEqualsLiteral("oklch") ||
|
||||
mToken.mIdent.LowerCaseEqualsLiteral("lch")) {
|
||||
isPolarColorSpace = true;
|
||||
} else {
|
||||
return CSSParseResult::Error;
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ var validGradientAndElementValues = [
|
|||
"linear-gradient(.414rad, red, blue)",
|
||||
"linear-gradient(90deg in srgb, 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(in oklab, yellow, purple)",
|
||||
|
||||
|
|
@ -4302,7 +4303,8 @@ var gCSSProperties = {
|
|||
"hsl(0rad, 0%, 0%)",
|
||||
"hsl(0turn, 0%, 0%)",
|
||||
"hsl(1turn, 0%, 0%)",
|
||||
/* oklab() and oklch(). */
|
||||
/* lch(), oklab(), and oklch(). */
|
||||
"lch(0 0 0)",
|
||||
"oklab(0 0 0)",
|
||||
"oklch(0 0 0)",
|
||||
],
|
||||
|
|
@ -4327,6 +4329,7 @@ var gCSSProperties = {
|
|||
"hsl(0.5grad 400% 500% / 9.0)",
|
||||
"hsl(33rad 100% 90% / 4)",
|
||||
"hsl(0.33turn, 40%, 40%, 10%)",
|
||||
"lch(70% 50 180deg / 40%)",
|
||||
"oklab(100% 0 0)",
|
||||
"oklab(60% 0.1 -0.1 / 75%)",
|
||||
"oklch(70% 0.2 180deg / 40%)",
|
||||
|
|
@ -4361,6 +4364,8 @@ var gCSSProperties = {
|
|||
"rgb(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 / 1)",
|
||||
"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)"],
|
||||
["hsl(0 0% 0% / 1)", "rgb(0, 0, 0)"],
|
||||
["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 / 0.5)", "rgba(0, 0, 0, 0.5)"],
|
||||
["oklab(150% 0.5 0.2 / 1)", "rgb(255, 0, 0)"],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue