Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
2026-04-15 09:32:06 +08:00
15 changed files with 286 additions and 102 deletions
+2 -2
View File
@@ -289,7 +289,7 @@ nsLocaleService::GetLocaleFromAcceptLanguage(const char *acceptLanguage, nsILoca
PR_sscanf(cPtr1,";q=%f",&qvalue[countLang]);
*cPtr1 = '\0';
}
if (strlen(cPtr)<NSILOCALE_MAX_ACCEPT_LANGUAGE) { /* ignore if too long */
if (strlen(cPtr)<NSILOCALE_MAX_ACCEPT_LENGTH) { /* ignore if too long */
qvalue[countLang] -= (bias += 0.0001f); /* to insure original order */
ptrLanguage[countLang++] = cPtr;
if (countLang>=NSILOCALE_MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
@@ -321,8 +321,8 @@ nsLocaleService::GetLocaleFromAcceptLanguage(const char *acceptLanguage, nsILoca
cPtr = nsCRT::strtok(input.get(),",",&cPtr2);
while (cPtr) {
if (strlen(cPtr)<NSILOCALE_MAX_ACCEPT_LENGTH) { /* ignore if too long */
if (countLang>=NSILOCALE_MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
PL_strncpyz(acceptLanguageList[countLang++],cPtr,NSILOCALE_MAX_ACCEPT_LENGTH);
if (countLang>=NSILOCALE_MAX_ACCEPT_LENGTH) break; /* quit if too many */
}
cPtr = nsCRT::strtok(cPtr2,",",&cPtr2);
}
+32 -11
View File
@@ -104,11 +104,13 @@ class HashMap
//
// Also see the definition of Ptr in HashTable above (with T = Entry).
typedef typename Impl::Ptr Ptr;
Ptr lookup(const Lookup& l) const { return impl.lookup(l); }
MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& l) const { return impl.lookup(l); }
// Like lookup, but does not assert if two threads call lookup at the same
// time. Only use this method when none of the threads will modify the map.
Ptr readonlyThreadsafeLookup(const Lookup& l) const { return impl.readonlyThreadsafeLookup(l); }
MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& l) const {
return impl.readonlyThreadsafeLookup(l);
}
// Assuming |p.found()|, remove |*p|.
void remove(Ptr p) { impl.remove(p); }
@@ -147,7 +149,7 @@ class HashMap
// assert(p->key == 3);
// char val = p->value;
typedef typename Impl::AddPtr AddPtr;
AddPtr lookupForAdd(const Lookup& l) const {
MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& l) const {
return impl.lookupForAdd(l);
}
@@ -198,6 +200,10 @@ class HashMap
// using the finish() method.
void clear() { impl.clear(); }
// Remove all entries. Unlike clear() this method tries to shrink the table.
// Unlike finish() it does not require the map to be initialized again.
void clearAndShrink() { impl.clearAndShrink(); }
// Remove all the entries and release all internal buffers. The map must
// be initialized again before any use.
void finish() { impl.finish(); }
@@ -355,11 +361,13 @@ class HashSet
//
// Also see the definition of Ptr in HashTable above.
typedef typename Impl::Ptr Ptr;
Ptr lookup(const Lookup& l) const { return impl.lookup(l); }
MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& l) const { return impl.lookup(l); }
// Like lookup, but does not assert if two threads call lookup at the same
// time. Only use this method when none of the threads will modify the map.
Ptr readonlyThreadsafeLookup(const Lookup& l) const { return impl.readonlyThreadsafeLookup(l); }
MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& l) const {
return impl.readonlyThreadsafeLookup(l);
}
// Assuming |p.found()|, remove |*p|.
void remove(Ptr p) { impl.remove(p); }
@@ -397,7 +405,9 @@ class HashSet
// Note that relookupOrAdd(p,l,t) performs Lookup using |l| and adds the
// entry |t|, where the caller ensures match(l,t).
typedef typename Impl::AddPtr AddPtr;
AddPtr lookupForAdd(const Lookup& l) const { return impl.lookupForAdd(l); }
MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& l) const {
return impl.lookupForAdd(l);
}
template <typename U>
MOZ_MUST_USE bool add(AddPtr& p, U&& u) {
@@ -437,6 +447,10 @@ class HashSet
// using the finish() method.
void clear() { impl.clear(); }
// Remove all entries. Unlike clear() this method tries to shrink the table.
// Unlike finish() it does not require the set to be initialized again.
void clearAndShrink() { impl.clearAndShrink(); }
// Remove all the entries and release all internal buffers. The set must
// be initialized again before any use.
void finish() { impl.finish(); }
@@ -1383,7 +1397,7 @@ class HashTable : private AllocPolicy
return wouldBeUnderloaded(capacity(), entryCount);
}
static bool match(Entry& e, const Lookup& l)
static MOZ_ALWAYS_INLINE bool match(Entry& e, const Lookup& l)
{
return HashPolicy::match(HashPolicy::getKey(e.get()), l);
}
@@ -1393,7 +1407,8 @@ class HashTable : private AllocPolicy
// (The use of the METER() macro to increment stats violates this
// restriction but we will live with that for now because it's enabled so
// rarely.)
Entry& lookup(const Lookup& l, HashNumber keyHash, unsigned collisionBit) const
MOZ_ALWAYS_INLINE Entry&
lookup(const Lookup& l, HashNumber keyHash, unsigned collisionBit) const
{
MOZ_ASSERT(isLiveHash(keyHash));
MOZ_ASSERT(!(keyHash & sCollisionBit));
@@ -1689,6 +1704,12 @@ class HashTable : private AllocPolicy
#endif
}
void clearAndShrink()
{
clear();
compactIfUnderloaded();
}
void finish()
{
#ifdef JS_DEBUG
@@ -1747,7 +1768,7 @@ class HashTable : private AllocPolicy
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
}
Ptr lookup(const Lookup& l) const
MOZ_ALWAYS_INLINE Ptr lookup(const Lookup& l) const
{
mozilla::ReentrancyGuard g(*this);
if (!HasHash<HashPolicy>(l))
@@ -1756,7 +1777,7 @@ class HashTable : private AllocPolicy
return Ptr(lookup(l, keyHash, 0), *this);
}
Ptr readonlyThreadsafeLookup(const Lookup& l) const
MOZ_ALWAYS_INLINE Ptr readonlyThreadsafeLookup(const Lookup& l) const
{
if (!HasHash<HashPolicy>(l))
return Ptr();
@@ -1764,7 +1785,7 @@ class HashTable : private AllocPolicy
return Ptr(lookup(l, keyHash, 0), *this);
}
AddPtr lookupForAdd(const Lookup& l) const
MOZ_ALWAYS_INLINE AddPtr lookupForAdd(const Lookup& l) const
{
mozilla::ReentrancyGuard g(*this);
if (!EnsureHash<HashPolicy>(l))
+3 -1
View File
@@ -32,6 +32,7 @@ JS::Zone::Zone(JSRuntime* rt)
gcGrayRoots(),
gcWeakKeys(SystemAllocPolicy(), rt->randomHashCodeScrambler()),
typeDescrObjects(this, SystemAllocPolicy()),
atomCache_(),
gcMallocBytes(0),
gcMallocGCTriggered(false),
usage(&rt->gc.usage),
@@ -82,7 +83,8 @@ bool Zone::init(bool isSystemArg)
return uniqueIds_.init() &&
gcZoneGroupEdges.init() &&
gcWeakKeys.init() &&
typeDescrObjects.init();
typeDescrObjects.init() &&
atomCache().init();
}
void
+5 -1
View File
@@ -355,9 +355,13 @@ struct Zone : public JS::shadow::Zone,
js::MovableCellHasher<JSObject*>,
js::SystemAllocPolicy>;
JS::WeakCache<TypeDescrObjectSet> typeDescrObjects;
bool addTypeDescrObject(JSContext* cx, HandleObject obj);
// Set of atoms recently used by this Zone. Purged on GC.
js::AtomSet atomCache_;
js::AtomSet& atomCache() { return atomCache_; }
// Malloc counter to measure memory pressure for GC scheduling. It runs from
// gcMaxMallocBytes down to zero. This counter should be used only when it's
+28 -10
View File
@@ -10,7 +10,9 @@
#include "jsatominlines.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Maybe.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/Unused.h"
#include <string.h>
@@ -63,7 +65,9 @@ const char js_setter_str[] = "setter";
// which create a small number of atoms.
static const uint32_t JS_STRING_HASH_COUNT = 64;
AtomSet::Ptr js::FrozenAtomSet::readonlyThreadsafeLookup(const AtomSet::Lookup& l) const {
MOZ_ALWAYS_INLINE AtomSet::Ptr
js::FrozenAtomSet::readonlyThreadsafeLookup(const AtomSet::Lookup& l) const
{
return mSet->readonlyThreadsafeLookup(l);
}
@@ -283,10 +287,18 @@ static JSAtom*
AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin)
{
if (JSAtom* s = cx->staticStrings().lookup(tbchars, length))
return s;
return s;
AtomHasher::Lookup lookup(tbchars, length);
JS::Zone* zone = cx->zone();
mozilla::Maybe<AtomSet::AddPtr> zonePtr;
if (zone && pin == DoNotPinAtom) {
zonePtr.emplace(zone->atomCache().lookupForAdd(lookup));
if (zonePtr.ref())
return zonePtr.ref()->asPtrUnbarriered();
}
// Note: when this function is called while the permanent atoms table is
// being initialized (in initializeAtoms()), |permanentAtoms| is not yet
// initialized so this lookup is always skipped. Only once
@@ -294,8 +306,12 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, P
// initialized and then this lookup will go ahead.
if (cx->isPermanentAtomsInitialized()) {
AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
if (pp)
return pp->asPtr(cx);
if (pp) {
JSAtom* atom = pp->asPtr(cx);
if (zonePtr)
mozilla::Unused << zone->atomCache().add(zonePtr.ref(), AtomStateEntry(atom, false));
return atom;
}
}
AutoLockForExclusiveAccess lock(cx);
@@ -305,9 +321,14 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, P
if (p) {
JSAtom* atom = p->asPtr(cx);
p->setPinned(bool(pin));
if (zonePtr)
mozilla::Unused << zone->atomCache().add(zonePtr.ref(), AtomStateEntry(atom, false));
return atom;
}
if (!JSString::validateLength(cx, length))
return nullptr;
AutoCompartment ac(cx, cx->atomsCompartment(lock), &lock);
JSFlatString* flat = NewStringCopyN<NoGC>(cx, tbchars, length);
@@ -330,6 +351,9 @@ AtomizeAndCopyChars(ExclusiveContext* cx, const CharT* tbchars, size_t length, P
return nullptr;
}
if (zonePtr)
mozilla::Unused << zone->atomCache().add(zonePtr.ref(), AtomStateEntry(atom, false));
return atom;
}
@@ -382,9 +406,6 @@ js::Atomize(ExclusiveContext* cx, const char* bytes, size_t length, PinningBehav
{
CHECK_REQUEST(cx);
if (!JSString::validateLength(cx, length))
return nullptr;
const Latin1Char* chars = reinterpret_cast<const Latin1Char*>(bytes);
return AtomizeAndCopyChars(cx, chars, length, pin);
}
@@ -395,9 +416,6 @@ js::AtomizeChars(ExclusiveContext* cx, const CharT* chars, size_t length, Pinnin
{
CHECK_REQUEST(cx);
if (!JSString::validateLength(cx, length))
return nullptr;
return AtomizeAndCopyChars(cx, chars, length, pin);
}
+4 -4
View File
@@ -80,12 +80,12 @@ struct AtomHasher
HashNumber hash;
Lookup(const char16_t* chars, size_t length)
MOZ_ALWAYS_INLINE Lookup(const char16_t* chars, size_t length)
: twoByteChars(chars), isLatin1(false), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
}
Lookup(const JS::Latin1Char* chars, size_t length)
MOZ_ALWAYS_INLINE Lookup(const JS::Latin1Char* chars, size_t length)
: latin1Chars(chars), isLatin1(true), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
@@ -94,7 +94,7 @@ struct AtomHasher
};
static HashNumber hash(const Lookup& l) { return l.hash; }
static inline bool match(const AtomStateEntry& entry, const Lookup& lookup);
static MOZ_ALWAYS_INLINE bool match(const AtomStateEntry& entry, const Lookup& lookup);
static void rekey(AtomStateEntry& k, const AtomStateEntry& newKey) { k = newKey; }
};
@@ -113,7 +113,7 @@ public:
~FrozenAtomSet() { js_delete(mSet); }
AtomSet::Ptr readonlyThreadsafeLookup(const AtomSet::Lookup& l) const;
MOZ_ALWAYS_INLINE AtomSet::Ptr readonlyThreadsafeLookup(const AtomSet::Lookup& l) const;
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
return mSet->sizeOfIncludingThis(mallocSizeOf);
+1 -1
View File
@@ -165,7 +165,7 @@ AtomHasher::Lookup::Lookup(const JSAtom* atom)
}
}
inline bool
MOZ_ALWAYS_INLINE bool
AtomHasher::match(const AtomStateEntry& entry, const Lookup& lookup)
{
JSAtom* key = entry.asPtrUnbarriered();
+3
View File
@@ -3419,6 +3419,9 @@ GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
for (GCCompartmentsIter comp(rt); !comp.done(); comp.next())
comp->purge();
for (GCZonesIter zone(rt); !zone.done(); zone.next())
zone->atomCache().clearAndShrink();
freeUnusedLifoBlocksAfterSweeping(&rt->tempLifoAlloc);
rt->interpreterStack().purge(rt);
-9
View File
@@ -350,15 +350,6 @@ js::StaticStrings::getUnitStringForElement(JSContext* cx, JSString* str, size_t
return NewDependentString(cx, str, index, 1);
}
inline JSAtom*
js::StaticStrings::getLength2(char16_t c1, char16_t c2)
{
MOZ_ASSERT(fitsInSmallChar(c1));
MOZ_ASSERT(fitsInSmallChar(c2));
size_t index = (((size_t)toSmallChar[c1]) << 6) + toSmallChar[c2];
return length2StaticTable[index];
}
MOZ_ALWAYS_INLINE void
JSString::finalize(js::FreeOp* fop)
{
+7 -2
View File
@@ -1146,7 +1146,7 @@ class StaticStrings
}
template <typename CharT>
JSAtom* lookup(const CharT* chars, size_t length) {
MOZ_ALWAYS_INLINE JSAtom* lookup(const CharT* chars, size_t length) {
switch (length) {
case 1: {
char16_t c = chars[0];
@@ -1194,7 +1194,12 @@ class StaticStrings
static const SmallChar toSmallChar[];
JSAtom* getLength2(char16_t c1, char16_t c2);
MOZ_ALWAYS_INLINE JSAtom* getLength2(char16_t c1, char16_t c2) {
MOZ_ASSERT(fitsInSmallChar(c1));
MOZ_ASSERT(fitsInSmallChar(c2));
size_t index = (size_t(toSmallChar[c1]) << 6) + toSmallChar[c2];
return length2StaticTable[index];
}
JSAtom* getLength2(uint32_t u) {
MOZ_ASSERT(u < 100);
return getLength2('0' + u / 10, '0' + u % 10);
+154
View File
@@ -0,0 +1,154 @@
/* -*- 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 kLabLightnessMax = 100.0f;
static constexpr float kLchPercentScaleC = 150.0f;
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
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)
{
// 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;
return LinearSRGBToColor(linearR, linearG, linearB, 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);
}
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
#endif /* nsCSSNonSRGBColorSpace_h___ */
+34 -60
View File
@@ -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,
@@ -1289,6 +1239,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,
@@ -7675,6 +7626,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);
@@ -7920,6 +7879,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)
{
@@ -7932,14 +7907,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 +7930,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;
}
@@ -8917,6 +8889,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"))))
@@ -11172,7 +11145,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;
+6 -1
View File
@@ -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)",
@@ -4294,7 +4295,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)",
],
@@ -4319,6 +4321,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%)",
@@ -4353,6 +4356,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)"],
@@ -1111,6 +1111,8 @@ NS_IMETHODIMP
nsExternalHelperAppService::SetProtocolHandlerDefaults(nsIHandlerInfo *aHandlerInfo,
bool aOSHandlerExists)
{
NS_ENSURE_ARG_POINTER(aHandlerInfo);
// this type isn't in our database, so we've only got an OS default handler,
// if one exists