[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / page / scrolling / ScrollingStateNode.cpp
1 /*
2  * Copyright (C) 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ScrollingStateNode.h"
28
29 #if ENABLE(ASYNC_SCROLLING)
30
31 #include "ScrollingStateFixedNode.h"
32 #include "ScrollingStateTree.h"
33 #include <wtf/text/TextStream.h>
34
35 #include <wtf/text/WTFString.h>
36
37 namespace WebCore {
38
39 ScrollingStateNode::ScrollingStateNode(ScrollingNodeType nodeType, ScrollingStateTree& scrollingStateTree, ScrollingNodeID nodeID)
40     : m_nodeType(nodeType)
41     , m_nodeID(nodeID)
42     , m_scrollingStateTree(scrollingStateTree)
43 {
44 }
45
46 // This copy constructor is used for cloning nodes in the tree, and it doesn't make sense
47 // to clone the relationship pointers, so don't copy that information from the original node.
48 ScrollingStateNode::ScrollingStateNode(const ScrollingStateNode& stateNode, ScrollingStateTree& adoptiveTree)
49     : m_nodeType(stateNode.nodeType())
50     , m_nodeID(stateNode.scrollingNodeID())
51     , m_changedProperties(stateNode.changedProperties())
52     , m_scrollingStateTree(adoptiveTree)
53 {
54     if (hasChangedProperty(Layer))
55         setLayer(stateNode.layer().toRepresentation(adoptiveTree.preferredLayerRepresentation()));
56
57     scrollingStateTree().addNode(*this);
58 }
59
60 ScrollingStateNode::~ScrollingStateNode() = default;
61
62 void ScrollingStateNode::setPropertyChanged(unsigned propertyBit)
63 {
64     if (hasChangedProperty(propertyBit))
65         return;
66
67     setPropertyChangedBit(propertyBit);
68     m_scrollingStateTree.setHasChangedProperties();
69 }
70
71 void ScrollingStateNode::setPropertyChangedBitsAfterReattach()
72 {
73     setPropertyChangedBit(Layer);
74     setPropertyChangedBit(ChildNodes);
75     m_scrollingStateTree.setHasChangedProperties();
76 }
77
78 Ref<ScrollingStateNode> ScrollingStateNode::cloneAndReset(ScrollingStateTree& adoptiveTree)
79 {
80     auto clone = this->clone(adoptiveTree);
81
82     // Now that this node is cloned, reset our change properties.
83     resetChangedProperties();
84
85     cloneAndResetChildren(clone.get(), adoptiveTree);
86
87     return clone;
88 }
89
90 void ScrollingStateNode::cloneAndResetChildren(ScrollingStateNode& clone, ScrollingStateTree& adoptiveTree)
91 {
92     if (!m_children)
93         return;
94
95     for (auto& child : *m_children)
96         clone.appendChild(child->cloneAndReset(adoptiveTree));
97 }
98
99 void ScrollingStateNode::appendChild(Ref<ScrollingStateNode>&& childNode)
100 {
101     childNode->setParent(this);
102
103     if (!m_children)
104         m_children = makeUnique<Vector<RefPtr<ScrollingStateNode>>>();
105     m_children->append(WTFMove(childNode));
106     setPropertyChanged(ChildNodes);
107 }
108
109 void ScrollingStateNode::insertChild(Ref<ScrollingStateNode>&& childNode, size_t index)
110 {
111     childNode->setParent(this);
112
113     if (!m_children) {
114         ASSERT(!index);
115         m_children = makeUnique<Vector<RefPtr<ScrollingStateNode>>>();
116     }
117
118     if (index > m_children->size()) {
119         ASSERT_NOT_REACHED();  // Crash data suggest we can get here.
120         m_children->append(WTFMove(childNode));
121     } else
122         m_children->insert(index, WTFMove(childNode));
123     
124     setPropertyChanged(ChildNodes);
125 }
126
127 void ScrollingStateNode::removeFromParent()
128 {
129     if (!m_parent)
130         return;
131
132     m_parent->removeChild(*this);
133     m_parent = nullptr;
134 }
135
136 void ScrollingStateNode::removeChild(ScrollingStateNode& childNode)
137 {
138     auto childIndex = indexOfChild(childNode);
139     if (childIndex != notFound)
140         removeChildAtIndex(childIndex);
141 }
142
143 void ScrollingStateNode::removeChildAtIndex(size_t index)
144 {
145     ASSERT(m_children && index < m_children->size());
146     if (m_children && index < m_children->size()) {
147         m_children->remove(index);
148         setPropertyChanged(ChildNodes);
149     }
150 }
151
152 size_t ScrollingStateNode::indexOfChild(ScrollingStateNode& childNode) const
153 {
154     if (!m_children)
155         return notFound;
156
157     return m_children->find(&childNode);
158 }
159
160 void ScrollingStateNode::setLayer(const LayerRepresentation& layerRepresentation)
161 {
162     if (layerRepresentation == m_layer)
163         return;
164     
165     m_layer = layerRepresentation;
166
167     setPropertyChanged(Layer);
168 }
169
170 void ScrollingStateNode::dumpProperties(TextStream& ts, ScrollingStateTreeAsTextBehavior behavior) const
171 {
172     if (behavior & ScrollingStateTreeAsTextBehaviorIncludeNodeIDs)
173         ts.dumpProperty("nodeID", scrollingNodeID());
174     
175     if (behavior & ScrollingStateTreeAsTextBehaviorIncludeLayerIDs)
176         ts.dumpProperty("layerID", layer().layerID());
177 }
178
179 void ScrollingStateNode::dump(TextStream& ts, ScrollingStateTreeAsTextBehavior behavior) const
180 {
181     ts << "\n";
182     ts << indent << "(";
183     ts.increaseIndent();
184     dumpProperties(ts, behavior);
185
186     if (m_children) {
187         ts << "\n";
188         ts << indent <<"(";
189         {
190             TextStream::IndentScope indentScope(ts);
191             ts << "children " << children()->size();
192             for (auto& child : *m_children)
193                 child->dump(ts, behavior);
194             ts << "\n";
195         }
196         ts << indent << ")";
197     }
198     ts << "\n";
199     ts.decreaseIndent();
200     ts << indent << ")";
201 }
202
203 String ScrollingStateNode::scrollingStateTreeAsText(ScrollingStateTreeAsTextBehavior behavior) const
204 {
205     TextStream ts(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect);
206
207     dump(ts, behavior);
208     ts << "\n";
209     return ts.release();
210 }
211
212 } // namespace WebCore
213
214 #endif // ENABLE(ASYNC_SCROLLING)