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

Unified Diff: third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp

Issue 1188563005: Compute snap offsets (both repeat and element based) (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fix compile issue Created 5 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp
diff --git a/third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7f5ea7f9b39cae494b091e7d4efaa8805484f890
--- /dev/null
+++ b/third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp
@@ -0,0 +1,168 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "SnapCoordinator.h"
+
+#include "core/dom/Element.h"
+#include "core/dom/Node.h"
+#include "core/dom/NodeComputedStyle.h"
+#include "core/layout/LayoutBlock.h"
+#include "core/layout/LayoutBox.h"
+#include "core/style/ComputedStyle.h"
+#include "platform/LengthFunctions.h"
+
+namespace blink {
+
+SnapCoordinator::SnapCoordinator()
+ : m_snapContainers()
+{
+}
+
+SnapCoordinator::~SnapCoordinator() { }
+
+PassOwnPtrWillBeRawPtr<SnapCoordinator> SnapCoordinator::create()
+{
+ return adoptPtrWillBeNoop(new SnapCoordinator());
+}
+
+void SnapCoordinator::snapAreaDidChange(LayoutBox& snapArea, const Vector<LengthPoint>& snapCoordinates)
+{
+ if (snapCoordinates.isEmpty()) {
+ snapArea.setSnapContainer(nullptr);
+ } else {
+ LayoutBox* snapContainer = findSnapContainer(snapArea);
+ if (snapContainer) {
+ snapArea.setSnapContainer(snapContainer);
+ } else {
+ // TODO(majidvp): keep track of snap elements that do not have any
+ // container so that we check them again when a new container is
+ // added to the page.
+ }
+ }
+}
+
+void SnapCoordinator::snapContainerDidChange(LayoutBox& snapContainer, ScrollSnapType scrollSnapType)
+{
+
esprehn 2015/12/01 18:31:11 Remove empty line here
majidvp 2015/12/03 17:54:16 Done.
+ if (scrollSnapType == ScrollSnapTypeNone) {
+ // TODO(majidvp): Track and report these removals to CompositorWorker
+ // instance responsible for snapping
+ m_snapContainers.remove(&snapContainer);
+ } else {
+ m_snapContainers.add(&snapContainer);
esprehn 2015/12/01 18:31:11 remove this map, it's not used outside debug code
majidvp 2015/12/03 17:54:17 At the moment it is for debug only but I am planni
+ }
+
+ // TODO(majidvp): Add logic to correctly handle orphaned snap areas here.
+ // 1. Removing container: find a new snap container for its orphan snap
+ // areas (most likely nearest ancestor of current container) otherwise add
+ // them to an orphan list.
+ // 2. Adding container: may take over snap areas from nearest ancestor snap
+ // container or from existing areas in orphan pool.
+}
+
+static bool isSnapContainer(const ComputedStyle* style)
+{
+ return style && style->scrollSnapType() != ScrollSnapTypeNone;
+}
+
+LayoutBox* SnapCoordinator::findSnapContainer(const LayoutBox& snapArea)
+{
+ LayoutBox* curBox = snapArea.enclosingBox();
esprehn 2015/12/01 18:31:11 box, you're also mixing concepts here of containin
majidvp 2015/12/03 17:54:17 The spec talks about "the nearest ancestor (on the
+ while (curBox) {
+ if (isSnapContainer(curBox->style())) {
esprehn 2015/12/01 18:31:11 style() can't be null, you don't need the null che
majidvp 2015/12/03 17:54:17 I have modified the logic to match your recommenda
+ // TODO(majidvp): upcoming spec change will require "scroll-snap-
+ // points: elements" to be present as well
+ return curBox;
+ }
+ curBox = curBox->containingBlock();
+ }
+
+ return nullptr;
+}
+
+// Translate local snap coordinates into snap container space
+Vector<FloatPoint> localToContainerSnapCoordinates(const LayoutBox& containerBox, const LayoutBox& snapArea)
+{
+ Vector<FloatPoint> result;
+ LayoutPoint scrollOffset(containerBox.scrollLeft(), containerBox.scrollTop());
+
+ const Vector<LengthPoint>& snapCoordinates = snapArea.style()->scrollSnapCoordinate();
+ for (auto& coordinate : snapCoordinates) {
+ FloatPoint localPoint = floatPointForLengthPoint(coordinate, FloatSize(snapArea.size()));
+ FloatPoint containerPoint = snapArea.localToContainerPoint(localPoint, &containerBox);
+ containerPoint.moveBy(scrollOffset);
+ result.append(containerPoint);
+ }
+ return result;
+}
+
+Vector<double> SnapCoordinator::snapOffsets(const Element& element, ScrollbarOrientation orientation)
+{
+ const ComputedStyle* style = element.computedStyle();
+ const LayoutBox* snapContainer = element.layoutBox();
+ ASSERT(style);
+ ASSERT(snapContainer);
+
+ const ScrollSnapPoints& snapPoints = (orientation == HorizontalScrollbar) ? style->scrollSnapPointsX() : style->scrollSnapPointsY();
+
+ Vector<double> result;
+ LayoutUnit clientSize = (orientation == HorizontalScrollbar) ? snapContainer->clientWidth(): snapContainer->clientHeight();
esprehn 2015/12/01 18:31:11 missing space before :
majidvp 2015/12/03 17:54:17 Done.
+ LayoutUnit scrollSize = (orientation == HorizontalScrollbar) ? snapContainer->scrollWidth(): snapContainer->scrollHeight();
esprehn 2015/12/01 18:31:11 ditto
majidvp 2015/12/03 17:54:16 Done.
+
+ if (snapPoints.hasRepeat) {
+ LayoutUnit repeat = valueForLength(snapPoints.repeatOffset, clientSize);
+
+ // calc() values may be negative or zero in which case we clamp them to 1px
+ // See: https://lists.w3.org/Archives/Public/www-style/2015Jul/0075.html
+ repeat = std::max(repeat, LayoutUnit(1));
esprehn 2015/12/01 18:31:11 we often write: std::max<LayoutUnit>(a, b) inste
majidvp 2015/12/03 17:54:16 Updated to match expected style.
+ for (LayoutUnit offset = repeat; offset <= (scrollSize - clientSize); offset += repeat) {
+ result.append(offset.toFloat());
+ }
+ }
+
+ // Compute element-based snap points by mapping the snap coordinates from snap element to snap container
+ bool didAddSnapAreaOffset = false;
+ if (SnapAreaSet* snapAreas = snapContainer->snapAreas()) {
+ for (auto& snapArea : *snapAreas) {
+ Vector<FloatPoint> snapCoordinates = localToContainerSnapCoordinates(*snapContainer, *snapArea);
+ for (const FloatPoint& snapCoordinate : snapCoordinates) {
+ float snapOffset = (orientation == HorizontalScrollbar) ? snapCoordinate.x() : snapCoordinate.y();
+ if (snapOffset > scrollSize - clientSize)
+ continue;
+ result.append(snapOffset);
+ didAddSnapAreaOffset = true;
+ }
+ }
+ }
+
+ if (didAddSnapAreaOffset)
+ std::sort(result.begin(), result.end());
+
+ return result;
+}
+
+#ifndef NDEBUG
+
+void SnapCoordinator::showSnapAreaMap()
+{
+ for (auto& container : m_snapContainers)
esprehn 2015/12/01 18:31:11 nothing uses this set except your debug code, why
majidvp 2015/12/03 17:54:17 Explained above that I expect to use this in upcom
+ showSnapAreasFor(container);
+}
+
+void SnapCoordinator::showSnapAreasFor(const LayoutBox* container)
+{
+ const char* prefix = " ";
+ container->node()->showNodePathForThis();
+ if (SnapAreaSet* snapAreas = container->snapAreas()) {
+ for (auto& snapArea : *snapAreas) {
+ snapArea->node()->showNode(prefix);
+ }
+ }
+}
+
+#endif
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698