mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 05:38:39 +00:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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___ */
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user