Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: third_party/WebKit/Source/core/layout/ScrollAnchor.cpp

Issue 1961243002: Round anchor offsets to DIPs in ScrollAnchor::restore. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: tweak and add comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/layout/ScrollAnchor.h" 5 #include "core/layout/ScrollAnchor.h"
6 6
7 #include "core/frame/FrameView.h" 7 #include "core/frame/FrameView.h"
8 #include "core/frame/UseCounter.h" 8 #include "core/frame/UseCounter.h"
9 #include "core/layout/LayoutView.h" 9 #include "core/layout/LayoutView.h"
10 #include "core/layout/line/InlineTextBox.h" 10 #include "core/layout/line/InlineTextBox.h"
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 } else if (layoutObject->isText()) { 82 } else if (layoutObject->isText()) {
83 // TODO(skobes): Use first and last InlineTextBox only? 83 // TODO(skobes): Use first and last InlineTextBox only?
84 for (InlineTextBox* box = toLayoutText(layoutObject)->firstTextBox(); bo x; box = box->nextTextBox()) 84 for (InlineTextBox* box = toLayoutText(layoutObject)->firstTextBox(); bo x; box = box->nextTextBox())
85 localBounds.unite(box->calculateBoundaries()); 85 localBounds.unite(box->calculateBoundaries());
86 } else { 86 } else {
87 // Only LayoutBox and LayoutText are supported. 87 // Only LayoutBox and LayoutText are supported.
88 ASSERT_NOT_REACHED(); 88 ASSERT_NOT_REACHED();
89 } 89 }
90 LayoutRect relativeBounds = LayoutRect(layoutObject->localToAncestorQuad( 90 LayoutRect relativeBounds = LayoutRect(layoutObject->localToAncestorQuad(
91 FloatRect(localBounds), scrollerLayoutBox(scroller)).boundingBox()); 91 FloatRect(localBounds), scrollerLayoutBox(scroller)).boundingBox());
92 // When the scroller is the FrameView, localToAncestorQuad returns document coords,
93 // so we must subtract scroll offset to get viewport coords. We discard the fractional
94 // part of the scroll offset so that the rounding in restore() matches the s napping of
95 // the anchor node to the pixel grid of the layer it paints into. For non-Fr ameView
96 // scrollers, we rely on the flooring behavior of LayoutBox::scrolledContent Offset.
92 if (scroller->isFrameView()) 97 if (scroller->isFrameView())
93 relativeBounds.moveBy(-LayoutPoint(scroller->scrollPositionDouble())); 98 relativeBounds.moveBy(-flooredIntPoint(scroller->scrollPositionDouble()) );
eae 2016/05/10 23:09:18 We round scroll offsets in PaintLayerScrollableAre
skobes 2016/05/10 23:19:00 It's somewhat more subtle. For the return value o
94 return relativeBounds; 99 return relativeBounds;
95 } 100 }
96 101
97 static LayoutPoint computeRelativeOffset(const LayoutObject* layoutObject, const ScrollableArea* scroller, Corner corner) 102 static LayoutPoint computeRelativeOffset(const LayoutObject* layoutObject, const ScrollableArea* scroller, Corner corner)
98 { 103 {
99 return cornerPointOfRect(relativeBounds(layoutObject, scroller), corner); 104 return cornerPointOfRect(relativeBounds(layoutObject, scroller), corner);
100 } 105 }
101 106
102 static bool candidateMovesWithScroller(const LayoutObject* candidate, const Scro llableArea* scroller) 107 static bool candidateMovesWithScroller(const LayoutObject* candidate, const Scro llableArea* scroller)
103 { 108 {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 179
175 m_anchorObject->setIsScrollAnchorObject(); 180 m_anchorObject->setIsScrollAnchorObject();
176 m_savedRelativeOffset = computeRelativeOffset(m_anchorObject, m_scroller, m_ corner); 181 m_savedRelativeOffset = computeRelativeOffset(m_anchorObject, m_scroller, m_ corner);
177 } 182 }
178 183
179 void ScrollAnchor::restore() 184 void ScrollAnchor::restore()
180 { 185 {
181 if (!m_anchorObject) 186 if (!m_anchorObject)
182 return; 187 return;
183 188
184 LayoutSize adjustment = computeRelativeOffset(m_anchorObject, m_scroller, m_ corner) - m_savedRelativeOffset; 189 // The anchor node can report fractional positions, but it is DIP-snapped wh en
190 // painting (crbug.com/610805), so we must round the offsets to determine th e
191 // visual delta. If we scroll by the delta in LayoutUnits, the snapping of t he
192 // anchor node may round differently from the snapping of the scroll positio n.
193 // (For example, anchor moving from 2.4px -> 2.6px is really 2px -> 3px, so we
194 // should scroll by 1px instead of 0.2px.) This is true regardless of whethe r
195 // the ScrollableArea actually uses fractional scroll positions.
196 IntSize adjustment =
197 roundedIntSize(computeRelativeOffset(m_anchorObject, m_scroller, m_corne r)) -
198 roundedIntSize(m_savedRelativeOffset);
185 if (!adjustment.isZero()) { 199 if (!adjustment.isZero()) {
200 DoublePoint desiredPos = m_scroller->scrollPositionDouble() + adjustment ;
186 ScrollAnimatorBase* animator = m_scroller->existingScrollAnimator(); 201 ScrollAnimatorBase* animator = m_scroller->existingScrollAnimator();
187 if (!animator || !animator->hasRunningAnimation()) { 202 if (!animator || !animator->hasRunningAnimation()) {
188 m_scroller->setScrollPosition( 203 m_scroller->setScrollPosition(desiredPos, AnchoringScroll);
189 m_scroller->scrollPositionDouble() + DoubleSize(adjustment),
190 AnchoringScroll);
191 } else { 204 } else {
192 // If in the middle of a scroll animation, stop the animation, make 205 // If in the middle of a scroll animation, stop the animation, make
193 // the adjustment, and continue the animation on the pending delta. 206 // the adjustment, and continue the animation on the pending delta.
194 FloatSize pendingDelta = animator->desiredTargetPosition() - FloatPo int(m_scroller->scrollPositionDouble()); 207 FloatSize pendingDelta = animator->desiredTargetPosition() - FloatPo int(m_scroller->scrollPositionDouble());
195 animator->cancelAnimation(); 208 animator->cancelAnimation();
196 m_scroller->setScrollPosition( 209 m_scroller->setScrollPosition(desiredPos, AnchoringScroll);
197 m_scroller->scrollPositionDouble() + DoubleSize(adjustment),
198 AnchoringScroll);
199 animator->userScroll(ScrollByPixel, pendingDelta); 210 animator->userScroll(ScrollByPixel, pendingDelta);
200 } 211 }
201 // Update UMA metric. 212 // Update UMA metric.
202 DEFINE_STATIC_LOCAL(EnumerationHistogram, adjustedOffsetHistogram, 213 DEFINE_STATIC_LOCAL(EnumerationHistogram, adjustedOffsetHistogram,
203 ("Layout.ScrollAnchor.AdjustedScrollOffset", 2)); 214 ("Layout.ScrollAnchor.AdjustedScrollOffset", 2));
204 adjustedOffsetHistogram.count(1); 215 adjustedOffsetHistogram.count(1);
205 UseCounter::count(scrollerLayoutBox(m_scroller)->document(), UseCounter: :ScrollAnchored); 216 UseCounter::count(scrollerLayoutBox(m_scroller)->document(), UseCounter: :ScrollAnchored);
206 } 217 }
207 } 218 }
208 219
209 void ScrollAnchor::clear() 220 void ScrollAnchor::clear()
210 { 221 {
211 LayoutObject* anchorObject = m_anchorObject; 222 LayoutObject* anchorObject = m_anchorObject;
212 m_anchorObject = nullptr; 223 m_anchorObject = nullptr;
213 224
214 if (anchorObject) 225 if (anchorObject)
215 anchorObject->maybeClearIsScrollAnchorObject(); 226 anchorObject->maybeClearIsScrollAnchorObject();
216 } 227 }
217 228
218 } // namespace blink 229 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698