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 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(¤t_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 |
OLD | NEW |