12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CC_ANIMATION_TRANSFORM_OPERATIONS_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CC_ANIMATION_TRANSFORM_OPERATIONS_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/transform_operation.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/cc_export.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/transform.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gfx {
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)class BoxF;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct DecomposedTransform;
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Transform operations are a decomposed transformation matrix. It can be
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// applied to obtain a gfx::Transform at any time, and can be blended
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// intelligently with other transform operations, so long as they represent the
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// same decomposition. For example, if we have a transform that is made up of
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// a rotation followed by skew, it can be blended intelligently with another
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// transform made up of a rotation followed by a skew. Blending is possible if
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// we have two dissimilar sets of transform operations, but the effect may not
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// be what was intended. For more information, see the comments for the blend
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// function below.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CC_EXPORT TransformOperations {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperations();
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperations(const TransformOperations& other);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~TransformOperations();
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns a transformation matrix representing these transform operations.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform Apply() const;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Given another set of transform operations and a progress in the range
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // [0, 1], returns a transformation matrix representing the intermediate
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // value. If this->MatchesTypes(from), then each of the operations are
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // blended separately and then combined. Otherwise, the two sets of
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // transforms are baked to matrices (using apply), and the matrices are
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // then decomposed and interpolated. For more information, see
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // http://www.w3.org/TR/2011/WD-css3-2d-transforms-20111215/#matrix-decomposition.
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  gfx::Transform Blend(const TransformOperations& from,
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                       SkMScalar progress) const;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Sets |bounds| be the bounding box for the region within which |box| will
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // exist when it is transformed by the result of calling Blend on |from| and
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // with progress in the range [min_progress, max_progress]. If this region
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // cannot be computed, returns false.
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool BlendedBoundsForBox(const gfx::BoxF& box,
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           const TransformOperations& from,
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           SkMScalar min_progress,
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           SkMScalar max_progress,
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                           gfx::BoxF* bounds) const;
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // Returns true if these operations affect scale.
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  bool AffectsScale() const;
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Returns true if these operations are only translations.
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool IsTranslation() const;
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if this operation and its descendants have the same types
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // as other and its descendants.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool MatchesTypes(const TransformOperations& other) const;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if these operations can be blended. It will only return
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // false if we must resort to matrix interpolation, and matrix interpolation
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // fails (this can happen if either matrix cannot be decomposed).
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool CanBlendWith(const TransformOperations& other) const;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
751675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // If these operations have no more than one scale operation, and if the only
761675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // other operations are translations, sets |scale| to the scale component
771675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // of these operations. Otherwise, returns false.
781675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  bool ScaleComponent(gfx::Vector3dF* scale) const;
791675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void AppendTranslate(SkMScalar x, SkMScalar y, SkMScalar z);
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void AppendRotate(SkMScalar x, SkMScalar y, SkMScalar z, SkMScalar degrees);
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void AppendScale(SkMScalar x, SkMScalar y, SkMScalar z);
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void AppendSkew(SkMScalar x, SkMScalar y);
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void AppendPerspective(SkMScalar depth);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AppendMatrix(const gfx::Transform& matrix);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AppendIdentity();
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsIdentity() const;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool BlendInternal(const TransformOperations& from,
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar progress,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     gfx::Transform* result) const;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<TransformOperation> operations_;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ComputeDecomposedTransform() const;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For efficiency, we cache the decomposed transform.
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mutable scoped_ptr<gfx::DecomposedTransform> decomposed_transform_;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mutable bool decomposed_transform_dirty_;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_ASSIGN(TransformOperations);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // CC_ANIMATION_TRANSFORM_OPERATIONS_H_
108