Bug 1408308: Integrate Servo SourceSizeList in ResponsiveImageSelector. r=Manishearth
☠☠ backed out by 168af2eb1faf ☠ ☠
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 09 Nov 2017 15:18:08 +0100
changeset 391502 b59ffea83e0abe345853fa76dba4bca551464858
parent 391501 6f321c024fc4e82363e9b1215891a37d8abde5de
child 391503 168af2eb1faf085e06768dd11431175242afb5ee
push id32892
push userncsoregi@mozilla.com
push dateMon, 13 Nov 2017 22:56:04 +0000
treeherdermozilla-central@3dddb19f2a07 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersManishearth
bugs1408308
milestone59.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 1408308: Integrate Servo SourceSizeList in ResponsiveImageSelector. r=Manishearth This needs to dumb down the parsing in order to match what we do in Gecko and pass more tests. The remaining tests are just because of calc() in media queries and "or" media expressions. MozReview-Commit-ID: CXGdYVbojBL
dom/base/ResponsiveImageSelector.cpp
dom/base/ResponsiveImageSelector.h
layout/style/ServoBindingList.h
layout/style/ServoBindingTypes.h
layout/style/ServoBindings.toml
layout/style/ServoStyleSet.h
--- a/dom/base/ResponsiveImageSelector.cpp
+++ b/dom/base/ResponsiveImageSelector.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "mozilla/dom/ResponsiveImageSelector.h"
+#include "mozilla/ServoStyleSet.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
 #include "nsPresContext.h"
 
 #include "nsCSSParser.h"
 #include "nsCSSProps.h"
 #include "nsMediaList.h"
