| Index: third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
|
| diff --git a/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp b/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..70f345ec26a97baad6839827cf5cd1e70a54a9d9
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp
|
| @@ -0,0 +1,148 @@
|
| +// Copyright 2017 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 "core/animation/ScrollTimeline.h"
|
| +
|
| +#include "core/dom/ExceptionCode.h"
|
| +#include "core/layout/LayoutBox.h"
|
| +#include "core/paint/PaintLayerScrollableArea.h"
|
| +
|
| +namespace blink {
|
| +
|
| +namespace {
|
| +bool StringToScrollDirection(String scroll_direction,
|
| + ScrollTimeline::ScrollDirection& result) {
|
| + // TODO(smcgruer): Support 'auto' value.
|
| + if (scroll_direction == "block") {
|
| + result = ScrollTimeline::Block;
|
| + return true;
|
| + }
|
| + if (scroll_direction == "inline") {
|
| + result = ScrollTimeline::Inline;
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +} // namespace
|
| +
|
| +ScrollTimeline* ScrollTimeline::Create(Document& document,
|
| + ScrollTimelineOptions options,
|
| + ExceptionState& exception_state) {
|
| + Element* scroll_source = options.scrollSource() ? options.scrollSource()
|
| + : document.scrollingElement();
|
| +
|
| + ScrollDirection orientation;
|
| + if (!StringToScrollDirection(options.orientation(), orientation)) {
|
| + exception_state.ThrowDOMException(kNotSupportedError,
|
| + "Invalid orientation");
|
| + return nullptr;
|
| + }
|
| +
|
| + // TODO(smcgruer): Support 'auto' value.
|
| + if (options.timeRange().isScrollTimelineAutoKeyword()) {
|
| + exception_state.ThrowDOMException(
|
| + kNotSupportedError, "'auto' value for timeRange not yet supported");
|
| + return nullptr;
|
| + }
|
| +
|
| + return new ScrollTimeline(document, scroll_source, orientation,
|
| + options.timeRange().getAsDouble());
|
| +}
|
| +
|
| +ScrollTimeline::ScrollTimeline(const Document& document,
|
| + Element* scroll_source,
|
| + ScrollDirection orientation,
|
| + double time_range)
|
| + : scroll_source_(scroll_source),
|
| + orientation_(orientation),
|
| + time_range_(time_range) {
|
| + DCHECK(RuntimeEnabledFeatures::CompositorWorkerEnabled());
|
| +}
|
| +
|
| +double ScrollTimeline::currentTime(bool& is_null) {
|
| + // 1. If scrollSource does not currently have a CSS layout box, or if its
|
| + // layout box is not a scroll container, return an unresolved time value.
|
| + LayoutBox* layout_box = scroll_source_->GetLayoutBox();
|
| + if (!layout_box || !layout_box->HasOverflowClip()) {
|
| + is_null = false;
|
| + return std::numeric_limits<double>::quiet_NaN();
|
| + }
|
| +
|
| + // 2. Otherwise, let current scroll offset be the current scroll offset of
|
| + // scrollSource in the direction specified by orientation.
|
| +
|
| + // Depending on the writing-mode and direction, the scroll origin shifts and
|
| + // the scroll offset may be negative. The easiest way to deal with this is to
|
| + // use only the magnitude of the scroll offset, and compare it to (max-offset
|
| + // - min_offset).
|
| + PaintLayerScrollableArea* scrollable_area = layout_box->GetScrollableArea();
|
| + // Using the absolute value of the scroll offset only makes sense if either
|
| + // the max or min scroll offset for a given axis is 0. This should be
|
| + // guaranteed by the scroll origin code, but these DCHECKs ensure that.
|
| + DCHECK(scrollable_area->MaximumScrollOffset().Height() == 0 ||
|
| + scrollable_area->MinimumScrollOffset().Height() == 0);
|
| + DCHECK(scrollable_area->MaximumScrollOffset().Width() == 0 ||
|
| + scrollable_area->MinimumScrollOffset().Width() == 0);
|
| + ScrollOffset scroll_offset = scrollable_area->GetScrollOffset();
|
| + ScrollOffset scroll_dimensions = scrollable_area->MaximumScrollOffset() -
|
| + scrollable_area->MinimumScrollOffset();
|
| +
|
| + double current_offset;
|
| + double max_offset;
|
| + bool is_horizontal = layout_box->IsHorizontalWritingMode();
|
| + if (orientation_ == Block) {
|
| + current_offset =
|
| + is_horizontal ? scroll_offset.Height() : scroll_offset.Width();
|
| + max_offset =
|
| + is_horizontal ? scroll_dimensions.Height() : scroll_dimensions.Width();
|
| + } else {
|
| + current_offset =
|
| + is_horizontal ? scroll_offset.Width() : scroll_offset.Height();
|
| + max_offset =
|
| + is_horizontal ? scroll_dimensions.Width() : scroll_dimensions.Height();
|
| + }
|
| +
|
| + // 3. If current scroll offset is less than startScrollOffset, return an
|
| + // unresolved time value if fill is none or forwards, or 0 otherwise.
|
| + // TODO(smcgruer): Implement |startScrollOffset| and |fill|.
|
| +
|
| + // 4. If current scroll offset is greater than or equal to endScrollOffset,
|
| + // return an unresolved time value if fill is none or backwards, or the
|
| + // effective time range otherwise.
|
| + // TODO(smcgruer): Implement |endScrollOffset| and |fill|.
|
| +
|
| + // 5. Return the result of evaluating the following expression:
|
| + // ((current scroll offset - startScrollOffset) /
|
| + // (endScrollOffset - startScrollOffset)) * effective time range
|
| +
|
| + is_null = false;
|
| + return (std::abs(current_offset) / max_offset) * time_range_;
|
| +}
|
| +
|
| +Element* ScrollTimeline::scrollSource() {
|
| + return scroll_source_.Get();
|
| +}
|
| +
|
| +String ScrollTimeline::orientation() {
|
| + switch (orientation_) {
|
| + case Block:
|
| + return "block";
|
| + case Inline:
|
| + return "inline";
|
| + default:
|
| + NOTREACHED();
|
| + return "";
|
| + }
|
| +}
|
| +
|
| +void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) {
|
| + result.setDouble(time_range_);
|
| +}
|
| +
|
| +DEFINE_TRACE(ScrollTimeline) {
|
| + visitor->Trace(scroll_source_);
|
| + AnimationTimeline::Trace(visitor);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|