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..de235c95578556daae90a39909008f0663571053 |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/animation/ScrollTimeline.cpp |
@@ -0,0 +1,161 @@ |
+// 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) { |
+ if (scroll_direction == "auto") { |
+ *result = ScrollTimeline::Auto; |
+ return true; |
+ } |
+ if (scroll_direction == "block") { |
+ *result = ScrollTimeline::Block; |
+ return true; |
+ } |
+ if (scroll_direction == "inline") { |
+ *result = ScrollTimeline::Inline; |
+ return true; |
+ } |
+ return false; |
+} |
+} // namespace |
+ |
+ScrollTimeline* ScrollTimeline::Create(const Document& document, |
+ ScrollTimelineOptions options, |
+ ExceptionState& exception_state) { |
+ // TODO(smcgruer): The spec allows for a null scrollSource. |
majidvp
2017/05/15 14:38:52
Hmmm, I presume that if the scrollSource is not sp
smcgruer
2017/05/15 15:22:54
Nope, spec defines it as follows (https://wicg.git
flackr
2017/05/15 17:29:06
Note, probably should be the document.scrollingEle
smcgruer
2017/05/16 19:24:47
Filed https://github.com/WICG/scroll-animations/is
|
+ if (!options.scrollSource()) { |
+ exception_state.ThrowDOMException(kNotSupportedError, |
+ "A scrollSource must be specified"); |
+ return nullptr; |
+ } |
+ |
+ 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 new ScrollTimeline(document, options.scrollSource(), orientation, |
+ options.timeRange().getAsDouble()); |
+} |
+ |
+ScrollTimeline::ScrollTimeline(const Document& document, |
+ Element* scroll_source, |
+ ScrollDirection orientation, |
+ double time_range) |
+ : AnimationTimeline(const_cast<Document*>(&document), nullptr), |
+ scroll_source_(scroll_source), |
+ orientation_(orientation), |
+ time_range_(time_range) {} |
+ |
+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->GetScrollableArea()) { |
majidvp
2017/05/15 14:38:52
I don't think layout_box->GetScrollableArea() maps
smcgruer
2017/05/15 15:22:54
Ah, so looks like by the spec we just want to chec
flackr
2017/05/15 17:29:06
LayoutObject::HasOverflowClip
smcgruer
2017/05/16 19:24:47
Done.
|
+ LOG(INFO) << "!layout_box || !layout_box->GetScrollableArea()"; |
+ is_null = true; |
+ 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. |
+ ScrollDirection local_orientation = orientation_; |
+ if (local_orientation == Auto) { |
+ // If only one direction is scrollable, selects that direction. Otherwise |
+ // selects the direction along the block axis. |
+ DCHECK(layout_box->HasScrollableOverflowX() || |
+ layout_box->HasScrollableOverflowY()); |
flackr
2017/05/15 17:29:06
I don't think this check is correct. We could have
smcgruer
2017/05/17 15:52:03
Done.
|
+ local_orientation = layout_box->HasScrollableOverflowY() ? Block : Inline; |
flackr
2017/05/15 17:29:06
Isn't this assuming LTR? I think you'd have to che
smcgruer
2017/05/17 15:52:02
Done.
|
+ } |
+ double current_scroll_offset = 0.0; |
+ double max_scroll_offset = 1.0; |
+ switch (local_orientation) { |
+ case Block: |
+ current_scroll_offset = scroll_source_->scrollTop(); |
+ max_scroll_offset = |
+ scroll_source_->scrollHeight() - scroll_source_->clientHeight(); |
majidvp
2017/05/15 14:38:52
Shouldn't we use the logical coordinates here as o
smcgruer
2017/05/15 15:22:54
Possibly. I just wrote this based on a comment in
smcgruer
2017/05/17 15:52:02
Done.
|
+ break; |
+ case Inline: |
+ current_scroll_offset = scroll_source_->scrollLeft(); |
+ max_scroll_offset = |
+ scroll_source_->scrollWidth() - scroll_source_->clientWidth(); |
+ break; |
+ case Auto: |
+ LOG(FATAL) << "local_orientation cannot be Auto"; |
+ break; |
+ } |
+ |
+ // 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 (current_scroll_offset / max_scroll_offset) * time_range_; |
+} |
+ |
+double ScrollTimeline::currentTime() { |
+ bool ignored; |
+ return currentTime(ignored); |
+} |
+ |
+double ScrollTimeline::CurrentTimeInternal(bool& is_null) { |
+ return currentTime(is_null); |
+} |
+ |
+double ScrollTimeline::CurrentTimeInternal() { |
+ bool ignored; |
+ return currentTime(ignored); |
+} |
+ |
+Element* ScrollTimeline::scrollSource() { |
+ return scroll_source_.Get(); |
+} |
+ |
+String ScrollTimeline::orientation() { |
+ switch (orientation_) { |
+ case Auto: |
+ return "auto"; |
+ case Block: |
+ return "block"; |
+ case Inline: |
+ return "inline"; |
+ } |
+} |
+ |
+void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) { |
+ result.setDouble(time_range_); |
+} |
+ |
+DEFINE_TRACE(ScrollTimeline) { |
+ visitor->Trace(scroll_source_); |
+ AnimationTimeline::Trace(visitor); |
+} |
+ |
+} // namespace blink |