@@ -236,21 +237,28 @@ ResponsiveImageSelector::ClearSelectedCa
   mSelectedCandidateIndex = -1;
   mSelectedCandidateURL = nullptr;
 }
 
 bool
 ResponsiveImageSelector::SetSizesFromDescriptor(const nsAString & aSizes)
 {
   ClearSelectedCandidate();
+
+  if (Document()->IsStyledByServo()) {
+    NS_ConvertUTF16toUTF8 sizes(aSizes);
+    mServoSourceSizeList.reset(Servo_SourceSizeList_Parse(&sizes));
+    return !!mServoSourceSizeList;
+  }
+
+  nsCSSParser cssParser;
+
   mSizeQueries.Clear();
   mSizeValues.Clear();
 
-  nsCSSParser cssParser;
-
   return cssParser.ParseSourceSizeList(aSizes, nullptr, 0,
                                        mSizeQueries, mSizeValues);
 }
 
 void
 ResponsiveImageSelector::AppendCandidateIfUnique(const ResponsiveImageCandidate & aCandidate)
 {
   int numCandidates = mCandidates.Length();
@@ -359,21 +367,21 @@ ResponsiveImageSelector::SelectImage(boo
   ClearSelectedCandidate();
 
   int numCandidates = mCandidates.Length();
   if (!numCandidates) {
     return oldBest != -1;
   }
 
   nsIDocument* doc = Document();
-  nsIPresShell *shell = doc ? doc->GetShell() : nullptr;
-  nsPresContext *pctx = shell ? shell->GetPresContext() : nullptr;
-  nsCOMPtr<nsIURI> baseURI = mOwnerNode ? mOwnerNode->GetBaseURI() : nullptr;
+  nsIPresShell* shell = doc->GetShell();
+  nsPresContext* pctx = shell ? shell->GetPresContext() : nullptr;
+  nsCOMPtr<nsIURI> baseURI = mOwnerNode->GetBaseURI();
 
-  if (!pctx || !doc || !baseURI) {
+  if (!pctx || !baseURI) {
     return oldBest != -1;
   }
 
   double displayDensity = pctx->CSSPixelsToDevPixels(1.0f);
   double overrideDPPX = pctx->GetOverrideDPPX();
 
   if (overrideDPPX > 0) {
     displayDensity = overrideDPPX;
@@ -383,17 +391,17 @@ ResponsiveImageSelector::SelectImage(boo
   // - For now, select the lowest density greater than displayDensity, otherwise
   //   the greatest density available
 
   // If the list contains computed width candidates, compute the current
   // effective image width.
   double computedWidth = -1;
   for (int i = 0; i < numCandidates; i++) {
     if (mCandidates[i].IsComputedFromWidth()) {
-      DebugOnly<bool> computeResult = \
+      DebugOnly<bool> computeResult =
         ComputeFinalWidthForCurrentViewport(&computedWidth);
       MOZ_ASSERT(computeResult,
                  "Computed candidates not allowed without sizes data");
       break;
     }
   }
 
   int bestIndex = -1;
@@ -434,44 +442,48 @@ ResponsiveImageSelector::GetSelectedCand
   SelectImage();
 
   return mSelectedCandidateIndex;
 }
 
 bool
 ResponsiveImageSelector::ComputeFinalWidthForCurrentViewport(double *aWidth)
 {
-  unsigned int numSizes = mSizeQueries.Length();
   nsIDocument* doc = Document();
-  nsIPresShell *presShell = doc ? doc->GetShell() : nullptr;
-  nsPresContext *pctx = presShell ? presShell->GetPresContext() : nullptr;
+  nsIPresShell* presShell = doc->GetShell();
+  nsPresContext* pctx = presShell ? presShell->GetPresContext() : nullptr;
 
   if (!pctx) {
     return false;
   }
-
-  MOZ_ASSERT(numSizes == mSizeValues.Length(),
-             "mSizeValues length differs from mSizeQueries");
+  nscoord effectiveWidth;
+  if (doc->IsStyledByServo()) {
+    effectiveWidth = presShell->StyleSet()->AsServo()->EvaluateSourceSizeList(
+      mServoSourceSizeList.get());
+  } else {
+    unsigned int numSizes = mSizeQueries.Length();
+    MOZ_ASSERT(numSizes == mSizeValues.Length(),
+               "mSizeValues length differs from mSizeQueries");
 
-  unsigned int i;
-  for (i = 0; i < numSizes; i++) {
-    if (mSizeQueries[i]->Matches(pctx, nullptr)) {
-      break;
+    unsigned int i;
+    for (i = 0; i < numSizes; i++) {
+      if (mSizeQueries[i]->Matches(pctx, nullptr)) {
+        break;
+      }
     }
-  }
 
-  nscoord effectiveWidth;
-  if (i == numSizes) {
-    // No match defaults to 100% viewport
-    nsCSSValue defaultWidth(100.0f, eCSSUnit_ViewportWidth);
-    effectiveWidth = nsRuleNode::CalcLengthWithInitialFont(pctx,
-                                                           defaultWidth);
-  } else {
-    effectiveWidth = nsRuleNode::CalcLengthWithInitialFont(pctx,
-                                                           mSizeValues[i]);
+    if (i == numSizes) {
+      // No match defaults to 100% viewport
+      nsCSSValue defaultWidth(100.0f, eCSSUnit_ViewportWidth);
+      effectiveWidth = nsRuleNode::CalcLengthWithInitialFont(pctx,
+                                                             defaultWidth);
+    } else {
+      effectiveWidth = nsRuleNode::CalcLengthWithInitialFont(pctx,
+                                                             mSizeValues[i]);
+    }
   }
 
   *aWidth = nsPresContext::AppUnitsToDoubleCSSPixels(std::max(effectiveWidth, 0));
   return true;
 }
 
 ResponsiveImageCandidate::ResponsiveImageCandidate()
 {
--- a/dom/base/ResponsiveImageSelector.h
+++ b/dom/base/ResponsiveImageSelector.h
@@ -115,16 +115,20 @@ private:
   // If this array contains an eCandidateType_Default, it should be the last
   // element, such that the Setters can preserve/replace it respectively.
   nsTArray<ResponsiveImageCandidate> mCandidates;
   int mSelectedCandidateIndex;
   // The cached resolved URL for mSelectedCandidateIndex, such that we only
   // resolve the absolute URL at selection time
   nsCOMPtr<nsIURI> mSelectedCandidateURL;
 
+  // Servo bits.
+  UniquePtr<RawServoSourceSizeList> mServoSourceSizeList;
+
+  // Gecko bits.
   nsTArray< nsAutoPtr<nsMediaQuery> > mSizeQueries;
   nsTArray<nsCSSValue> mSizeValues;
 };
 
 class ResponsiveImageCandidate {
 public:
   ResponsiveImageCandidate();
   ResponsiveImageCandidate(const nsAString& aURLString, double aDensity,
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -129,16 +129,23 @@ SERVO_BINDING_FUNC(Servo_StyleSet_Resolv
                    RawServoStyleSetBorrowed set,
                    ServoStyleContextBorrowedOrNull parent_style,
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_SelectorList_Drop, void,
                    RawServoSelectorListOwned selector_list)
 SERVO_BINDING_FUNC(Servo_SelectorList_Parse,
                    RawServoSelectorList*,
                    const nsACString* selector_list)
+SERVO_BINDING_FUNC(Servo_SourceSizeList_Parse,
+                   RawServoSourceSizeList*,
+                   const nsACString* value)
+SERVO_BINDING_FUNC(Servo_SourceSizeList_Evaluate,
+                   int32_t,
+                   RawServoStyleSetBorrowed set,
+                   RawServoSourceSizeListBorrowedOrNull)
 SERVO_BINDING_FUNC(Servo_SelectorList_Matches, bool,
                    RawGeckoElementBorrowed, RawServoSelectorListBorrowed)
 SERVO_BINDING_FUNC(Servo_SelectorList_Closest, const RawGeckoElement*,
                    RawGeckoElementBorrowed, RawServoSelectorListBorrowed)
 SERVO_BINDING_FUNC(Servo_SelectorList_QueryFirst, const RawGeckoElement*,
                    RawGeckoNodeBorrowed, RawServoSelectorListBorrowed,
                    bool may_use_invalidation)
 SERVO_BINDING_FUNC(Servo_SelectorList_QueryAll, void,
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -12,16 +12,17 @@
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/Types.h"
 #include "nsCSSPropertyID.h"
 #include "nsStyleAutoArray.h"
 #include "nsTArray.h"
 
 struct RawServoStyleSet;
 struct RawServoSelectorList;
+struct RawServoSourceSizeList;
 struct RawServoAnimationValueMap;
 struct RustString;
 
 #define SERVO_ARC_TYPE(name_, type_) struct type_;
 #include "mozilla/ServoArcTypeList.h"
 #undef SERVO_ARC_TYPE
 
 namespace mozilla {
@@ -177,16 +178,19 @@ DECL_BORROWED_REF_TYPE_FOR(RawGeckoAnima
 DECL_BORROWED_REF_TYPE_FOR(RawGeckoComputedTiming)
 DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoServoStyleRuleList)
 DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSPropertyIDSet)
 DECL_BORROWED_REF_TYPE_FOR(RawGeckoCSSPropertyIDList)
 DECL_BORROWED_REF_TYPE_FOR(nsXBLBinding)
 DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoStyleChildrenIterator)
 DECL_OWNED_REF_TYPE_FOR(RawServoSelectorList)
 DECL_BORROWED_REF_TYPE_FOR(RawServoSelectorList)
+DECL_OWNED_REF_TYPE_FOR(RawServoSourceSizeList)
+DECL_BORROWED_REF_TYPE_FOR(RawServoSourceSizeList)
+DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawServoSourceSizeList)
 
 #undef DECL_ARC_REF_TYPE_FOR
 #undef DECL_OWNED_REF_TYPE_FOR
 #undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
 #undef DECL_BORROWED_REF_TYPE_FOR
 #undef DECL_NULLABLE_BORROWED_REF_TYPE_FOR
 #undef DECL_BORROWED_MUT_REF_TYPE_FOR
 #undef DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR
@@ -220,12 +224,13 @@ DECL_BORROWED_REF_TYPE_FOR(RawServoSelec
     {                                                       \
       Servo_##name_##_Drop(aPtr);                           \
     }                                                       \
   };                                                        \
   }
 
 DEFINE_BOXED_TYPE(StyleSet, RawServoStyleSet);
 DEFINE_BOXED_TYPE(SelectorList, RawServoSelectorList);
+DEFINE_BOXED_TYPE(SourceSizeList, RawServoSourceSizeList);
 
 #undef DEFINE_BOXED_TYPE
 
 #endif // mozilla_ServoBindingTypes_h
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -490,16 +490,17 @@ structs-types = [
     "RawGeckoPresContext",
     "RawGeckoPresContextOwned",
     "RawGeckoStyleAnimationList",
     "RawGeckoStyleChildrenIterator",
     "RawGeckoServoStyleRuleList",
     "RawGeckoURLExtraData",
     "RawGeckoXBLBinding",
     "RawServoSelectorList",
+    "RawServoSourceSizeList",
     "RefPtr",
     "RustString",
     "CSSPseudoClassType",
     "CSSPseudoElementType",
     "ServoTraversalFlags",
     "ComputedTimingFunction_BeforeFlag",
     "CounterStylePtr",
     "FontFamilyType",
@@ -603,16 +604,17 @@ structs-types = [
     "mozilla::SharedFontList",
 ]
 array-types = [
     { cpp-type = "uintptr_t", rust-type = "usize" },
 ]
 servo-owned-types = [
     { name = "RawServoStyleSet", opaque = true },
     { name = "RawServoSelectorList", opaque = false },
+    { name = "RawServoSourceSizeList", opaque = false },
     { name = "ServoElementSnapshot", opaque = false },
     { name = "RawServoAnimationValueMap", opaque = true },
 ]
 servo-immutable-borrow-types = [
     "RawGeckoNode",
     "RawGeckoElement",
     "RawGeckoDocument",
     "RawServoDeclarationBlockStrong",
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -9,16 +9,17 @@
 
 #include "mozilla/AtomArray.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/EnumeratedArray.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/PostTraversalTask.h"
 #include "mozilla/ServoBindingTypes.h"
 #include "mozilla/ServoElementSnapshot.h"
+#include "mozilla/ServoBindings.h"
 #include "mozilla/ServoUtils.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/SheetType.h"
 #include "mozilla/UniquePtr.h"
 #include "MainThreadUtils.h"
 #include "nsCSSPseudoElements.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsChangeHint.h"
@@ -145,16 +146,25 @@ public:
 
   bool StyleSheetsHaveChanged() const
   {
     return StylistNeedsUpdate();
   }
 
   nsRestyleHint MediumFeaturesChanged(bool aViewportChanged);
 
+  // Evaluates a given SourceSizeList, returning the optimal viewport width in
+  // app units.
+  //
+  // The SourceSizeList parameter can be null, in which case it will return
+  // 100vw.
+  nscoord EvaluateSourceSizeList(const RawServoSourceSizeList* aSourceSizeList) const {
+    return Servo_SourceSizeList_Evaluate(mRawSet.get(), aSourceSizeList);
+  }
+
   // aViewportChanged outputs whether any viewport units is used.
   bool MediumFeaturesChangedRules(bool* aViewportUnitsUsed);
 
   void InvalidateStyleForCSSRuleChanges();
 
   void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
   const RawServoStyleSet* RawSet() const {
     return mRawSet.get();