| Index: cc/trees/property_tree.cc
|
| diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
|
| deleted file mode 100644
|
| index 544755b211625cf9ab73cfdbbc88b9d28bca0333..0000000000000000000000000000000000000000
|
| --- a/cc/trees/property_tree.cc
|
| +++ /dev/null
|
| @@ -1,335 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include <set>
|
| -#include <vector>
|
| -
|
| -#include "base/logging.h"
|
| -#include "cc/base/math_util.h"
|
| -#include "cc/trees/property_tree.h"
|
| -
|
| -namespace cc {
|
| -
|
| -template <typename T>
|
| -PropertyTree<T>::PropertyTree() {
|
| - nodes_.push_back(T());
|
| - back()->id = 0;
|
| - back()->parent_id = -1;
|
| -}
|
| -
|
| -template <typename T>
|
| -PropertyTree<T>::~PropertyTree() {
|
| -}
|
| -
|
| -template <typename T>
|
| -int PropertyTree<T>::Insert(const T& tree_node, int parent_id) {
|
| - DCHECK_GT(nodes_.size(), 0u);
|
| - nodes_.push_back(tree_node);
|
| - T& node = nodes_.back();
|
| - node.parent_id = parent_id;
|
| - node.id = static_cast<int>(nodes_.size()) - 1;
|
| - return node.id;
|
| -}
|
| -
|
| -template class PropertyTree<TransformNode>;
|
| -template class PropertyTree<ClipNode>;
|
| -template class PropertyTree<OpacityNode>;
|
| -
|
| -TransformNodeData::TransformNodeData()
|
| - : target_id(-1),
|
| - content_target_id(-1),
|
| - needs_local_transform_update(true),
|
| - is_invertible(true),
|
| - ancestors_are_invertible(true),
|
| - is_animated(false),
|
| - to_screen_is_animated(false),
|
| - flattens_inherited_transform(false),
|
| - node_and_ancestors_are_flat(true),
|
| - scrolls(false),
|
| - needs_sublayer_scale(false),
|
| - layer_scale_factor(1.0f) {
|
| -}
|
| -
|
| -TransformNodeData::~TransformNodeData() {
|
| -}
|
| -
|
| -ClipNodeData::ClipNodeData() : transform_id(-1), target_id(-1) {
|
| -}
|
| -
|
| -bool TransformTree::ComputeTransform(int source_id,
|
| - int dest_id,
|
| - gfx::Transform* transform) const {
|
| - transform->MakeIdentity();
|
| -
|
| - if (source_id == dest_id)
|
| - return true;
|
| -
|
| - if (source_id > dest_id && IsDescendant(source_id, dest_id))
|
| - return CombineTransformsBetween(source_id, dest_id, transform);
|
| -
|
| - if (dest_id > source_id && IsDescendant(dest_id, source_id))
|
| - return CombineInversesBetween(source_id, dest_id, transform);
|
| -
|
| - int lca = LowestCommonAncestor(source_id, dest_id);
|
| -
|
| - bool no_singular_matrices_to_lca =
|
| - CombineTransformsBetween(source_id, lca, transform);
|
| -
|
| - bool no_singular_matrices_from_lca =
|
| - CombineInversesBetween(lca, dest_id, transform);
|
| -
|
| - return no_singular_matrices_to_lca && no_singular_matrices_from_lca;
|
| -}
|
| -
|
| -bool TransformTree::Are2DAxisAligned(int source_id, int dest_id) const {
|
| - gfx::Transform transform;
|
| - return ComputeTransform(source_id, dest_id, &transform) &&
|
| - transform.Preserves2dAxisAlignment();
|
| -}
|
| -
|
| -void TransformTree::UpdateTransforms(int id) {
|
| - TransformNode* node = Node(id);
|
| - TransformNode* parent_node = parent(node);
|
| - TransformNode* target_node = Node(node->data.target_id);
|
| - if (node->data.needs_local_transform_update)
|
| - UpdateLocalTransform(node);
|
| - UpdateScreenSpaceTransform(node, parent_node, target_node);
|
| - UpdateSublayerScale(node);
|
| - UpdateTargetSpaceTransform(node, target_node);
|
| - UpdateIsAnimated(node, parent_node);
|
| - UpdateSnapping(node);
|
| -}
|
| -
|
| -bool TransformTree::IsDescendant(int desc_id, int source_id) const {
|
| - while (desc_id != source_id) {
|
| - if (desc_id < 0)
|
| - return false;
|
| - desc_id = Node(desc_id)->parent_id;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -int TransformTree::LowestCommonAncestor(int a, int b) const {
|
| - std::set<int> chain_a;
|
| - std::set<int> chain_b;
|
| - while (a || b) {
|
| - if (a) {
|
| - a = Node(a)->parent_id;
|
| - if (a > -1 && chain_b.find(a) != chain_b.end())
|
| - return a;
|
| - chain_a.insert(a);
|
| - }
|
| - if (b) {
|
| - b = Node(b)->parent_id;
|
| - if (b > -1 && chain_a.find(b) != chain_a.end())
|
| - return b;
|
| - chain_b.insert(b);
|
| - }
|
| - }
|
| - NOTREACHED();
|
| - return 0;
|
| -}
|
| -
|
| -bool TransformTree::CombineTransformsBetween(int source_id,
|
| - int dest_id,
|
| - gfx::Transform* transform) const {
|
| - const TransformNode* current = Node(source_id);
|
| - const TransformNode* dest = Node(dest_id);
|
| - // Combine transforms to and from the screen when possible. Since flattening
|
| - // is a non-linear operation, we cannot use this approach when there is
|
| - // non-trivial flattening between the source and destination nodes. For
|
| - // example, consider the tree R->A->B->C, where B flattens its inherited
|
| - // transform, and A has a non-flat transform. Suppose C is the source and A is
|
| - // the destination. The expected result is C * B. But C's to_screen
|
| - // transform is C * B * flattened(A * R), and A's from_screen transform is
|
| - // R^{-1} * A^{-1}. If at least one of A and R isn't flat, the inverse of
|
| - // flattened(A * R) won't be R^{-1} * A{-1}, so multiplying C's to_screen and
|
| - // A's from_screen will not produce the correct result.
|
| - if (!dest || (dest->data.ancestors_are_invertible &&
|
| - current->data.node_and_ancestors_are_flat)) {
|
| - transform->ConcatTransform(current->data.to_screen);
|
| - if (dest)
|
| - transform->ConcatTransform(dest->data.from_screen);
|
| - return true;
|
| - }
|
| -
|
| - bool all_are_invertible = true;
|
| -
|
| - // Flattening is defined in a way that requires it to be applied while
|
| - // traversing downward in the tree. We first identify nodes that are on the
|
| - // path from the source to the destination (this is traversing upward), and
|
| - // then we visit these nodes in reverse order, flattening as needed. We
|
| - // early-out if we get to a node whose target node is the destination, since
|
| - // we can then re-use the target space transform stored at that node.
|
| - std::vector<int> source_to_destination;
|
| - source_to_destination.push_back(current->id);
|
| - current = parent(current);
|
| - for (; current && current->id > dest_id; current = parent(current)) {
|
| - if (current->data.target_id == dest_id &&
|
| - current->data.content_target_id == dest_id)
|
| - break;
|
| - source_to_destination.push_back(current->id);
|
| - }
|
| -
|
| - gfx::Transform combined_transform;
|
| - if (current->id > dest_id) {
|
| - combined_transform = current->data.to_target;
|
| - // The stored target space transform has sublayer scale baked in, but we
|
| - // need the unscaled transform.
|
| - combined_transform.Scale(1.0f / dest->data.sublayer_scale.x(),
|
| - 1.0f / dest->data.sublayer_scale.y());
|
| - }
|
| -
|
| - for (int i = source_to_destination.size() - 1; i >= 0; i--) {
|
| - const TransformNode* node = Node(source_to_destination[i]);
|
| - if (node->data.flattens_inherited_transform)
|
| - combined_transform.FlattenTo2d();
|
| - combined_transform.PreconcatTransform(node->data.to_parent);
|
| -
|
| - if (!node->data.is_invertible)
|
| - all_are_invertible = false;
|
| - }
|
| -
|
| - transform->ConcatTransform(combined_transform);
|
| - return all_are_invertible;
|
| -}
|
| -
|
| -bool TransformTree::CombineInversesBetween(int source_id,
|
| - int dest_id,
|
| - gfx::Transform* transform) const {
|
| - const TransformNode* current = Node(dest_id);
|
| - const TransformNode* dest = Node(source_id);
|
| - // Just as in CombineTransformsBetween, we can use screen space transforms in
|
| - // this computation only when there isn't any non-trivial flattening
|
| - // involved.
|
| - if (current->data.ancestors_are_invertible &&
|
| - current->data.node_and_ancestors_are_flat) {
|
| - transform->PreconcatTransform(current->data.from_screen);
|
| - if (dest)
|
| - transform->PreconcatTransform(dest->data.to_screen);
|
| - return true;
|
| - }
|
| -
|
| - // Inverting a flattening is not equivalent to flattening an inverse. This
|
| - // means we cannot, for example, use the inverse of each node's to_parent
|
| - // transform, flattening where needed. Instead, we must compute the transform
|
| - // from the destination to the source, with flattening, and then invert the
|
| - // result.
|
| - gfx::Transform dest_to_source;
|
| - CombineTransformsBetween(dest_id, source_id, &dest_to_source);
|
| - gfx::Transform source_to_dest;
|
| - bool all_are_invertible = dest_to_source.GetInverse(&source_to_dest);
|
| - transform->PreconcatTransform(source_to_dest);
|
| - return all_are_invertible;
|
| -}
|
| -
|
| -void TransformTree::UpdateLocalTransform(TransformNode* node) {
|
| - gfx::Transform transform = node->data.post_local;
|
| - transform.Translate(-node->data.scroll_offset.x(),
|
| - -node->data.scroll_offset.y());
|
| - transform.PreconcatTransform(node->data.local);
|
| - transform.PreconcatTransform(node->data.pre_local);
|
| - node->data.set_to_parent(transform);
|
| - node->data.needs_local_transform_update = false;
|
| -}
|
| -
|
| -void TransformTree::UpdateScreenSpaceTransform(TransformNode* node,
|
| - TransformNode* parent_node,
|
| - TransformNode* target_node) {
|
| - if (!parent_node) {
|
| - node->data.to_screen = node->data.to_parent;
|
| - node->data.ancestors_are_invertible = true;
|
| - node->data.to_screen_is_animated = false;
|
| - node->data.node_and_ancestors_are_flat = node->data.to_parent.IsFlat();
|
| - } else {
|
| - node->data.to_screen = parent_node->data.to_screen;
|
| - if (node->data.flattens_inherited_transform)
|
| - node->data.to_screen.FlattenTo2d();
|
| - node->data.to_screen.PreconcatTransform(node->data.to_parent);
|
| - node->data.ancestors_are_invertible =
|
| - parent_node->data.ancestors_are_invertible;
|
| - node->data.node_and_ancestors_are_flat =
|
| - parent_node->data.node_and_ancestors_are_flat &&
|
| - node->data.to_parent.IsFlat();
|
| - }
|
| -
|
| - if (!node->data.to_screen.GetInverse(&node->data.from_screen))
|
| - node->data.ancestors_are_invertible = false;
|
| -}
|
| -
|
| -void TransformTree::UpdateSublayerScale(TransformNode* node) {
|
| - // The sublayer scale depends on the screen space transform, so update it too.
|
| - node->data.sublayer_scale =
|
| - node->data.needs_sublayer_scale
|
| - ? MathUtil::ComputeTransform2dScaleComponents(
|
| - node->data.to_screen, node->data.layer_scale_factor)
|
| - : gfx::Vector2dF(1.0f, 1.0f);
|
| -}
|
| -
|
| -void TransformTree::UpdateTargetSpaceTransform(TransformNode* node,
|
| - TransformNode* target_node) {
|
| - node->data.to_target.MakeIdentity();
|
| - if (node->data.needs_sublayer_scale) {
|
| - node->data.to_target.Scale(node->data.sublayer_scale.x(),
|
| - node->data.sublayer_scale.y());
|
| - } else {
|
| - const bool target_is_root_surface = target_node->id == 1;
|
| - // In order to include the root transform for the root surface, we walk up
|
| - // to the root of the transform tree in ComputeTransform.
|
| - int target_id = target_is_root_surface ? 0 : target_node->id;
|
| - if (target_node) {
|
| - node->data.to_target.Scale(target_node->data.sublayer_scale.x(),
|
| - target_node->data.sublayer_scale.y());
|
| - }
|
| -
|
| - gfx::Transform unscaled_target_transform;
|
| - ComputeTransform(node->id, target_id, &unscaled_target_transform);
|
| - node->data.to_target.PreconcatTransform(unscaled_target_transform);
|
| - }
|
| -
|
| - if (!node->data.to_target.GetInverse(&node->data.from_target))
|
| - node->data.ancestors_are_invertible = false;
|
| -}
|
| -
|
| -void TransformTree::UpdateIsAnimated(TransformNode* node,
|
| - TransformNode* parent_node) {
|
| - if (parent_node) {
|
| - node->data.to_screen_is_animated =
|
| - node->data.is_animated || parent_node->data.to_screen_is_animated;
|
| - }
|
| -}
|
| -
|
| -void TransformTree::UpdateSnapping(TransformNode* node) {
|
| - if (!node->data.scrolls || node->data.to_screen_is_animated ||
|
| - !node->data.to_target.IsScaleOrTranslation()) {
|
| - return;
|
| - }
|
| -
|
| - // Scroll snapping must be done in target space (the pixels we care about).
|
| - // This means we effectively snap the target space transform. If TT is the
|
| - // target space transform and TT' is TT with its translation components
|
| - // rounded, then what we're after is the scroll delta X, where TT * X = TT'.
|
| - // I.e., we want a transform that will realize our scroll snap. It follows
|
| - // that X = TT^-1 * TT'. We cache TT and TT^-1 to make this more efficient.
|
| - gfx::Transform rounded = node->data.to_target;
|
| - rounded.RoundTranslationComponents();
|
| - gfx::Transform delta = node->data.from_target;
|
| - delta *= rounded;
|
| - gfx::Transform inverse_delta(gfx::Transform::kSkipInitialization);
|
| - bool invertible_delta = delta.GetInverse(&inverse_delta);
|
| -
|
| - // The delta should be a translation, modulo floating point error, and should
|
| - // therefore be invertible.
|
| - DCHECK(invertible_delta);
|
| -
|
| - // Now that we have our scroll delta, we must apply it to each of our
|
| - // combined, to/from matrices.
|
| - node->data.to_parent.PreconcatTransform(delta);
|
| - node->data.to_target.PreconcatTransform(delta);
|
| - node->data.from_target.ConcatTransform(inverse_delta);
|
| - node->data.to_screen.PreconcatTransform(delta);
|
| - node->data.from_screen.ConcatTransform(inverse_delta);
|
| -}
|
| -
|
| -} // namespace cc
|
|
|