diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index af9769f4cb0e..16c69f86c943 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -146,6 +146,7 @@ using namespace mozilla::gfx; #define DISPLAY_CONTENTS_ENABLED_PREF_NAME "layout.css.display-contents.enabled" #define TEXT_ALIGN_UNSAFE_ENABLED_PREF_NAME "layout.css.text-align-unsafe-value.enabled" #define FLOAT_LOGICAL_VALUES_ENABLED_PREF_NAME "layout.css.float-logical-values.enabled" +#define BG_CLIP_TEXT_ENABLED_PREF_NAME "layout.css.background-clip-text.enabled" #ifdef DEBUG // TODO: remove, see bug 598468. @@ -392,6 +393,39 @@ FloatLogicalValuesEnabledPrefChangeCallback(const char* aPrefName, isFloatLogicalValuesEnabled ? eCSSKeyword_inline_end : eCSSKeyword_UNKNOWN; } + +// When the pref "layout.css.background-clip-text.enabled" changes, this +// function is invoked to let us update kBackgroundClipKTable, to selectively +// disable or restore the entries for "text" in that table. +static void +BackgroundClipTextEnabledPrefChangeCallback(const char* aPrefName, + void* aClosure) +{ + NS_ASSERTION(strcmp(aPrefName, BG_CLIP_TEXT_ENABLED_PREF_NAME) == 0, + "Did you misspell " BG_CLIP_TEXT_ENABLED_PREF_NAME " ?"); + + static bool sIsBGClipKeywordIndexInitialized; + static int32_t sIndexOfTextInBGClipTable; + bool isBGClipTextEnabled = + Preferences::GetBool(BG_CLIP_TEXT_ENABLED_PREF_NAME, false); + + if (!sIsBGClipKeywordIndexInitialized) { + // First run: find the position of "text" in kBackgroundClipKTable. + sIndexOfTextInBGClipTable = + nsCSSProps::FindIndexOfKeyword(eCSSKeyword_text, + nsCSSProps::kBackgroundClipKTable); + + sIsBGClipKeywordIndexInitialized = true; + } + + // OK -- now, stomp on or restore the "text" entry in kBackgroundClipKTable, + // depending on whether the pref is enabled vs. disabled. + if (sIndexOfTextInBGClipTable >= 0) { + nsCSSProps::kBackgroundClipKTable[sIndexOfTextInBGClipTable].mKeyword = + isBGClipTextEnabled ? eCSSKeyword_text : eCSSKeyword_UNKNOWN; + } +} + template static bool HasMatchingCurrentAnimations(const nsIFrame* aFrame, TestType&& aTest) @@ -7647,6 +7681,10 @@ nsLayoutUtils::Initialize() FLOAT_LOGICAL_VALUES_ENABLED_PREF_NAME); FloatLogicalValuesEnabledPrefChangeCallback(FLOAT_LOGICAL_VALUES_ENABLED_PREF_NAME, nullptr); + Preferences::RegisterCallback(BackgroundClipTextEnabledPrefChangeCallback, + BG_CLIP_TEXT_ENABLED_PREF_NAME); + BackgroundClipTextEnabledPrefChangeCallback(BG_CLIP_TEXT_ENABLED_PREF_NAME, + nullptr); nsComputedDOMStyle::RegisterPrefChangeCallbacks(); } diff --git a/layout/style/Declaration.cpp b/layout/style/Declaration.cpp index 5dea92b0af28..848f2e353a92 100644 --- a/layout/style/Declaration.cpp +++ b/layout/style/Declaration.cpp @@ -295,12 +295,16 @@ Declaration::GetImageLayerValue( if (clip->mValue.GetIntValue() != NS_STYLE_IMAGELAYER_CLIP_BORDER || origin->mValue.GetIntValue() != NS_STYLE_IMAGELAYER_ORIGIN_PADDING) { - MOZ_ASSERT(nsCSSProps::kKeywordTableTable[ - aTable[nsStyleImageLayers::origin]] == - nsCSSProps::kImageLayerOriginKTable); - MOZ_ASSERT(nsCSSProps::kKeywordTableTable[ - aTable[nsStyleImageLayers::clip]] == - nsCSSProps::kImageLayerOriginKTable); +#ifdef DEBUG + for (size_t i = 0; nsCSSProps::kImageLayerOriginKTable[i].mValue != -1; i++) { + // For each keyword & value in kOriginKTable, ensure that + // kBackgroundKTable has a matching entry at the same position. + MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mKeyword == + nsCSSProps::kBackgroundClipKTable[i].mKeyword); + MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mValue == + nsCSSProps::kBackgroundClipKTable[i].mValue); + } +#endif static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER == NS_STYLE_IMAGELAYER_ORIGIN_BORDER && NS_STYLE_IMAGELAYER_CLIP_PADDING == diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index a3f15d81d8e1..ddc2e3874f5b 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -12063,13 +12063,16 @@ CSSParserImpl::ParseImageLayersItem( // The spec allows a second box value (for background-clip), // immediately following the first one (for background-origin). - // 'background-clip' and 'background-origin' use the same keyword table - MOZ_ASSERT(nsCSSProps::kKeywordTableTable[ - aTable[nsStyleImageLayers::origin]] == - nsCSSProps::kImageLayerOriginKTable); - MOZ_ASSERT(nsCSSProps::kKeywordTableTable[ - aTable[nsStyleImageLayers::clip]] == - nsCSSProps::kImageLayerOriginKTable); +#ifdef DEBUG + for (size_t i = 0; nsCSSProps::kImageLayerOriginKTable[i].mValue != -1; i++) { + // For each keyword & value in kOriginKTable, ensure that + // kBackgroundKTable has a matching entry at the same position. + MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mKeyword == + nsCSSProps::kBackgroundClipKTable[i].mKeyword); + MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mValue == + nsCSSProps::kBackgroundClipKTable[i].mValue); + } +#endif static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER == NS_STYLE_IMAGELAYER_ORIGIN_BORDER && NS_STYLE_IMAGELAYER_CLIP_PADDING == diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index f141ffba1e81..143549580a26 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -522,7 +522,7 @@ CSS_PROP_BACKGROUND( CSS_PROPERTY_VALUE_LIST_USES_COMMAS, "", VARIANT_KEYWORD, // used by list parsing - kImageLayerOriginKTable, + kBackgroundClipKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_None) CSS_PROP_BACKGROUND( diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index fe2b5be73dd6..65ef3ad42ecb 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -890,7 +890,9 @@ const KTableEntry nsCSSProps::kImageLayerAttachmentKTable[] = { static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER == NS_STYLE_IMAGELAYER_ORIGIN_BORDER && NS_STYLE_IMAGELAYER_CLIP_PADDING == NS_STYLE_IMAGELAYER_ORIGIN_PADDING && NS_STYLE_IMAGELAYER_CLIP_CONTENT == NS_STYLE_IMAGELAYER_ORIGIN_CONTENT, - "bg-clip and bg-origin style constants must agree"); + "Except background-clip:text, all {background,mask}-clip and " + "{background,mask}-origin style constants must agree"); + const KTableEntry nsCSSProps::kImageLayerOriginKTable[] = { { eCSSKeyword_border_box, NS_STYLE_IMAGELAYER_ORIGIN_BORDER }, { eCSSKeyword_padding_box, NS_STYLE_IMAGELAYER_ORIGIN_PADDING }, @@ -898,6 +900,21 @@ const KTableEntry nsCSSProps::kImageLayerOriginKTable[] = { { eCSSKeyword_UNKNOWN, -1 } }; +KTableEntry nsCSSProps::kBackgroundClipKTable[] = { + { eCSSKeyword_border_box, NS_STYLE_IMAGELAYER_CLIP_BORDER }, + { eCSSKeyword_padding_box, NS_STYLE_IMAGELAYER_CLIP_PADDING }, + { eCSSKeyword_content_box, NS_STYLE_IMAGELAYER_CLIP_CONTENT }, + // The next entry is controlled by the layout.css.background-clip-text.enabled + // pref. + { eCSSKeyword_text, NS_STYLE_IMAGELAYER_CLIP_TEXT }, + { eCSSKeyword_UNKNOWN, -1 } +}; + +static_assert(ArrayLength(nsCSSProps::kImageLayerOriginKTable) == + ArrayLength(nsCSSProps::kBackgroundClipKTable) - 1, + "background-clip has one extra value, which is text, compared" + "to {background,mask}-origin"); + // Note: Don't change this table unless you update // ParseImageLayerPosition! diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index 7f22b1a90dd0..f928407346e6 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -678,6 +678,9 @@ public: static const KTableEntry kImageLayerSizeKTable[]; static const KTableEntry kImageLayerCompositeKTable[]; static const KTableEntry kImageLayerModeKTable[]; + // Not const because we modify its entries when the pref + // "layout.css.background-clip.text" changes: + static KTableEntry kBackgroundClipKTable[]; static const KTableEntry kBlendModeKTable[]; static const KTableEntry kBorderCollapseKTable[]; static const KTableEntry kBorderColorKTable[]; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 7a787d14bd62..1663e9e96534 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -1845,7 +1845,7 @@ nsComputedDOMStyle::DoGetBackgroundClip() return GetBackgroundList(&nsStyleImageLayers::Layer::mClip, &nsStyleImageLayers::mClipCount, StyleBackground()->mImage, - nsCSSProps::kImageLayerOriginKTable); + nsCSSProps::kBackgroundClipKTable); } already_AddRefed diff --git a/layout/style/nsStyleConsts.h b/layout/style/nsStyleConsts.h index c684007b9bd9..9941edf07250 100644 --- a/layout/style/nsStyleConsts.h +++ b/layout/style/nsStyleConsts.h @@ -267,10 +267,12 @@ enum class FillMode : uint32_t; #define NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL 2 // See nsStyleImageLayers -// Code depends on these constants having the same values as BG_ORIGIN_* +// Code depends on these constants having the same values as IMAGELAYER_ORIGIN_* #define NS_STYLE_IMAGELAYER_CLIP_BORDER 0 #define NS_STYLE_IMAGELAYER_CLIP_PADDING 1 #define NS_STYLE_IMAGELAYER_CLIP_CONTENT 2 +// One extra constant which does not exist in IMAGELAYER_ORIGIN_* +#define NS_STYLE_IMAGELAYER_CLIP_TEXT 3 // A magic value that we use for our "pretend that background-clip is // 'padding' when we have a solid border" optimization. This isn't diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 84db5c53e83e..92af54319eff 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2421,6 +2421,9 @@ pref("layout.css.scope-pseudo.enabled", true); // Is support for background-blend-mode enabled? pref("layout.css.background-blend-mode.enabled", true); +// Is support for background-clip:text enabled? (bug 1263516) +pref("layout.css.background-clip-text.enabled", false); + // Is support for CSS vertical text enabled? pref("layout.css.vertical-text.enabled", true);