mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 13:58:49 +00:00
Issue #3003 prerequisite - Split non-sRGB CSS color helpers out of nsCSSParser
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsCSSNonSRGBColorSpace_h___
|
||||
#define nsCSSNonSRGBColorSpace_h___
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsStyleUtil.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
static constexpr float kOklabPercentScaleAB = 0.4f;
|
||||
static constexpr double kRadiansPerDegree = 0.01745329251994329576923690768489;
|
||||
|
||||
inline float
|
||||
LinearSRGBToEncoded(float aValue)
|
||||
{
|
||||
if (aValue <= 0.0031308f) {
|
||||
return 12.92f * aValue;
|
||||
}
|
||||
return 1.055f * std::pow(aValue, 1.0f / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
inline nscolor
|
||||
OklabToSRGBColor(float aL, float aA, float aB, float aAlpha)
|
||||
{
|
||||
// Per CSS Color, the lightness component for Oklab/Oklch is clamped.
|
||||
float lightness = mozilla::clamped(aL, 0.0f, 1.0f);
|
||||
uint8_t alpha =
|
||||
nsStyleUtil::FloatToColorComponent(mozilla::clamped(aAlpha, 0.0f, 1.0f));
|
||||
|
||||
// Treat values extremely close to zero as zero to avoid tiny floating-point
|
||||
// representation differences for percentage inputs.
|
||||
static constexpr float kLightnessEndpointEpsilon = 0.000002f;
|
||||
|
||||
if (lightness <= kLightnessEndpointEpsilon) {
|
||||
return NS_RGBA(0, 0, 0, alpha);
|
||||
}
|
||||
|
||||
float lRoot = lightness + 0.3963377774f * aA + 0.2158037573f * aB;
|
||||
float mRoot = lightness - 0.1055613458f * aA - 0.0638541728f * aB;
|
||||
float sRoot = lightness - 0.0894841775f * aA - 1.2914855480f * aB;
|
||||
|
||||
float l = lRoot * lRoot * lRoot;
|
||||
float m = mRoot * mRoot * mRoot;
|
||||
float s = sRoot * sRoot * sRoot;
|
||||
|
||||
float linearR = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s;
|
||||
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);
|
||||
}
|
||||
|
||||
inline nscolor
|
||||
OklchToSRGBColor(float aL, float aChroma, float aHue, float aAlpha)
|
||||
{
|
||||
double hueRadians = aHue * kRadiansPerDegree;
|
||||
float a = aChroma * std::cos(hueRadians);
|
||||
float b = aChroma * std::sin(hueRadians);
|
||||
return OklabToSRGBColor(aL, a, b, aAlpha);
|
||||
}
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* nsCSSNonSRGBColorSpace_h___ */
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "nsCSSParser.h"
|
||||
#include "CSSNestingFlattener.h"
|
||||
#include "nsAlgorithm.h"
|
||||
#include "nsCSSNonSRGBColorSpace.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsCSSKeywords.h"
|
||||
#include "nsCSSScanner.h"
|
||||
@@ -169,57 +170,6 @@ struct ReducePercentageCalcOps : ReduceNumberCalcOps
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr float kOKLabPercentScaleAB = 0.4f;
|
||||
static constexpr double kRadiansPerDegree = 0.01745329251994329576923690768489;
|
||||
|
||||
static inline float
|
||||
LinearSRGBToEncoded(float aValue)
|
||||
{
|
||||
if (aValue <= 0.0031308f) {
|
||||
return 12.92f * aValue;
|
||||
}
|
||||
return 1.055f * std::pow(aValue, 1.0f / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
static nscolor
|
||||
OKLabToSRGBColor(float aL, float aA, float aB, float aAlpha)
|
||||
{
|
||||
// Per CSS Color, the lightness component for Oklab/Oklch is clamped.
|
||||
float lightness = mozilla::clamped(aL, 0.0f, 1.0f);
|
||||
uint8_t alpha =
|
||||
nsStyleUtil::FloatToColorComponent(mozilla::clamped(aAlpha, 0.0f, 1.0f));
|
||||
|
||||
// Treat values extremely close to zero as zero to avoid tiny floating-point
|
||||
// representation differences for percentage inputs.
|
||||
static constexpr float kLightnessEndpointEpsilon = 0.000002f;
|
||||
|
||||
if (lightness <= kLightnessEndpointEpsilon) {
|
||||
return NS_RGBA(0, 0, 0, alpha);
|
||||
}
|
||||
|
||||
float lRoot = lightness + 0.3963377774f * aA + 0.2158037573f * aB;
|
||||
float mRoot = lightness - 0.1055613458f * aA - 0.0638541728f * aB;
|
||||
float sRoot = lightness - 0.0894841775f * aA - 1.2914855480f * aB;
|
||||
|
||||
float l = lRoot * lRoot * lRoot;
|
||||
float m = mRoot * mRoot * mRoot;
|
||||
float s = sRoot * sRoot * sRoot;
|
||||
|
||||
float linearR = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s;
|
||||
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);
|
||||
}
|
||||
|
||||
static_assert(css::eAuthorSheetFeatures == 0 &&
|
||||
css::eUserSheetFeatures == 1 &&
|
||||
css::eAgentSheetFeatures == 2,
|
||||
@@ -7932,14 +7882,14 @@ CSSParserImpl::ParseOKLabColor(nscolor& aColor)
|
||||
|
||||
bool hasComma = ExpectSymbol(commaSeparator, true);
|
||||
const char separatorBeforeAlpha = hasComma ? commaSeparator : '/';
|
||||
if (!ParseOKLabComponent(a, kOKLabPercentScaleAB,
|
||||
if (!ParseOKLabComponent(a, kOklabPercentScaleAB,
|
||||
hasComma ? Some(commaSeparator) : Nothing()) ||
|
||||
!ParseOKLabComponent(b, kOKLabPercentScaleAB, Nothing()) ||
|
||||
!ParseOKLabComponent(b, kOklabPercentScaleAB, Nothing()) ||
|
||||
!ParseColorOpacityAndCloseParen(alpha, separatorBeforeAlpha)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aColor = OKLabToSRGBColor(l, a, b, alpha);
|
||||
aColor = OklabToSRGBColor(l, a, b, alpha);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7955,17 +7905,14 @@ CSSParserImpl::ParseOKLCHColor(nscolor& aColor)
|
||||
|
||||
bool hasComma = ExpectSymbol(commaSeparator, true);
|
||||
const char separatorBeforeAlpha = hasComma ? commaSeparator : '/';
|
||||
if (!ParseOKLabComponent(chroma, kOKLabPercentScaleAB,
|
||||
if (!ParseOKLabComponent(chroma, kOklabPercentScaleAB,
|
||||
hasComma ? Some(commaSeparator) : Nothing()) ||
|
||||
!ParseHue(hue) ||
|
||||
!ParseColorOpacityAndCloseParen(alpha, separatorBeforeAlpha)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double hueRadians = hue * kRadiansPerDegree;
|
||||
float a = chroma * std::cos(hueRadians);
|
||||
float b = chroma * std::sin(hueRadians);
|
||||
aColor = OKLabToSRGBColor(l, a, b, alpha);
|
||||
aColor = OklchToSRGBColor(l, chroma, hue, alpha);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user