1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
// Copyright 2018 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 "third_party/blink/renderer/core/animation/scroll_timeline_util.h"
#include "third_party/blink/renderer/bindings/core/v8/double_or_scroll_timeline_auto_keyword.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_scrolltimelineautokeyword.h"
#include "third_party/blink/renderer/core/animation/animation_timeline.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
namespace blink {
namespace scroll_timeline_util {
scoped_refptr<CompositorScrollTimeline> ToCompositorScrollTimeline(
AnimationTimeline* timeline) {
if (!timeline || IsA<DocumentTimeline>(timeline))
return nullptr;
auto* scroll_timeline = To<ScrollTimeline>(timeline);
Node* scroll_source = scroll_timeline->ResolvedScrollSource();
absl::optional<CompositorElementId> element_id =
GetCompositorScrollElementId(scroll_source);
#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
auto* time_range = scroll_timeline->timeRange();
DCHECK(time_range);
#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
DoubleOrScrollTimelineAutoKeyword time_range;
scroll_timeline->timeRange(time_range);
// TODO(smcgruer): Handle 'auto' time range value.
DCHECK(time_range.IsDouble());
#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
LayoutBox* box =
scroll_timeline->IsActive() ? scroll_source->GetLayoutBox() : nullptr;
CompositorScrollTimeline::ScrollDirection orientation = ConvertOrientation(
scroll_timeline->GetOrientation(), box ? box->Style() : nullptr);
return CompositorScrollTimeline::Create(
element_id, orientation, scroll_timeline->GetResolvedScrollOffsets(),
#if defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
time_range->GetAsDouble()
#else // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
time_range.GetAsDouble()
#endif // defined(USE_BLINK_V8_BINDING_NEW_IDL_UNION)
);
}
absl::optional<CompositorElementId> GetCompositorScrollElementId(
const Node* node) {
if (!node || !node->GetLayoutObject() ||
!node->GetLayoutObject()->FirstFragment().PaintProperties()) {
return absl::nullopt;
}
return CompositorElementIdFromUniqueObjectId(
node->GetLayoutObject()->UniqueId(),
CompositorElementIdNamespace::kScroll);
}
// The compositor does not know about writing modes, so we have to convert the
// web concepts of 'block' and 'inline' direction into absolute vertical or
// horizontal directions.
CompositorScrollTimeline::ScrollDirection ConvertOrientation(
ScrollTimeline::ScrollDirection orientation,
const ComputedStyle* style) {
// Easy cases; physical is always physical.
if (orientation == ScrollTimeline::Horizontal)
return CompositorScrollTimeline::ScrollRight;
if (orientation == ScrollTimeline::Vertical)
return CompositorScrollTimeline::ScrollDown;
// Harder cases; first work out which axis is which, and then for each check
// which edge we start at.
// writing-mode: horizontal-tb
bool is_horizontal_writing_mode =
style ? style->IsHorizontalWritingMode() : true;
// writing-mode: vertical-lr
bool is_flipped_lines_writing_mode =
style ? style->IsFlippedLinesWritingMode() : false;
// direction: ltr;
bool is_ltr_direction = style ? style->IsLeftToRightDirection() : true;
if (orientation == ScrollTimeline::Block) {
if (is_horizontal_writing_mode) {
// For horizontal writing mode, block is vertical. The starting edge is
// always the top.
return CompositorScrollTimeline::ScrollDown;
}
// For vertical writing mode, the block axis is horizontal. The starting
// edge depends on if we are lr or rl.
return is_flipped_lines_writing_mode ? CompositorScrollTimeline::ScrollRight
: CompositorScrollTimeline::ScrollLeft;
}
DCHECK_EQ(orientation, ScrollTimeline::Inline);
if (is_horizontal_writing_mode) {
// For horizontal writing mode, inline is horizontal. The starting edge
// depends on the directionality.
return is_ltr_direction ? CompositorScrollTimeline::ScrollRight
: CompositorScrollTimeline::ScrollLeft;
}
// For vertical writing mode, inline is vertical. The starting edge still
// depends on the directionality; whether it is vertical-lr or vertical-rl
// does not matter.
return is_ltr_direction ? CompositorScrollTimeline::ScrollDown
: CompositorScrollTimeline::ScrollUp;
}
double ComputeProgress(double current_offset,
const WTF::Vector<double>& resolved_offsets) {
return cc::ComputeProgress<WTF::Vector<double>>(current_offset,
resolved_offsets);
}
} // namespace scroll_timeline_util
} // namespace blink
|