Chromium Code Reviews| 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 |