Пример #1
0
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;
}