mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 11:57:32 +09:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
commit
4c1a4a4402
31 changed files with 827 additions and 36 deletions
|
|
@ -1270,6 +1270,12 @@ ComputeSelectorStateDependence(nsCSSSelector& aSelector)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (pseudoClass->mType == CSSPseudoClassType::autofill ||
|
||||
pseudoClass->mType == CSSPseudoClassType::mozAutofillHighlight) {
|
||||
states |= NS_EVENT_STATE_AUTOFILL;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto idx = static_cast<CSSPseudoClassTypeBase>(pseudoClass->mType);
|
||||
states |= nsCSSPseudoClasses::sPseudoClassStateDependences[idx];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ CSS_KEY(collapse, collapse)
|
|||
CSS_KEY(color, color)
|
||||
CSS_KEY(color-burn, color_burn)
|
||||
CSS_KEY(color-dodge, color_dodge)
|
||||
CSS_KEY(color-mix, color_mix)
|
||||
CSS_KEY(common-ligatures, common_ligatures)
|
||||
CSS_KEY(column, column)
|
||||
CSS_KEY(column-reverse, column_reverse)
|
||||
|
|
@ -313,6 +314,7 @@ CSS_KEY(horizontal, horizontal)
|
|||
CSS_KEY(horizontal-tb, horizontal_tb)
|
||||
CSS_KEY(hue, hue)
|
||||
CSS_KEY(hue-rotate, hue_rotate)
|
||||
CSS_KEY(hsl, hsl)
|
||||
CSS_KEY(hz, hz)
|
||||
CSS_KEY(icon, icon)
|
||||
CSS_KEY(ignore, ignore)
|
||||
|
|
|
|||
|
|
@ -7444,6 +7444,110 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue)
|
|||
}
|
||||
break;
|
||||
case eCSSToken_Function: {
|
||||
// check for color-mix function
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("color-mix")) {
|
||||
// parse color-mix function
|
||||
if (!GetToken(true)) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
if (mToken.mType != eCSSToken_Ident || !mToken.mIdent.LowerCaseEqualsLiteral("in")) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
// Check for supported color spaces: srgb or hsl
|
||||
if (!GetToken(true) || mToken.mType != eCSSToken_Ident) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
mozilla::css::ColorMixColorSpace colorSpace;
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("srgb")) {
|
||||
colorSpace = mozilla::css::ColorMixColorSpace::sRGB;
|
||||
} else if (mToken.mIdent.LowerCaseEqualsLiteral("hsl")) {
|
||||
colorSpace = mozilla::css::ColorMixColorSpace::HSL;
|
||||
} else {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
if (!ExpectSymbol(',', true)) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
nsCSSValue color1;
|
||||
if (ParseColor(color1) != CSSParseResult::Ok) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
// parse optional weight for first color
|
||||
bool w1_specified = false;
|
||||
float w1 = 0.5f; // Default to 50%
|
||||
if (GetToken(true)) {
|
||||
if (mToken.mType == eCSSToken_Percentage) {
|
||||
w1 = mToken.mNumber; // percentage tokens are already normalized (0.0-1.0)
|
||||
w1_specified = true;
|
||||
// Reject invalid percentages (outside 0-100% range)
|
||||
if (w1 < 0.0f || w1 > 1.0f) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
} else {
|
||||
UngetToken();
|
||||
}
|
||||
}
|
||||
|
||||
if (!ExpectSymbol(',', true)) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
nsCSSValue color2;
|
||||
if (ParseColor(color2) != CSSParseResult::Ok) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
// parse optional weight for second color
|
||||
bool w2_specified = false;
|
||||
float w2 = 0.5f; // default to 50%
|
||||
if (GetToken(true)) {
|
||||
if (mToken.mType == eCSSToken_Percentage) {
|
||||
w2 = mToken.mNumber; // percentage tokens are already normalized (0.0-1.0)
|
||||
w2_specified = true;
|
||||
// Reject invalid percentages (outside 0-100% range)
|
||||
if (w2 < 0.0f || w2 > 1.0f) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
} else {
|
||||
UngetToken();
|
||||
}
|
||||
}
|
||||
|
||||
if (w1_specified && !w2_specified) {
|
||||
// first specified, second should be complement
|
||||
w2 = 1.0f - w1;
|
||||
} else if (!w1_specified && w2_specified) {
|
||||
// second specified, first should be complement
|
||||
w1 = 1.0f - w2;
|
||||
}
|
||||
|
||||
if (!ExpectSymbol(')', true)) {
|
||||
SkipUntil(')');
|
||||
return CSSParseResult::Error;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::css::ColorMixValue> colorMix = new mozilla::css::ColorMixValue(
|
||||
colorSpace, color1, color2, w1, w2);
|
||||
aValue.SetColorMixValue(colorMix.forget());
|
||||
return CSSParseResult::Ok;
|
||||
}
|
||||
|
||||
bool isRGB;
|
||||
bool isHSL;
|
||||
if ((isRGB = mToken.mIdent.LowerCaseEqualsLiteral("rgb")) ||
|
||||
|
|
@ -8650,7 +8754,8 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
|
|||
(tk->mIdent.LowerCaseEqualsLiteral("rgb") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("hsl") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("rgba") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("hsla"))))
|
||||
tk->mIdent.LowerCaseEqualsLiteral("hsla") ||
|
||||
tk->mIdent.LowerCaseEqualsLiteral("color-mix"))))
|
||||
{
|
||||
// Put token back so that parse color can get it
|
||||
UngetToken();
|
||||
|
|
|
|||
|
|
@ -194,6 +194,9 @@ CSS_STATE_PSEUDO_CLASS(mozFullScreen, ":-moz-full-screen", 0, "", NS_EVENT_STATE
|
|||
CSS_STATE_PSEUDO_CLASS(modal, ":modal", 0, "", NS_EVENT_STATE_MODAL_DIALOG)
|
||||
CSS_STATE_PSEUDO_CLASS(mozModalDialog, ":-moz-modal-dialog", 0, "", NS_EVENT_STATE_MODAL_DIALOG)
|
||||
|
||||
// Matches autofilled input elements
|
||||
CSS_STATE_PSEUDO_CLASS(autofill, ":autofill", 0, "", NS_EVENT_STATE_AUTOFILL)
|
||||
|
||||
// Matches if the element is focused and should show a focus ring
|
||||
CSS_STATE_PSEUDO_CLASS(mozFocusRing, ":-moz-focusring", 0, "", NS_EVENT_STATE_FOCUSRING)
|
||||
|
||||
|
|
@ -274,6 +277,9 @@ CSS_STATE_PSEUDO_CLASS(mozMeterSubSubOptimum, ":-moz-meter-sub-sub-optimum", 0,
|
|||
// Those values should be parsed but do nothing.
|
||||
CSS_STATE_PSEUDO_CLASS(mozPlaceholder, ":-moz-placeholder", 0, "", NS_EVENT_STATE_IGNORE)
|
||||
|
||||
// Internal-only pseudo-class for autofill highlight
|
||||
CSS_STATE_PSEUDO_CLASS(mozAutofillHighlight, ":-moz-autofill-highlight", CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "", NS_EVENT_STATE_AUTOFILL)
|
||||
|
||||
#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||
#undef DEFINED_CSS_STATE_PSEUDO_CLASS
|
||||
#undef CSS_STATE_PSEUDO_CLASS
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "PLDHashTable.h"
|
||||
#include "nsICSSPseudoComparator.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/css/ImportRule.h"
|
||||
#include "mozilla/css/StyleRule.h"
|
||||
#include "mozilla/css/GroupRule.h"
|
||||
#include "nsIDocument.h"
|
||||
|
|
@ -649,6 +650,12 @@ CascadeRuleEnumFunc(css::Rule* aRule, void* aData)
|
|||
if (!layer->mData->mCounterStyleRules.AppendElement(counterStyleRule)) {
|
||||
return false;
|
||||
}
|
||||
} else if (css::Rule::IMPORT_RULE == type &&
|
||||
nsCSSRuleUtils::LoadImportedSheetsInOrderEnabled()) {
|
||||
css::ImportRule* importRule = static_cast<css::ImportRule*>(aRule);
|
||||
nsCSSRuleProcessor::CascadeSheet(
|
||||
importRule->GetStyleSheet()->AsConcrete(),
|
||||
layer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -660,10 +667,12 @@ nsCSSRuleProcessor::CascadeSheet(CSSStyleSheet* aSheet, CascadeLayer* aLayer)
|
|||
aSheet->UseForPresentation(aLayer->mPresContext,
|
||||
aLayer->mCacheKey) &&
|
||||
aSheet->mInner) {
|
||||
CSSStyleSheet* child = aSheet->mInner->mFirstChild;
|
||||
while (child) {
|
||||
CascadeSheet(child, aLayer);
|
||||
child = child->mNext;
|
||||
if (!nsCSSRuleUtils::LoadImportedSheetsInOrderEnabled()) {
|
||||
CSSStyleSheet* child = aSheet->mInner->mFirstChild;
|
||||
while (child) {
|
||||
CascadeSheet(child, aLayer);
|
||||
child = child->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aSheet->mInner->mOrderedRules.EnumerateForwards(CascadeRuleEnumFunc,
|
||||
|
|
|
|||
|
|
@ -154,13 +154,13 @@ public:
|
|||
bool IsInRuleProcessorCache() const { return mInRuleProcessorCache; }
|
||||
bool IsUsedByMultipleStyleSets() const { return mStyleSetRefCnt > 1; }
|
||||
|
||||
static bool CascadeSheet(mozilla::CSSStyleSheet* aSheet,
|
||||
CascadeLayer* aLayer);
|
||||
|
||||
protected:
|
||||
virtual ~nsCSSRuleProcessor();
|
||||
|
||||
private:
|
||||
static bool CascadeSheet(mozilla::CSSStyleSheet* aSheet,
|
||||
CascadeLayer* aLayer);
|
||||
|
||||
RuleProcessorGroup* GetGroup(nsPresContext* aPresContext);
|
||||
void RefreshGroup(nsPresContext* aPresContext);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ using namespace mozilla::dom;
|
|||
#define VISITED_PSEUDO_PREF "layout.css.visited_links_enabled"
|
||||
|
||||
static bool gSupportVisitedPseudo = true;
|
||||
static bool gLoadImportedSheetsInOrder = true;
|
||||
|
||||
static nsTArray<nsCOMPtr<nsIAtom>>* sSystemMetrics = 0;
|
||||
|
||||
|
|
@ -31,6 +32,9 @@ nsCSSRuleUtils::Startup()
|
|||
{
|
||||
Preferences::AddBoolVarCache(
|
||||
&gSupportVisitedPseudo, VISITED_PSEUDO_PREF, true);
|
||||
Preferences::AddBoolVarCache(&gLoadImportedSheetsInOrder,
|
||||
"layout.css.load-imported-sheets-in-order",
|
||||
true);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -206,6 +210,12 @@ nsCSSRuleUtils::HasSystemMetric(nsIAtom* aMetric)
|
|||
return sSystemMetrics->IndexOf(aMetric) != sSystemMetrics->NoIndex;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsCSSRuleUtils::LoadImportedSheetsInOrderEnabled()
|
||||
{
|
||||
return gLoadImportedSheetsInOrder;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
/* static */ uint8_t
|
||||
nsCSSRuleUtils::GetWindowsThemeIdentifier()
|
||||
|
|
@ -566,6 +576,14 @@ nsCSSRuleUtils::StateSelectorMatches(Element* aElement,
|
|||
for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList;
|
||||
pseudoClass;
|
||||
pseudoClass = pseudoClass->mNext) {
|
||||
if (pseudoClass->mType == CSSPseudoClassType::autofill ||
|
||||
pseudoClass->mType == CSSPseudoClassType::mozAutofillHighlight) {
|
||||
// Match if the element has the autofill state, regardless of focus
|
||||
if (!aElement->State().HasState(NS_EVENT_STATE_AUTOFILL)) {
|
||||
return false;
|
||||
}
|
||||
continue; // This pseudo-class matches
|
||||
}
|
||||
auto idx = static_cast<CSSPseudoClassTypeBase>(pseudoClass->mType);
|
||||
EventStates statesToCheck = nsCSSPseudoClasses::sPseudoClassStates[idx];
|
||||
if (!statesToCheck.IsEmpty() && !StateSelectorMatches(aElement,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ struct nsCSSRuleUtils
|
|||
static void FreeSystemMetrics();
|
||||
static bool HasSystemMetric(nsIAtom* aMetric);
|
||||
|
||||
static bool LoadImportedSheetsInOrderEnabled();
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Cached theme identifier for the moz-windows-theme media query.
|
||||
static uint8_t GetWindowsThemeIdentifier();
|
||||
|
|
|
|||
|
|
@ -166,6 +166,10 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
|||
mValue.mComplexColor = aCopy.mValue.mComplexColor;
|
||||
mValue.mComplexColor->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_ColorMix == mUnit) {
|
||||
mValue.mColorMix = aCopy.mValue.mColorMix;
|
||||
mValue.mColorMix->AddRef();
|
||||
}
|
||||
else if (eCSSUnit_Revert == mUnit) {
|
||||
mValue.mCascadeOrigin = aCopy.mValue.mCascadeOrigin;
|
||||
}
|
||||
|
|
@ -282,6 +286,14 @@ bool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
|||
else if (eCSSUnit_ComplexColor == mUnit) {
|
||||
return *mValue.mComplexColor == *aOther.mValue.mComplexColor;
|
||||
}
|
||||
else if (eCSSUnit_ColorMix == mUnit) {
|
||||
return mValue.mColorMix == aOther.mValue.mColorMix ||
|
||||
(mValue.mColorMix->mColorSpace == aOther.mValue.mColorMix->mColorSpace &&
|
||||
mValue.mColorMix->mColor1 == aOther.mValue.mColorMix->mColor1 &&
|
||||
mValue.mColorMix->mColor2 == aOther.mValue.mColorMix->mColor2 &&
|
||||
mValue.mColorMix->mWeight1 == aOther.mValue.mColorMix->mWeight1 &&
|
||||
mValue.mColorMix->mWeight2 == aOther.mValue.mColorMix->mWeight2);
|
||||
}
|
||||
else if (eCSSUnit_Revert == mUnit) {
|
||||
return mValue.mCascadeOrigin == aOther.mValue.mCascadeOrigin;
|
||||
}
|
||||
|
|
@ -421,6 +433,8 @@ void nsCSSValue::DoReset()
|
|||
mValue.mFloatColor->Release();
|
||||
} else if (eCSSUnit_ComplexColor == mUnit) {
|
||||
mValue.mComplexColor->Release();
|
||||
} else if (eCSSUnit_ColorMix == mUnit) {
|
||||
mValue.mColorMix->Release();
|
||||
} else if (UnitHasArrayValue()) {
|
||||
mValue.mArray->Release();
|
||||
} else if (eCSSUnit_URL == mUnit) {
|
||||
|
|
@ -545,6 +559,14 @@ nsCSSValue::SetComplexColorValue(already_AddRefed<ComplexColorValue> aValue)
|
|||
mValue.mComplexColor = aValue.take();
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSValue::SetColorMixValue(already_AddRefed<ColorMixValue> aValue)
|
||||
{
|
||||
Reset();
|
||||
mUnit = eCSSUnit_ColorMix;
|
||||
mValue.mColorMix = aValue.take();
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSValue::SetCascadeOriginValue(mozilla::SheetType aValue, nsCSSUnit aUnit)
|
||||
{
|
||||
|
|
@ -1709,6 +1731,28 @@ nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
|
|||
}
|
||||
serializable.AppendToString(aProperty, aResult, aSerialization);
|
||||
}
|
||||
else if (eCSSUnit_ColorMix == unit) {
|
||||
const ColorMixValue* colorMix = GetColorMixValue();
|
||||
aResult.AppendLiteral("color-mix(in ");
|
||||
|
||||
// append color space
|
||||
switch (colorMix->mColorSpace) {
|
||||
case mozilla::css::ColorMixColorSpace::sRGB:
|
||||
aResult.AppendLiteral("srgb");
|
||||
break;
|
||||
case mozilla::css::ColorMixColorSpace::HSL:
|
||||
aResult.AppendLiteral("hsl");
|
||||
break;
|
||||
}
|
||||
|
||||
// append color1 and color2
|
||||
aResult.AppendLiteral(", ");
|
||||
colorMix->mColor1.AppendToString(aProperty, aResult, aSerialization);
|
||||
aResult.AppendLiteral(", ");
|
||||
colorMix->mColor2.AppendToString(aProperty, aResult, aSerialization);
|
||||
|
||||
aResult.Append(')');
|
||||
}
|
||||
else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
|
||||
aResult.AppendLiteral("url(");
|
||||
nsStyleUtil::AppendEscapedCSSString(
|
||||
|
|
@ -2007,6 +2051,7 @@ nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
|
|||
case eCSSUnit_HSLColor: break;
|
||||
case eCSSUnit_HSLAColor: break;
|
||||
case eCSSUnit_ComplexColor: break;
|
||||
case eCSSUnit_ColorMix: break;
|
||||
case eCSSUnit_Percent: aResult.Append(char16_t('%')); break;
|
||||
case eCSSUnit_Number: break;
|
||||
case eCSSUnit_Gradient: break;
|
||||
|
|
@ -2221,6 +2266,11 @@ nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|||
n += mValue.mComplexColor->SizeOfIncludingThis(aMallocSizeOf);
|
||||
break;
|
||||
|
||||
// Color Mix
|
||||
case eCSSUnit_ColorMix:
|
||||
n += mValue.mColorMix->SizeOfIncludingThis(aMallocSizeOf);
|
||||
break;
|
||||
|
||||
// Cascade Origin: nothing extra to measure.
|
||||
case eCSSUnit_Revert:
|
||||
break;
|
||||
|
|
@ -3075,6 +3125,18 @@ css::ComplexColorValue::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
css::ColorMixValue::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
// Only measure it if it's unshared, to avoid double-counting.
|
||||
size_t n = 0;
|
||||
if (mRefCnt <= 1) {
|
||||
n += aMallocSizeOf(this);
|
||||
n += mColor1.SizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mColor2.SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
nsCSSValueGradientStop::nsCSSValueGradientStop()
|
||||
: mLocation(eCSSUnit_None),
|
||||
mColor(eCSSUnit_Null),
|
||||
|
|
|
|||
|
|
@ -521,6 +521,7 @@ enum nsCSSUnit {
|
|||
eCSSUnit_HSLColor = 89, // (nsCSSValueFloatColor*)
|
||||
eCSSUnit_HSLAColor = 90, // (nsCSSValueFloatColor*)
|
||||
eCSSUnit_ComplexColor = 91, // (ComplexColorValue*)
|
||||
eCSSUnit_ColorMix = 92, // (ColorMixValue*)
|
||||
|
||||
eCSSUnit_Percent = 100, // (float) 1.0 == 100%) value is percentage of something
|
||||
eCSSUnit_Number = 101, // (float) value is numeric (usually multiplier, different behavior than percent)
|
||||
|
|
@ -606,6 +607,13 @@ struct nsCSSValueTriplet;
|
|||
struct nsCSSValueTriplet_heap;
|
||||
class nsCSSValueFloatColor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
enum class ColorMixColorSpace;
|
||||
struct ColorMixValue;
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
class nsCSSValue {
|
||||
public:
|
||||
struct Array;
|
||||
|
|
@ -804,6 +812,12 @@ public:
|
|||
MOZ_ASSERT(mUnit == eCSSUnit_ComplexColor);
|
||||
return mValue.mComplexColor->ToComplexColor();
|
||||
}
|
||||
|
||||
mozilla::css::ColorMixValue* GetColorMixValue() const
|
||||
{
|
||||
MOZ_ASSERT(mUnit == eCSSUnit_ColorMix);
|
||||
return mValue.mColorMix;
|
||||
}
|
||||
|
||||
Array* GetArrayValue() const
|
||||
{
|
||||
|
|
@ -950,6 +964,8 @@ public:
|
|||
void SetRGBAColorValue(const mozilla::css::RGBAColorData& aValue);
|
||||
void SetComplexColorValue(
|
||||
already_AddRefed<mozilla::css::ComplexColorValue> aValue);
|
||||
void SetColorMixValue(
|
||||
already_AddRefed<mozilla::css::ColorMixValue> aValue);
|
||||
void SetCascadeOriginValue(mozilla::SheetType aValue, nsCSSUnit aUnit);
|
||||
void SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
|
||||
void SetURLValue(mozilla::css::URLValue* aURI);
|
||||
|
|
@ -1063,6 +1079,7 @@ protected:
|
|||
nsCSSValueFloatColor* MOZ_OWNING_REF mFloatColor;
|
||||
mozilla::css::FontFamilyListRefCnt* MOZ_OWNING_REF mFontFamilyList;
|
||||
mozilla::css::ComplexColorValue* MOZ_OWNING_REF mComplexColor;
|
||||
mozilla::css::ColorMixValue* MOZ_OWNING_REF mColorMix;
|
||||
mozilla::SheetType mCascadeOrigin;
|
||||
} mValue;
|
||||
};
|
||||
|
|
@ -1972,5 +1989,41 @@ protected:
|
|||
static const corner_type corners[4];
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
|
||||
enum class ColorMixColorSpace {
|
||||
sRGB,
|
||||
HSL
|
||||
};
|
||||
|
||||
struct ColorMixValue final
|
||||
{
|
||||
ColorMixColorSpace mColorSpace;
|
||||
nsCSSValue mColor1;
|
||||
nsCSSValue mColor2;
|
||||
float mWeight1;
|
||||
float mWeight2;
|
||||
|
||||
ColorMixValue(ColorMixColorSpace aColorSpace, const nsCSSValue& aColor1, const nsCSSValue& aColor2)
|
||||
: mColorSpace(aColorSpace), mColor1(aColor1), mColor2(aColor2), mWeight1(0.5f), mWeight2(0.5f) {}
|
||||
|
||||
ColorMixValue(ColorMixColorSpace aColorSpace, const nsCSSValue& aColor1, const nsCSSValue& aColor2,
|
||||
float aWeight1, float aWeight2)
|
||||
: mColorSpace(aColorSpace), mColor1(aColor1), mColor2(aColor2), mWeight1(aWeight1), mWeight2(aWeight2) {}
|
||||
|
||||
ColorMixValue(const ColorMixValue&) = delete;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(ColorMixValue)
|
||||
|
||||
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
~ColorMixValue() {}
|
||||
};
|
||||
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* nsCSSValue_h___ */
|
||||
|
||||
|
|
|
|||
|
|
@ -1137,6 +1137,165 @@ static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
|
|||
aResult = aParentColor;
|
||||
result = true;
|
||||
aConditions.SetUncacheable();
|
||||
} else if (eCSSUnit_ColorMix == unit) {
|
||||
const mozilla::css::ColorMixValue* colorMix = aValue.GetColorMixValue();
|
||||
if (colorMix) {
|
||||
nscolor color1, color2;
|
||||
if (SetColor(colorMix->mColor1, aParentColor, aPresContext, aContext, color1, aConditions) &&
|
||||
SetColor(colorMix->mColor2, aParentColor, aPresContext, aContext, color2, aConditions)) {
|
||||
|
||||
// interpolate each RGBA component with proper percentage handling
|
||||
float w1 = colorMix->mWeight1;
|
||||
float w2 = colorMix->mWeight2;
|
||||
|
||||
// edge case: if both weights are zero, return transparent black
|
||||
if (w1 <= 0.0f && w2 <= 0.0f) {
|
||||
aResult = NS_RGBA(0, 0, 0, 0);
|
||||
result = true;
|
||||
} else {
|
||||
// normalize weights
|
||||
float sum = w1 + w2;
|
||||
if (sum <= 0.0f) {
|
||||
// both weights zero - use equal weighting
|
||||
w1 = w2 = 0.5f;
|
||||
sum = 1.0f;
|
||||
}
|
||||
|
||||
float norm1 = w1 / sum;
|
||||
float norm2 = w2 / sum;
|
||||
|
||||
if (colorMix->mColorSpace == mozilla::css::ColorMixColorSpace::HSL) {
|
||||
// HSL color space mixing
|
||||
float h1, s1, l1, h2, s2, l2;
|
||||
float a1 = NS_GET_A(color1) / 255.0f;
|
||||
float a2 = NS_GET_A(color2) / 255.0f;
|
||||
|
||||
// Convert RGB colors to HSL
|
||||
NS_RGB2HSL(NS_GET_R(color1), NS_GET_G(color1), NS_GET_B(color1), &h1, &s1, &l1);
|
||||
NS_RGB2HSL(NS_GET_R(color2), NS_GET_G(color2), NS_GET_B(color2), &h2, &s2, &l2);
|
||||
|
||||
float h, s, l, a;
|
||||
|
||||
// check if both are opaque
|
||||
if (a1 >= 1.0f && a2 >= 1.0f) {
|
||||
if (s1 == 0.0f || s2 == 0.0f) {
|
||||
h = (s1 == 0.0f) ? h2 : h1;
|
||||
} else {
|
||||
float hue_diff = h2 - h1;
|
||||
if (hue_diff > 0.5f) {
|
||||
h1 += 1.0f;
|
||||
} else if (hue_diff < -0.5f) {
|
||||
h2 += 1.0f;
|
||||
}
|
||||
h = h1 * norm1 + h2 * norm2;
|
||||
if (h >= 1.0f) h -= 1.0f;
|
||||
}
|
||||
|
||||
// interpolate saturation and lightness normally
|
||||
s = s1 * norm1 + s2 * norm2;
|
||||
l = l1 * norm1 + l2 * norm2;
|
||||
a = 1.0f; // Result is opaque
|
||||
} else {
|
||||
// handle alpha premultiplication for HSL components when transparency is involved
|
||||
float alpha1_weight = norm1 * a1;
|
||||
float alpha2_weight = norm2 * a2;
|
||||
float total_alpha_weight = alpha1_weight + alpha2_weight;
|
||||
|
||||
if (total_alpha_weight <= 0.0f) {
|
||||
// both colors are fully transparent
|
||||
h = s = l = 0.0f;
|
||||
a = 0.0f;
|
||||
} else {
|
||||
// normalize alpha-weighted contributions
|
||||
float norm_alpha1 = alpha1_weight / total_alpha_weight;
|
||||
float norm_alpha2 = alpha2_weight / total_alpha_weight;
|
||||
|
||||
// handle hue interpolation (circular)
|
||||
if (s1 == 0.0f || s2 == 0.0f) {
|
||||
h = (s1 == 0.0f) ? h2 : h1;
|
||||
} else {
|
||||
float hue_diff = h2 - h1;
|
||||
if (hue_diff > 0.5f) {
|
||||
h1 += 1.0f;
|
||||
} else if (hue_diff < -0.5f) {
|
||||
h2 += 1.0f;
|
||||
}
|
||||
h = h1 * norm_alpha1 + h2 * norm_alpha2;
|
||||
if (h >= 1.0f) h -= 1.0f;
|
||||
}
|
||||
|
||||
// interpolate saturation and lightness with alpha weighting
|
||||
s = s1 * norm_alpha1 + s2 * norm_alpha2;
|
||||
l = l1 * norm_alpha1 + l2 * norm_alpha2;
|
||||
|
||||
// interpolate alpha normally (without premultiplication)
|
||||
a = a1 * norm1 + a2 * norm2;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back to RGB
|
||||
nscolor hslResult = NS_HSL2RGB(h, s, l);
|
||||
uint8_t aInt = (uint8_t)mozilla::clamped(a * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
|
||||
aResult = NS_RGBA(NS_GET_R(hslResult), NS_GET_G(hslResult), NS_GET_B(hslResult), aInt);
|
||||
result = true;
|
||||
} else {
|
||||
// sRGB color space mixing with proper alpha premultiplication
|
||||
float r1 = NS_GET_R(color1);
|
||||
float g1 = NS_GET_G(color1);
|
||||
float b1 = NS_GET_B(color1);
|
||||
float a1 = NS_GET_A(color1) / 255.0f;
|
||||
|
||||
float r2 = NS_GET_R(color2);
|
||||
float g2 = NS_GET_G(color2);
|
||||
float b2 = NS_GET_B(color2);
|
||||
float a2 = NS_GET_A(color2) / 255.0f;
|
||||
|
||||
float r, g, b, a;
|
||||
|
||||
// Check if both colors are opaque - use simple interpolation
|
||||
if (a1 >= 1.0f && a2 >= 1.0f) {
|
||||
// Simple linear interpolation for opaque colors
|
||||
r = r1 * norm1 + r2 * norm2;
|
||||
g = g1 * norm1 + g2 * norm2;
|
||||
b = b1 * norm1 + b2 * norm2;
|
||||
a = 1.0f; // Result is opaque
|
||||
} else {
|
||||
// handle alpha premultiplication for RGB components when transparency is involved
|
||||
float alpha1_weight = norm1 * a1;
|
||||
float alpha2_weight = norm2 * a2;
|
||||
float total_alpha_weight = alpha1_weight + alpha2_weight;
|
||||
|
||||
if (total_alpha_weight <= 0.0f) {
|
||||
// both colors are fully transparent
|
||||
r = g = b = a = 0.0f;
|
||||
} else {
|
||||
// normalize alpha-weighted contributions
|
||||
float norm_alpha1 = alpha1_weight / total_alpha_weight;
|
||||
float norm_alpha2 = alpha2_weight / total_alpha_weight;
|
||||
|
||||
// interpolate RGB components with alpha weighting
|
||||
r = r1 * norm_alpha1 + r2 * norm_alpha2;
|
||||
g = g1 * norm_alpha1 + g2 * norm_alpha2;
|
||||
b = b1 * norm_alpha1 + b2 * norm_alpha2;
|
||||
|
||||
// interpolate alpha normally (without premultiplication)
|
||||
a = a1 * norm1 + a2 * norm2;
|
||||
}
|
||||
}
|
||||
|
||||
// convert to integers with rounding
|
||||
uint8_t rInt = (uint8_t)mozilla::clamped(r + 0.5f, 0.0f, 255.0f);
|
||||
uint8_t gInt = (uint8_t)mozilla::clamped(g + 0.5f, 0.0f, 255.0f);
|
||||
uint8_t bInt = (uint8_t)mozilla::clamped(b + 0.5f, 0.0f, 255.0f);
|
||||
uint8_t aInt = (uint8_t)mozilla::clamped(a * 255.0f + 0.5f, 0.0f, 255.0f);
|
||||
|
||||
aResult = NS_RGBA(rInt, gInt, bInt, aInt);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (eCSSUnit_Enumerated == unit &&
|
||||
aValue.GetIntValue() == NS_STYLE_COLOR_INHERIT_FROM_BODY) {
|
||||
NS_ASSERTION(aPresContext->CompatibilityMode() == eCompatibility_NavQuirks,
|
||||
|
|
|
|||
|
|
@ -106,6 +106,14 @@ input {
|
|||
overflow-clip-box: content-box;
|
||||
}
|
||||
|
||||
/* Autofill highlight - placed immediately after base input styles */
|
||||
input:-moz-autofill-highlight,
|
||||
select:-moz-autofill-highlight,
|
||||
textarea:-moz-autofill-highlight {
|
||||
background-color: #fffcd0 !important;
|
||||
color: #090909;
|
||||
}
|
||||
|
||||
input > .anonymous-div,
|
||||
input::placeholder {
|
||||
word-wrap: normal !important;
|
||||
|
|
@ -1148,4 +1156,4 @@ input[type="number"] > div > div > div:hover {
|
|||
input[type="date"],
|
||||
input[type="time"] {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue