OLD | NEW |
---|---|
(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 flattens(false) { | |
41 } | |
42 | |
43 TransformNodeData::~TransformNodeData() { | |
44 } | |
45 | |
46 ClipNodeData::ClipNodeData() : transform_id(-1), target_id(-1) { | |
47 } | |
48 | |
49 bool IsDescendant(const TransformTree& tree, int desc_id, int source_id) { | |
50 while (desc_id != source_id) { | |
51 if (desc_id < 0) | |
52 return false; | |
53 desc_id = tree.Node(desc_id)->parent_id; | |
54 } | |
55 return true; | |
56 } | |
57 | |
58 int LowestCommonAncestor(const TransformTree& tree, int a, int b) { | |
59 std::set<int> chain_a; | |
60 std::set<int> chain_b; | |
61 while (a || b) { | |
62 if (a) { | |
63 a = tree.Node(a)->parent_id; | |
64 if (a > -1 && chain_b.find(a) != chain_b.end()) | |
65 return a; | |
66 chain_a.insert(a); | |
67 } | |
68 if (b) { | |
69 b = tree.Node(b)->parent_id; | |
70 if (b > -1 && chain_a.find(b) != chain_a.end()) | |
71 return b; | |
72 chain_b.insert(b); | |
73 } | |
74 } | |
75 NOTREACHED(); | |
76 return 0; | |
77 } | |
78 | |
79 bool CombineTransformsBetween(const TransformTree& tree, | |
80 int source_id, | |
81 int dest_id, | |
82 gfx::Transform* transform) { | |
83 const TransformNode* current = tree.Node(source_id); | |
84 const TransformNode* dest = tree.Node(dest_id); | |
85 if (!dest || dest->data.ancestors_are_invertible) { | |
86 transform->ConcatTransform(current->data.to_screen); | |
87 if (dest) | |
88 transform->ConcatTransform(dest->data.from_screen); | |
89 return true; | |
90 } | |
91 | |
92 bool all_are_invertible = true; | |
93 for (; current && current->id > dest_id; current = tree.parent(current)) { | |
94 transform->ConcatTransform(current->data.to_parent); | |
95 if (!current->data.is_invertible) | |
96 all_are_invertible = false; | |
97 } | |
98 | |
99 return all_are_invertible; | |
100 } | |
101 | |
102 bool CombineInversesBetween(const TransformTree& tree, | |
103 int source_id, | |
104 int dest_id, | |
105 gfx::Transform* transform) { | |
106 const TransformNode* current = tree.Node(dest_id); | |
107 const TransformNode* dest = tree.Node(source_id); | |
108 if (current->data.ancestors_are_invertible) { | |
109 transform->PreconcatTransform(current->data.from_screen); | |
110 if (dest) | |
111 transform->PreconcatTransform(dest->data.to_screen); | |
112 return true; | |
113 } | |
114 | |
115 bool all_are_invertible = true; | |
116 for (; current && current->id > source_id; current = tree.parent(current)) { | |
117 transform->PreconcatTransform(current->data.from_parent); | |
118 if (!current->data.is_invertible) | |
119 all_are_invertible = false; | |
120 } | |
121 | |
122 return all_are_invertible; | |
123 } | |
124 | |
125 bool ComputeTransform(const TransformTree& tree, | |
enne (OOO)
2014/12/10 23:45:59
This probably needs a note that transform should b
Ian Vollick
2014/12/12 03:01:47
I actually take advantage of the fact that it does
enne (OOO)
2014/12/12 19:05:49
It still looks to me like you're just passing iden
Ian Vollick
2014/12/15 21:45:17
Sorry, I pointed you at the wrong function. But in
| |
126 int source_id, | |
127 int dest_id, | |
128 gfx::Transform* transform) { | |
129 if (source_id == dest_id) | |
130 return true; | |
131 | |
132 if (source_id > dest_id && IsDescendant(tree, source_id, dest_id)) | |
133 return CombineTransformsBetween(tree, source_id, dest_id, transform); | |
134 | |
135 if (dest_id > source_id && IsDescendant(tree, dest_id, source_id)) | |
136 return CombineInversesBetween(tree, source_id, dest_id, transform); | |
137 | |
138 int lca = LowestCommonAncestor(tree, source_id, dest_id); | |
139 | |
140 bool no_singular_matrices_to_lca = | |
141 CombineTransformsBetween(tree, source_id, lca, transform); | |
142 | |
143 bool no_singular_matrices_from_lca = | |
144 CombineInversesBetween(tree, lca, dest_id, transform); | |
145 | |
146 return no_singular_matrices_to_lca && no_singular_matrices_from_lca; | |
147 } | |
148 | |
149 bool Are2DAxisAligned(const TransformTree& tree, int source_id, int dest_id) { | |
150 gfx::Transform transform; | |
151 return ComputeTransform(tree, source_id, dest_id, &transform) && | |
152 transform.Preserves2dAxisAlignment(); | |
153 } | |
154 | |
155 void UpdateScreenSpaceTransform(TransformTree* tree, int id) { | |
156 TransformNode* node = tree->Node(id); | |
157 TransformNode* parent = tree->parent(node); | |
158 TransformNode* target = tree->Node(node->data.target_id); | |
159 | |
160 if (!parent) { | |
161 node->data.to_screen = node->data.to_parent; | |
162 node->data.ancestors_are_invertible = true; | |
163 } else if (parent->data.flattens) { | |
164 // Flattening is tricky. Once a layer is drawn into its render target, it | |
165 // cannot escape, so we only need to consider transforms between the layer | |
166 // and its target when flattening (i.e., its draw transform). To compute the | |
167 // screen space transform when flattening is involved we combine three | |
168 // transforms, A * B * C, where A is the screen space transform of the | |
169 // target, B is the flattened draw transform of the layer's parent, and C is | |
170 // the local transform. | |
171 node->data.to_screen = target->data.to_screen; | |
172 gfx::Transform flattened; | |
173 ComputeTransform(*tree, parent->id, target->id, &flattened); | |
174 flattened.FlattenTo2d(); | |
175 node->data.to_screen.PreconcatTransform(flattened); | |
176 node->data.to_screen.PreconcatTransform(node->data.to_parent); | |
177 node->data.ancestors_are_invertible = parent->data.ancestors_are_invertible; | |
178 } else { | |
179 node->data.to_screen = parent->data.to_screen; | |
180 node->data.to_screen.PreconcatTransform(node->data.to_parent); | |
181 node->data.ancestors_are_invertible = parent->data.ancestors_are_invertible; | |
182 } | |
183 if (!node->data.to_screen.GetInverse(&node->data.from_screen)) | |
184 node->data.ancestors_are_invertible = false; | |
185 } | |
186 | |
187 } // namespace cc | |
OLD | NEW |