Bug 759568 - Part 1. Parse background-clip:text; r=dholbert r=heycom
☠☠ backed out by 79caf78bcaae ☠ ☠
authorCJKu <cku@mozilla.com>
Thu, 14 Apr 2016 12:45:37 +0800
changeset 293216 b68e6d1cf93ac9e82c716c17965d580ea49a820a
parent 293215 f8cf0fe7c810ee49bcb4efb27405073ae6156971
child 293217 6a2e62e8c861e742c5023a189df7ca98045f18ef
push id30178
push usercbook@mozilla.com
push dateFri, 15 Apr 2016 09:42:06 +0000
treeherdermozilla-central@afd82f887093 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert, heycom
bugs759568
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 759568 - Part 1. Parse background-clip:text; r=dholbert r=heycom MozReview-Commit-ID: BPuQjWYvAuj
layout/base/nsLayoutUtils.cpp
layout/style/Declaration.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsStyleConsts.h
modules/libpref/init/all.js
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -141,16 +141,17 @@ using namespace mozilla::layout;
 using namespace mozilla::gfx;
 
 #define GRID_ENABLED_PREF_NAME "layout.css.grid.enabled"
 #define GRID_TEMPLATE_SUBGRID_ENABLED_PREF_NAME "layout.css.grid-template-subgrid-value.enabled"
 #define WEBKIT_PREFIXES_ENABLED_PREF_NAME "layout.css.prefixes.webkit"
 #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.
 bool nsLayoutUtils::gPreventAssertInCompareTreePosition = false;
 #endif // DEBUG
 
 typedef FrameMetrics::ViewID ViewID;
 typedef nsStyleTransformMatrix::TransformReferenceBox TransformReferenceBox;
@@ -387,16 +388,49 @@ FloatLogicalValuesEnabledPrefChangeCallb
   MOZ_ASSERT(sIndexOfInlineStartInClearTable >= 0);
   nsCSSProps::kClearKTable[sIndexOfInlineStartInClearTable].mKeyword =
     isFloatLogicalValuesEnabled ? eCSSKeyword_inline_start : eCSSKeyword_UNKNOWN;
   MOZ_ASSERT(sIndexOfInlineEndInClearTable >= 0);
   nsCSSProps::kClearKTable[sIndexOfInlineEndInClearTable].mKeyword =
     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<typename TestType>
 static bool
 HasMatchingCurrentAnimations(const nsIFrame* aFrame, TestType&& aTest)
 {
   EffectSet* effects = EffectSet::GetEffectSet(aFrame);
   if (!effects) {
     return false;
   }
@@ -7642,16 +7676,20 @@ nsLayoutUtils::Initialize()
   DisplayContentsEnabledPrefChangeCallback(DISPLAY_CONTENTS_ENABLED_PREF_NAME,
                                            nullptr);
   TextAlignUnsafeEnabledPrefChangeCallback(TEXT_ALIGN_UNSAFE_ENABLED_PREF_NAME,
                                            nullptr);
   Preferences::RegisterCallback(FloatLogicalValuesEnabledPrefChangeCallback,
                                 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();
 }
 
 /* static */
 void
 nsLayoutUtils::Shutdown()
 {
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -290,22 +290,26 @@ Declaration::GetImageLayerValue(
     }
 
     MOZ_ASSERT(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
                origin->mValue.GetUnit() == eCSSUnit_Enumerated,
                "should not have inherit/initial within list");
 
     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 ==
                     NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
                     NS_STYLE_IMAGELAYER_CLIP_CONTENT ==
                     NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
                     "mask-clip and mask-origin style constants must agree");
       aValue.Append(char16_t(' '));
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -12058,23 +12058,26 @@ CSSParserImpl::ParseImageLayersItem(
             CSSParseResult::Ok) {
           NS_NOTREACHED("should be able to parse");
           return false;
         }
 
         // 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 ==
                       NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
                       NS_STYLE_IMAGELAYER_CLIP_CONTENT ==
                       NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
                       "bg-clip and bg-origin style constants must agree");
 
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -559,17 +559,17 @@ CSS_PROP_BACKGROUND(
     background_origin,
     BackgroundOrigin,
     CSS_PROPERTY_PARSE_VALUE_LIST |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
         CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
     "",
     VARIANT_KEYWORD, // used by list parsing
-    kImageLayerOriginKTable,
+    kBackgroundClipKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_BACKGROUND(
     background-position,
     background_position,
     BackgroundPosition,
     CSS_PROPERTY_PARSE_FUNCTION |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -885,24 +885,41 @@ const KTableEntry nsCSSProps::kImageLaye
   { eCSSKeyword_scroll, NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL },
   { eCSSKeyword_local, NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL },
   { eCSSKeyword_UNKNOWN, -1 }
 };
 
 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 },
   { eCSSKeyword_content_box, NS_STYLE_IMAGELAYER_ORIGIN_CONTENT },
   { 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!
 
 const KTableEntry nsCSSProps::kImageLayerPositionKTable[] = {
   { eCSSKeyword_center, NS_STYLE_IMAGELAYER_POSITION_CENTER },
   { eCSSKeyword_top, NS_STYLE_IMAGELAYER_POSITION_TOP },
   { eCSSKeyword_bottom, NS_STYLE_IMAGELAYER_POSITION_BOTTOM },
   { eCSSKeyword_left, NS_STYLE_IMAGELAYER_POSITION_LEFT },
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -673,16 +673,19 @@ public:
   static const KTableEntry kImageLayerAttachmentKTable[];
   static const KTableEntry kImageLayerOriginKTable[];
   static const KTableEntry kImageLayerPositionKTable[];
   static const KTableEntry kImageLayerRepeatKTable[];
   static const KTableEntry kImageLayerRepeatPartKTable[];
   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[];
   static const KTableEntry kBorderImageRepeatKTable[];
   static const KTableEntry kBorderImageSliceKTable[];
   static const KTableEntry kBorderStyleKTable[];
   static const KTableEntry kBorderWidthKTable[];
   static const KTableEntry kBoxAlignKTable[];
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1840,17 +1840,17 @@ nsComputedDOMStyle::DoGetBackgroundAttac
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBackgroundClip()
 {
   return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
                            &nsStyleImageLayers::mClipCount,
                            StyleBackground()->mImage,
-                           nsCSSProps::kImageLayerOriginKTable);
+                           nsCSSProps::kBackgroundClipKTable);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetBackgroundColor()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   SetToRGBAColor(val, StyleBackground()->mBackgroundColor);
   return val.forget();
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -262,20 +262,22 @@ enum class FillMode : uint32_t;
 #define NS_STYLE_ANIMATION_PLAY_STATE_PAUSED      1
 
 // See nsStyleImageLayers
 #define NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL        0
 #define NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED         1
 #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
 // actually equal to NS_STYLE_IMAGELAYER_CLIP_PADDING because using that
 // causes antialiasing seams between the background and border.  This
 // is a backend-only value.
 #define NS_STYLE_IMAGELAYER_CLIP_MOZ_ALMOST_PADDING  127
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2416,16 +2416,19 @@ pref("layout.css.unprefixing-service.glo
 #endif
 
 // Is support for the :scope selector enabled?
 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);
 
 // Is support for CSS text-combine-upright (tate-chu-yoko) enabled?
 pref("layout.css.text-combine-upright.enabled", false);
 
 // Is support for object-fit and object-position enabled?
 pref("layout.css.object-fit-and-position.enabled", true);