diff --git a/dom/html/test/test_bug332246.html b/dom/html/test/test_bug332246.html
index 3891db995bf7..e1acbe3096fd 100644
--- a/dom/html/test/test_bug332246.html
+++ b/dom/html/test/test_bug332246.html
@@ -37,9 +37,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=332246
/** Test for Bug 332246 **/
+function isWithFuzz(itIs, itShouldBe, fuzz, description) {
+ ok(Math.abs(itIs - itShouldBe) <= fuzz, `${description} - expected a value between ${itShouldBe - fuzz} and ${itShouldBe + fuzz}, got ${itIs}`);
+}
+
var a1 = document.getElementById('a1');
var a2 = document.getElementById('a2');
-is(a1.scrollHeight, 400, "Wrong a1.scrollHeight");
+isWithFuzz(a1.scrollHeight, 400, 1, "Wrong a1.scrollHeight");
is(a1.offsetHeight, 100, "Wrong a1.offsetHeight");
a2.scrollIntoView(true);
is(a1.scrollTop, 100, "Wrong scrollTop value after a2.scrollIntoView(true)");
@@ -48,7 +52,7 @@ is(a1.scrollTop, 200, "Wrong scrollTop value after a2.scrollIntoView(false)");
var b1 = document.getElementById('b1');
var b2 = document.getElementById('b2');
-is(b1.scrollHeight, 420, "Wrong b1.scrollHeight");
+isWithFuzz(b1.scrollHeight, 420, 1, "Wrong b1.scrollHeight");
is(b1.offsetHeight, 100, "Wrong b1.offsetHeight");
b2.scrollIntoView(true);
is(b1.scrollTop, 100, "Wrong scrollTop value after b2.scrollIntoView(true)");
@@ -57,12 +61,12 @@ is(b1.scrollTop, 220, "Wrong scrollTop value after b2.scrollIntoView(false)");
var c1 = document.getElementById('c1');
var c2 = document.getElementById('c2');
-is(c1.scrollHeight, 320, "Wrong c1.scrollHeight");
+isWithFuzz(c1.scrollHeight, 320, 1, "Wrong c1.scrollHeight");
is(c1.offsetHeight, 100, "Wrong c1.offsetHeight");
c2.scrollIntoView(true);
is(c1.scrollTop, 100, "Wrong scrollTop value after c2.scrollIntoView(true)");
c2.scrollIntoView(false);
-is(c1.scrollTop, 220, "Wrong scrollTop value after c2.scrollIntoView(false)");
+isWithFuzz(c1.scrollTop, 220, 1, "Wrong scrollTop value after c2.scrollIntoView(false)");
diff --git a/dom/tests/mochitest/general/test_offsets.html b/dom/tests/mochitest/general/test_offsets.html
index 144eafd90861..2926ac447290 100644
--- a/dom/tests/mochitest/general/test_offsets.html
+++ b/dom/tests/mochitest/general/test_offsets.html
@@ -12,8 +12,12 @@
}
+
+
+ style="margin: 1px; border: 2px solid black; padding: 4px; transform: translateY(1px);">
One
Two
diff --git a/dom/tests/mochitest/general/test_offsets.js b/dom/tests/mochitest/general/test_offsets.js
index 71c515f458b8..509daff8c77a 100644
--- a/dom/tests/mochitest/general/test_offsets.js
+++ b/dom/tests/mochitest/general/test_offsets.js
@@ -181,12 +181,25 @@ function checkCoord(element, type, val, testname)
is(element[type], Math.round(val), testname + " " + type);
}
+function checkCoordFuzzy(element, type, val, fuzz, testname)
+{
+ if (val != -10000)
+ ok(Math.abs(element[type] - Math.round(val)) <= fuzz, testname + " " + type);
+}
+
function checkCoords(element, type, left, top, width, height, testname)
{
checkCoord(element, type + "Left", left, testname);
checkCoord(element, type + "Top", top, testname);
- checkCoord(element, type + "Width", width, testname);
- checkCoord(element, type + "Height", height, testname);
+
+ if (type == "scroll") {
+ // scrollWidth and scrollHeight can deviate by 1 pixel due to snapping.
+ checkCoordFuzzy(element, type + "Width", width, 1, testname);
+ checkCoordFuzzy(element, type + "Height", height, 1, testname);
+ } else {
+ checkCoord(element, type + "Width", width, testname);
+ checkCoord(element, type + "Height", height, testname);
+ }
if (element instanceof SVGElement)
return;
diff --git a/gfx/src/nsRect.cpp b/gfx/src/nsRect.cpp
index 562eb67cbc33..c17c249b2ecd 100644
--- a/gfx/src/nsRect.cpp
+++ b/gfx/src/nsRect.cpp
@@ -5,6 +5,7 @@
#include "nsRect.h"
#include "mozilla/gfx/Types.h" // for NS_SIDE_BOTTOM, etc
+#include "mozilla/CheckedInt.h" // for CheckedInt
#include "nsDeviceContext.h" // for nsDeviceContext
#include "nsString.h" // for nsAutoString, etc
#include "nsMargin.h" // for nsMargin
@@ -20,6 +21,19 @@ const mozilla::gfx::IntRect& GetMaxSizedIntRect() {
return r;
}
+
+bool nsRect::Overflows() const {
+#ifdef NS_COORD_IS_FLOAT
+ return false;
+#else
+ mozilla::CheckedInt
xMost = this->x;
+ xMost += this->width;
+ mozilla::CheckedInt yMost = this->y;
+ yMost += this->height;
+ return !xMost.isValid() || !yMost.isValid();
+#endif
+}
+
#ifdef DEBUG
// Diagnostics
diff --git a/gfx/src/nsRect.h b/gfx/src/nsRect.h
index 178ab0b1f1f7..267f5849cbd7 100644
--- a/gfx/src/nsRect.h
+++ b/gfx/src/nsRect.h
@@ -129,6 +129,9 @@ struct nsRect :
*this = aRect1.SaturatingUnionEdges(aRect2);
}
+ // Return whether this rect's right or bottom edge overflow int32.
+ bool Overflows() const;
+
/**
* Return this rect scaled to a different appunits per pixel (APP) ratio.
* In the RoundOut version we make the rect the smallest rect containing the
diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp
index f5be8b1dfa0d..06fb8a79256c 100644
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3701,7 +3701,7 @@ ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem,
}
nsIFrame* scrollFrame = do_QueryFrame(sf);
displayport += scrollFrame->GetOffsetToCrossDoc(mContainerReferenceFrame);
- if (opaque.Contains(displayport)) {
+ if (opaquePixels.Contains(ScaleRegionToNearestPixels(displayport))) {
*aOpaqueForAnimatedGeometryRootParent = true;
}
}
diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp
index 9867a8149208..0cad0fa2f7ba 100644
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -390,8 +390,8 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowInput* aState,
if (!aForce) {
nsRect scrolledRect =
- mHelper.GetScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(),
- scrollPortSize);
+ mHelper.GetUnsnappedScrolledRectInternal(aState->mContentsOverflowAreas.ScrollableOverflow(),
+ scrollPortSize);
nscoord oneDevPixel = aState->mBoxState.PresContext()->DevPixelsToAppUnits(1);
// If the style is HIDDEN then we already know that aAssumeHScroll is false
@@ -686,8 +686,8 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowInput* aState,
ComputeInsideBorderSize(aState,
nsSize(kidDesiredSize.Width(), kidDesiredSize.Height()));
nsRect scrolledRect =
- mHelper.GetScrolledRectInternal(kidDesiredSize.ScrollableOverflow(),
- insideBorderSize);
+ mHelper.GetUnsnappedScrolledRectInternal(kidDesiredSize.ScrollableOverflow(),
+ insideBorderSize);
if (nsRect(nsPoint(0, 0), insideBorderSize).Contains(scrolledRect)) {
// Let's pretend we had no scrollbars coming in here
ReflowScrolledFrame(aState, false, false, &kidDesiredSize, false);
@@ -738,8 +738,8 @@ nsHTMLScrollFrame::PlaceScrollArea(const ScrollReflowInput& aState,
// Preserve the width or height of empty rects
nsSize portSize = mHelper.mScrollPort.Size();
nsRect scrolledRect =
- mHelper.GetScrolledRectInternal(aState.mContentsOverflowAreas.ScrollableOverflow(),
- portSize);
+ mHelper.GetUnsnappedScrolledRectInternal(aState.mContentsOverflowAreas.ScrollableOverflow(),
+ portSize);
scrolledArea.UnionRectEdges(scrolledRect,
nsRect(nsPoint(0,0), portSize));
@@ -3306,7 +3306,13 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
MOZ_ASSERT(!inactiveScrollClip->mIsAsyncScrollable);
}
- DisplayListClipState::AutoSaveRestore displayPortClipState(aBuilder);
+ // Clip our contents to the unsnapped scrolled rect. This makes sure that
+ // we don't have display items over the subpixel seam at the edge of the
+ // scrolled area.
+ DisplayListClipState::AutoSaveRestore scrolledRectClipState(aBuilder);
+ nsRect scrolledRectClip =
+ GetUnsnappedScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
+ mScrollPort.Size()) + mScrolledFrame->GetPosition();
if (usingDisplayPort) {
// Clip the contents to the display port.
// The dirty rect already acts kind of like a clip, in that
@@ -3324,8 +3330,10 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// pixels.
// If there is no display port, we don't need this because the clip
// from the scroll port is still applied.
- displayPortClipState.ClipContainingBlockDescendants(dirtyRect + aBuilder->ToReferenceFrame(mOuter));
+ scrolledRectClip = scrolledRectClip.Intersect(dirtyRect);
}
+ scrolledRectClipState.ClipContainingBlockDescendants(
+ scrolledRectClip + aBuilder->ToReferenceFrame(mOuter));
mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent);
}
@@ -5566,12 +5574,19 @@ ScrollFrameHelper::GetBorderRadii(const nsSize& aFrameSize,
return true;
}
+static nscoord
+SnapCoord(nscoord aCoord, double aRes, nscoord aAppUnitsPerPixel)
+{
+ double snappedToLayerPixels = NS_round((aRes*aCoord)/aAppUnitsPerPixel);
+ return NSToCoordRoundWithClamp(snappedToLayerPixels*aAppUnitsPerPixel/aRes);
+}
+
nsRect
ScrollFrameHelper::GetScrolledRect() const
{
nsRect result =
- GetScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
- mScrollPort.Size());
+ GetUnsnappedScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
+ mScrollPort.Size());
if (result.width < mScrollPort.width) {
NS_WARNING("Scrolled rect smaller than scrollport?");
@@ -5579,30 +5594,82 @@ ScrollFrameHelper::GetScrolledRect() const
if (result.height < mScrollPort.height) {
NS_WARNING("Scrolled rect smaller than scrollport?");
}
+
+ // Expand / contract the result by up to half a layer pixel so that scrolling
+ // to the right / bottom edge does not change the layer pixel alignment of
+ // the scrolled contents.
+ // For that, we first convert the scroll port and the scrolled rect to rects
+ // relative to the reference frame, since that's the space where painting does
+ // snapping.
+ nsSize scrollPortSize = GetScrollPositionClampingScrollPortSize();
+ nsIFrame* referenceFrame = nsLayoutUtils::GetReferenceFrame(mOuter);
+ nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(referenceFrame);
+ nsRect scrollPort(mScrollPort.TopLeft() + toReferenceFrame, scrollPortSize);
+ nsRect scrolledRect = result + scrollPort.TopLeft();
+
+ if (scrollPort.Overflows() || scrolledRect.Overflows()) {
+ return result;
+ }
+
+ // Now, snap the bottom right corner of both of these rects.
+ // We snap to layer pixels, so we need to respect the layer's scale.
+ nscoord appUnitsPerDevPixel = mScrolledFrame->PresContext()->AppUnitsPerDevPixel();
+ gfxSize scale = FrameLayerBuilder::GetPaintedLayerScaleForFrame(mScrolledFrame);
+ if (scale.IsEmpty()) {
+ scale = gfxSize(1.0f, 1.0f);
+ }
+
+ // Compute bounds for the scroll position, and computed the snapped scrolled
+ // rect from the scroll position bounds.
+ nscoord snappedScrolledAreaBottom = SnapCoord(scrolledRect.YMost(), scale.height, appUnitsPerDevPixel);
+ nscoord snappedScrollPortBottom = SnapCoord(scrollPort.YMost(), scale.height, appUnitsPerDevPixel);
+ nscoord maximumScrollOffsetY = snappedScrolledAreaBottom - snappedScrollPortBottom;
+ result.SetBottomEdge(scrollPort.height + maximumScrollOffsetY);
+
+ if (GetScrolledFrameDir() == NS_STYLE_DIRECTION_LTR) {
+ nscoord snappedScrolledAreaRight = SnapCoord(scrolledRect.XMost(), scale.width, appUnitsPerDevPixel);
+ nscoord snappedScrollPortRight = SnapCoord(scrollPort.XMost(), scale.width, appUnitsPerDevPixel);
+ nscoord maximumScrollOffsetX = snappedScrolledAreaRight - snappedScrollPortRight;
+ result.SetRightEdge(scrollPort.width + maximumScrollOffsetX);
+ } else {
+ // In RTL, the scrolled area's right edge is at scrollPort.XMost(),
+ // and the scrolled area's x position is zero or negative. We want
+ // the right edge to stay flush with the scroll port, so we snap the
+ // left edge.
+ nscoord snappedScrolledAreaLeft = SnapCoord(scrolledRect.x, scale.width, appUnitsPerDevPixel);
+ nscoord snappedScrollPortLeft = SnapCoord(scrollPort.x, scale.width, appUnitsPerDevPixel);
+ nscoord minimumScrollOffsetX = snappedScrolledAreaLeft - snappedScrollPortLeft;
+ result.SetLeftEdge(minimumScrollOffsetX);
+ }
+
return result;
}
-nsRect
-ScrollFrameHelper::GetScrolledRectInternal(const nsRect& aScrolledFrameOverflowArea,
- const nsSize& aScrollPortSize) const
-{
- uint8_t frameDir = IsLTR() ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
+uint8_t
+ScrollFrameHelper::GetScrolledFrameDir() const
+{
// If the scrolled frame has unicode-bidi: plaintext, the paragraph
// direction set by the text content overrides the direction of the frame
if (mScrolledFrame->StyleTextReset()->mUnicodeBidi &
NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
nsIFrame* childFrame = mScrolledFrame->PrincipalChildList().FirstChild();
if (childFrame) {
- frameDir =
- (nsBidiPresUtils::ParagraphDirection(childFrame) == NSBIDI_LTR)
+ return (nsBidiPresUtils::ParagraphDirection(childFrame) == NSBIDI_LTR)
? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
}
}
+ return IsLTR() ? NS_STYLE_DIRECTION_LTR : NS_STYLE_DIRECTION_RTL;
+}
+
+nsRect
+ScrollFrameHelper::GetUnsnappedScrolledRectInternal(const nsRect& aScrolledFrameOverflowArea,
+ const nsSize& aScrollPortSize) const
+{
return nsLayoutUtils::GetScrolledRect(mScrolledFrame,
aScrolledFrameOverflowArea,
- aScrollPortSize, frameDir);
+ aScrollPortSize, GetScrolledFrameDir());
}
nsMargin
diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h
index a1339cd3097e..dfee0e24753a 100644
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -308,7 +308,7 @@ public:
nsRect GetScrolledRect() const;
/**
- * GetScrolledRectInternal is designed to encapsulate deciding which
+ * GetUnsnappedScrolledRectInternal is designed to encapsulate deciding which
* directions of overflow should be reachable by scrolling and which
* should not. Callers should NOT depend on it having any particular
* behavior (although nsXULScrollFrame currently does).
@@ -318,8 +318,8 @@ public:
* nsXULScrollFrames, and allows scrolling down and to the left for
* nsHTMLScrollFrames with RTL directionality.
*/
- nsRect GetScrolledRectInternal(const nsRect& aScrolledOverflowArea,
- const nsSize& aScrollPortSize) const;
+ nsRect GetUnsnappedScrolledRectInternal(const nsRect& aScrolledOverflowArea,
+ const nsSize& aScrollPortSize) const;
uint32_t GetScrollbarVisibility() const {
return (mHasVerticalScrollbar ? nsIScrollableFrame::VERTICAL : 0) |
@@ -622,6 +622,7 @@ protected:
bool HasPluginFrames();
bool HasPerspective() const;
bool HasBgAttachmentLocal() const;
+ uint8_t GetScrolledFrameDir() const;
static void EnsureFrameVisPrefsCached();
static bool sFrameVisPrefsCached;
diff --git a/layout/generic/test/test_bug784410.html b/layout/generic/test/test_bug784410.html
index 133435107b2e..efaf6f943071 100644
--- a/layout/generic/test/test_bug784410.html
+++ b/layout/generic/test/test_bug784410.html
@@ -9,7 +9,7 @@
-
+
diff --git a/layout/generic/test/test_bug791616.html b/layout/generic/test/test_bug791616.html
index 5443c90c1df5..e2816ea735b3 100644
--- a/layout/generic/test/test_bug791616.html
+++ b/layout/generic/test/test_bug791616.html
@@ -11,7 +11,7 @@
position: absolute;
left: 200px;
top: 100px;
- font: 14px/1.1em "Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;
+ font: 14px/1.3em "Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;
}
diff --git a/layout/reftests/scrolling/fractional-scroll-area-invalidation.html b/layout/reftests/scrolling/fractional-scroll-area-invalidation.html
new file mode 100644
index 000000000000..2b20f160cddc
--- /dev/null
+++ b/layout/reftests/scrolling/fractional-scroll-area-invalidation.html
@@ -0,0 +1,59 @@
+
+
+
+
Make sure the scrolled layer is not invalidated when you scroll all the way to the bottom
+
+
+
+
+
+
+
+
diff --git a/layout/reftests/scrolling/fractional-scroll-area.html b/layout/reftests/scrolling/fractional-scroll-area.html
new file mode 100644
index 000000000000..cba421499ca5
--- /dev/null
+++ b/layout/reftests/scrolling/fractional-scroll-area.html
@@ -0,0 +1,74 @@
+
+
+
+
Fractional scroll area position / size
+
+
+
+
+
+
diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list
index 646050585bc9..6ee6bbacdd0b 100644
--- a/layout/reftests/scrolling/reftest.list
+++ b/layout/reftests/scrolling/reftest.list
@@ -36,3 +36,52 @@ skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,
== frame-scrolling-attr-1.html frame-scrolling-attr-ref.html
fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2420) == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html
== move-item.html move-item-ref.html # bug 1125750
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=199.6 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200.4 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=199.6&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+== fractional-scroll-area.html?top=0.4&outerBottom=100.4&innerBottom=200.4&scrollBefore=999 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200&scrollBefore=999
+!= fractional-scroll-area-invalidation.html about:blank
diff --git a/layout/reftests/text-overflow/reftest.list b/layout/reftests/text-overflow/reftest.list
index 8b3f45b24689..5df0e8ec8d17 100644
--- a/layout/reftests/text-overflow/reftest.list
+++ b/layout/reftests/text-overflow/reftest.list
@@ -22,7 +22,7 @@ skip-if(B2G||Mulet) HTTP(..) == table-cell.html table-cell-ref.html # Initial mu
skip-if(Mulet) fuzzy-if(gtkWidget,10,32) HTTP(..) == two-value-syntax.html two-value-syntax-ref.html # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables
skip-if(B2G||Mulet) HTTP(..) == single-value.html single-value-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(gtkWidget,10,2) HTTP(..) == atomic-under-marker.html atomic-under-marker-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
-fuzzy(1,702) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
+fuzzy(1,2616) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == combobox-zoom.html combobox-zoom-ref.html
# The vertical-text pref setting can be removed after bug 1138384 lands