Vector<double> SnapCoordinator::snapOffsets(const ContainerNode& element, ScrollbarOrientation orientation) { const ComputedStyle* style = element.computedStyle(); const LayoutBox* snapContainer = element.layoutBox(); ASSERT(style); ASSERT(snapContainer); Vector<double> result; if (style->getScrollSnapType() == ScrollSnapTypeNone) return result; const ScrollSnapPoints& snapPoints = (orientation == HorizontalScrollbar) ? style->scrollSnapPointsX() : style->scrollSnapPointsY(); LayoutUnit clientSize = (orientation == HorizontalScrollbar) ? snapContainer->clientWidth() : snapContainer->clientHeight(); LayoutUnit scrollSize = (orientation == HorizontalScrollbar) ? snapContainer->scrollWidth() : snapContainer->scrollHeight(); 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<LayoutUnit>(repeat, LayoutUnit(1)); 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 areas 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; }