Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: cc/trees/property_tree.cc

Issue 687873004: Introduce Property Trees (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@wip-awoloszyn2
Patch Set: . Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/trees/property_tree.h ('k') | cc/trees/property_tree_builder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <set>
6
7 #include "base/logging.h"
8 #include "cc/trees/property_tree.h"
9
10 namespace cc {
11
12 template <typename T>
13 PropertyTree<T>::PropertyTree() {
14 nodes_.push_back(T());
15 back()->id = 0;
16 back()->parent_id = -1;
17 }
18
19 template <typename T>
20 PropertyTree<T>::~PropertyTree() {
21 }
22
23 template <typename T>
24 int PropertyTree<T>::Insert(const T& tree_node, int parent_id) {
25 DCHECK_GT(nodes_.size(), 0u);
26 nodes_.push_back(tree_node);
27 T& node = nodes_.back();
28 node.parent_id = parent_id;
29 node.id = static_cast<int>(nodes_.size()) - 1;
30 return node.id;
31 }
32
33 template class PropertyTree<TransformNode>;
34 template class PropertyTree<ClipNode>;
35
36 TransformNodeData::TransformNodeData()
37 : target_id(-1),
38 is_invertible(true),
39 ancestors_are_invertible(true),
40 is_animated(false),
41 to_screen_is_animated(false),
42 flattens(false) {
43 }
44
45 TransformNodeData::~TransformNodeData() {
46 }
47
48 ClipNodeData::ClipNodeData() : transform_id(-1), target_id(-1) {
49 }
50
51 bool TransformTree::ComputeTransform(int source_id,
52 int dest_id,
53 gfx::Transform* transform) const {
54 transform->MakeIdentity();
55
56 if (source_id == dest_id)
57 return true;
58
59 if (source_id > dest_id && IsDescendant(source_id, dest_id))
60 return CombineTransformsBetween(source_id, dest_id, transform);
61
62 if (dest_id > source_id && IsDescendant(dest_id, source_id))
63 return CombineInversesBetween(source_id, dest_id, transform);
64
65 int lca = LowestCommonAncestor(source_id, dest_id);
66
67 bool no_singular_matrices_to_lca =
68 CombineTransformsBetween(source_id, lca, transform);
69
70 bool no_singular_matrices_from_lca =
71 CombineInversesBetween(lca, dest_id, transform);
72
73 return no_singular_matrices_to_lca && no_singular_matrices_from_lca;
74 }
75
76 bool TransformTree::Are2DAxisAligned(int source_id, int dest_id) const {
77 gfx::Transform transform;
78 return ComputeTransform(source_id, dest_id, &transform) &&
79 transform.Preserves2dAxisAlignment();
80 }
81
82 void TransformTree::UpdateScreenSpaceTransform(int id) {
83 TransformNode* current_node = Node(id);
84 TransformNode* parent_node = parent(current_node);
85 TransformNode* target_node = Node(current_node->data.target_id);
86
87 if (!parent_node) {
88 current_node->data.to_screen = current_node->data.to_parent;
89 current_node->data.ancestors_are_invertible = true;
90 current_node->data.to_screen_is_animated = false;
91 } else if (parent_node->data.flattens) {
92 // Flattening is tricky. Once a layer is drawn into its render target, it
93 // cannot escape, so we only need to consider transforms between the layer
94 // and its target when flattening (i.e., its draw transform). To compute the
95 // screen space transform when flattening is involved we combine three
96 // transforms, A * B * C, where A is the screen space transform of the
97 // target, B is the flattened draw transform of the layer's parent, and C is
98 // the local transform.
99 current_node->data.to_screen = target_node->data.to_screen;
100 gfx::Transform flattened;
101 ComputeTransform(parent_node->id, target_node->id, &flattened);
102 flattened.FlattenTo2d();
103 current_node->data.to_screen.PreconcatTransform(flattened);
104 current_node->data.to_screen.PreconcatTransform(
105 current_node->data.to_parent);
106 current_node->data.ancestors_are_invertible =
107 parent_node->data.ancestors_are_invertible;
108 } else {
109 current_node->data.to_screen = parent_node->data.to_screen;
110 current_node->data.to_screen.PreconcatTransform(
111 current_node->data.to_parent);
112 current_node->data.ancestors_are_invertible =
113 parent_node->data.ancestors_are_invertible;
114 }
115 if (!current_node->data.to_screen.GetInverse(&current_node->data.from_screen))
116 current_node->data.ancestors_are_invertible = false;
117
118 if (parent_node) {
119 current_node->data.to_screen_is_animated =
120 current_node->data.is_animated ||
121 parent_node->data.to_screen_is_animated;
122 }
123 }
124
125 bool TransformTree::IsDescendant(int desc_id, int source_id) const {
126 while (desc_id != source_id) {
127 if (desc_id < 0)
128 return false;
129 desc_id = Node(desc_id)->parent_id;
130 }
131 return true;
132 }
133
134 int TransformTree::LowestCommonAncestor(int a, int b) const {
135 std::set<int> chain_a;
136 std::set<int> chain_b;
137 while (a || b) {
138 if (a) {
139 a = Node(a)->parent_id;
140 if (a > -1 && chain_b.find(a) != chain_b.end())
141 return a;
142 chain_a.insert(a);
143 }
144 if (b) {
145 b = Node(b)->parent_id;
146 if (b > -1 && chain_a.find(b) != chain_a.end())
147 return b;
148 chain_b.insert(b);
149 }
150 }
151 NOTREACHED();
152 return 0;
153 }
154
155 bool TransformTree::CombineTransformsBetween(int source_id,
156 int dest_id,
157 gfx::Transform* transform) const {
158 const TransformNode* current = Node(source_id);
159 const TransformNode* dest = Node(dest_id);
160 if (!dest || dest->data.ancestors_are_invertible) {
161 transform->ConcatTransform(current->data.to_screen);
162 if (dest)
163 transform->ConcatTransform(dest->data.from_screen);
164 return true;
165 }
166
167 bool all_are_invertible = true;
168 for (; current && current->id > dest_id; current = parent(current)) {
169 transform->ConcatTransform(current->data.to_parent);
170 if (!current->data.is_invertible)
171 all_are_invertible = false;
172 }
173
174 return all_are_invertible;
175 }
176
177 bool TransformTree::CombineInversesBetween(int source_id,
178 int dest_id,
179 gfx::Transform* transform) const {
180 const TransformNode* current = Node(dest_id);
181 const TransformNode* dest = Node(source_id);
182 if (current->data.ancestors_are_invertible) {
183 transform->PreconcatTransform(current->data.from_screen);
184 if (dest)
185 transform->PreconcatTransform(dest->data.to_screen);
186 return true;
187 }
188
189 bool all_are_invertible = true;
190 for (; current && current->id > source_id; current = parent(current)) {
191 transform->PreconcatTransform(current->data.from_parent);
192 if (!current->data.is_invertible)
193 all_are_invertible = false;
194 }
195
196 return all_are_invertible;
197 }
198
199 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/property_tree.h ('k') | cc/trees/property_tree_builder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698