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
This commit is contained in:
Emilio Cobos Álvarez
2017-11-09 15:18:08 +01:00
parent 4b47ff7ad6
commit 3d7e848428
6 changed files with 68 additions and 28 deletions

View File

@@ -5,6 +5,7 @@
* 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"
@@ -241,11 +242,18 @@ bool
ResponsiveImageSelector::SetSizesFromDescriptor(const nsAString & aSizes)
{
ClearSelectedCandidate();
mSizeQueries.Clear();
mSizeValues.Clear();
if (Document()->IsStyledByServo()) {
NS_ConvertUTF16toUTF8 sizes(aSizes);
mServoSourceSizeList.reset(Servo_SourceSizeList_Parse(&sizes));
return !!mServoSourceSizeList;
}
nsCSSParser cssParser;
mSizeQueries.Clear();
mSizeValues.Clear();
return cssParser.ParseSourceSizeList(aSizes, nullptr, 0,
mSizeQueries, mSizeValues);
}
@@ -364,11 +372,11 @@ ResponsiveImageSelector::SelectImage(bool aReselect)
}
nsIDocument* doc = Document();
nsIPresShell *shell = doc ? doc->GetShell() : nullptr;
nsIPresShell* shell = doc->GetShell();
nsPresContext* pctx = shell ? shell->GetPresContext() : nullptr;
nsCOMPtr<nsIURI> baseURI = mOwnerNode ? mOwnerNode->GetBaseURI() : nullptr;
nsCOMPtr<nsIURI> baseURI = mOwnerNode->GetBaseURI();
if (!pctx || !doc || !baseURI) {
if (!pctx || !baseURI) {
return oldBest != -1;
}
@@ -388,7 +396,7 @@ ResponsiveImageSelector::SelectImage(bool aReselect)
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");
@@ -439,15 +447,19 @@ ResponsiveImageSelector::GetSelectedCandidateIndex()
bool
ResponsiveImageSelector::ComputeFinalWidthForCurrentViewport(double *aWidth)
{
unsigned int numSizes = mSizeQueries.Length();
nsIDocument* doc = Document();
nsIPresShell *presShell = doc ? doc->GetShell() : nullptr;
nsIPresShell* presShell = doc->GetShell();
nsPresContext* pctx = presShell ? presShell->GetPresContext() : nullptr;
if (!pctx) {
return false;
}
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");
@@ -458,7 +470,6 @@ ResponsiveImageSelector::ComputeFinalWidthForCurrentViewport(double *aWidth)
}
}
nscoord effectiveWidth;
if (i == numSizes) {
// No match defaults to 100% viewport
nsCSSValue defaultWidth(100.0f, eCSSUnit_ViewportWidth);
@@ -468,6 +479,7 @@ ResponsiveImageSelector::ComputeFinalWidthForCurrentViewport(double *aWidth)
effectiveWidth = nsRuleNode::CalcLengthWithInitialFont(pctx,
mSizeValues[i]);
}
}
*aWidth = nsPresContext::AppUnitsToDoubleCSSPixels(std::max(effectiveWidth, 0));
return true;

View File

@@ -120,6 +120,10 @@ private:
// resolve the absolute URL at selection time
nsCOMPtr<nsIURI> mSelectedCandidateURL;
// Servo bits.
UniquePtr<RawServoSourceSizeList> mServoSourceSizeList;
// Gecko bits.
nsTArray< nsAutoPtr<nsMediaQuery> > mSizeQueries;
nsTArray<nsCSSValue> mSizeValues;
};

View File

@@ -134,6 +134,13 @@ SERVO_BINDING_FUNC(Servo_SelectorList_Drop, void,
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*,

View File

@@ -17,6 +17,7 @@
struct RawServoStyleSet;
struct RawServoSelectorList;
struct RawServoSourceSizeList;
struct RawServoAnimationValueMap;
struct RustString;
@@ -182,6 +183,9 @@ 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
@@ -225,6 +229,7 @@ DECL_BORROWED_REF_TYPE_FOR(RawServoSelectorList)
DEFINE_BOXED_TYPE(StyleSet, RawServoStyleSet);
DEFINE_BOXED_TYPE(SelectorList, RawServoSelectorList);
DEFINE_BOXED_TYPE(SourceSizeList, RawServoSourceSizeList);
#undef DEFINE_BOXED_TYPE

View File

@@ -495,6 +495,7 @@ structs-types = [
"RawGeckoURLExtraData",
"RawGeckoXBLBinding",
"RawServoSelectorList",
"RawServoSourceSizeList",
"RefPtr",
"RustString",
"CSSPseudoClassType",
@@ -608,6 +609,7 @@ array-types = [
servo-owned-types = [
{ name = "RawServoStyleSet", opaque = true },
{ name = "RawServoSelectorList", opaque = false },
{ name = "RawServoSourceSizeList", opaque = false },
{ name = "ServoElementSnapshot", opaque = false },
{ name = "RawServoAnimationValueMap", opaque = true },
]

View File

@@ -14,6 +14,7 @@
#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"
@@ -150,6 +151,15 @@ public:
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);