transform_operations.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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)#include "cc/animation/transform_operations.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/gfx/animation/tween.h"
103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/box_f.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/transform_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/vector3d_f.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TransformOperations::TransformOperations()
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : decomposed_transform_dirty_(true) {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TransformOperations::TransformOperations(const TransformOperations& other) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_ = other.operations_;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decomposed_transform_dirty_ = other.decomposed_transform_dirty_;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!decomposed_transform_dirty_) {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    decomposed_transform_.reset(
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new gfx::DecomposedTransform(*other.decomposed_transform_.get()));
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TransformOperations::~TransformOperations() {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Transform TransformOperations::Apply() const {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform to_return;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < operations_.size(); ++i)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    to_return.PreconcatTransform(operations_[i].matrix);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return to_return;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)gfx::Transform TransformOperations::Blend(const TransformOperations& from,
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                          SkMScalar progress) const {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform to_return;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BlendInternal(from, progress, &to_return);
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return to_return;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool TransformOperations::BlendedBoundsForBox(const gfx::BoxF& box,
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              const TransformOperations& from,
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                              SkMScalar min_progress,
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                              SkMScalar max_progress,
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                              gfx::BoxF* bounds) const {
513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *bounds = box;
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool from_identity = from.IsIdentity();
543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  bool to_identity = IsIdentity();
553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (from_identity && to_identity)
563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return true;
573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!MatchesTypes(from))
593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  size_t num_operations =
623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      std::max(from_identity ? 0 : from.operations_.size(),
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)               to_identity ? 0 : operations_.size());
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < num_operations; ++i) {
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    gfx::BoxF bounds_for_operation;
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const TransformOperation* from_op =
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        from_identity ? NULL : &from.operations_[i];
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const TransformOperation* to_op = to_identity ? NULL : &operations_[i];
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!TransformOperation::BlendedBoundsForBox(*bounds,
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 from_op,
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 to_op,
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 min_progress,
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 max_progress,
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                 &bounds_for_operation))
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    *bounds = bounds_for_operation;
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool TransformOperations::AffectsScale() const {
83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (size_t i = 0; i < operations_.size(); ++i) {
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (operations_[i].type == TransformOperation::TransformOperationScale)
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return true;
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (operations_[i].type == TransformOperation::TransformOperationMatrix &&
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        !operations_[i].matrix.IsIdentityOrTranslation())
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return true;
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return false;
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool TransformOperations::IsTranslation() const {
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (size_t i = 0; i < operations_.size(); ++i) {
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    switch (operations_[i].type) {
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationIdentity:
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationTranslate:
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        continue;
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationMatrix:
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (!operations_[i].matrix.IsIdentityOrTranslation())
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          return false;
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        continue;
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationRotate:
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationScale:
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationSkew:
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationPerspective:
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return false;
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool TransformOperations::MaximumScale(const TransformOperations& from,
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       SkMScalar min_progress,
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       SkMScalar max_progress,
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       float* max_scale) const {
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!MatchesTypes(from))
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Vector3dF from_scale;
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Vector3dF to_scale;
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!from.ScaleComponent(&from_scale) || !ScaleComponent(&to_scale))
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Vector3dF scale_at_min_progress(
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      std::abs(gfx::Tween::FloatValueBetween(
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          min_progress, from_scale.x(), to_scale.x())),
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      std::abs(gfx::Tween::FloatValueBetween(
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          min_progress, from_scale.y(), to_scale.y())),
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      std::abs(gfx::Tween::FloatValueBetween(
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          min_progress, from_scale.z(), to_scale.z())));
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Vector3dF scale_at_max_progress(
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      std::abs(gfx::Tween::FloatValueBetween(
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          max_progress, from_scale.x(), to_scale.x())),
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      std::abs(gfx::Tween::FloatValueBetween(
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          max_progress, from_scale.y(), to_scale.y())),
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      std::abs(gfx::Tween::FloatValueBetween(
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          max_progress, from_scale.z(), to_scale.z())));
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  gfx::Vector3dF max_scale_3d = scale_at_min_progress;
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  max_scale_3d.SetToMax(scale_at_max_progress);
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *max_scale =
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      std::max(max_scale_3d.x(), std::max(max_scale_3d.y(), max_scale_3d.z()));
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool TransformOperations::ScaleComponent(gfx::Vector3dF* scale) const {
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *scale = gfx::Vector3dF(1.f, 1.f, 1.f);
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool has_scale_component = false;
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (size_t i = 0; i < operations_.size(); ++i) {
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    switch (operations_[i].type) {
153c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationIdentity:
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationTranslate:
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        continue;
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationMatrix:
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (!operations_[i].matrix.IsIdentityOrTranslation())
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          return false;
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        continue;
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationRotate:
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationSkew:
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationPerspective:
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return false;
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      case TransformOperation::TransformOperationScale:
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if (has_scale_component)
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          return false;
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        has_scale_component = true;
168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        scale->Scale(operations_[i].scale.x,
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     operations_[i].scale.y,
170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                     operations_[i].scale.z);
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TransformOperations::MatchesTypes(const TransformOperations& other) const {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsIdentity() || other.IsIdentity())
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (operations_.size() != other.operations_.size())
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < operations_.size(); ++i) {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (operations_[i].type != other.operations_[i].type
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      && !operations_[i].IsIdentity()
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      && !other.operations_[i].IsIdentity())
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TransformOperations::CanBlendWith(
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const TransformOperations& other) const {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Transform dummy;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return BlendInternal(other, 0.5, &dummy);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TransformOperations::AppendTranslate(SkMScalar x,
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                          SkMScalar y,
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                          SkMScalar z) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperation to_add;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.matrix.Translate3d(x, y, z);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.type = TransformOperation::TransformOperationTranslate;
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.translate.x = x;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.translate.y = y;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.translate.z = z;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_.push_back(to_add);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decomposed_transform_dirty_ = true;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TransformOperations::AppendRotate(SkMScalar x,
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                       SkMScalar y,
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                       SkMScalar z,
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                       SkMScalar degrees) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperation to_add;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.matrix.RotateAbout(gfx::Vector3dF(x, y, z), degrees);
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.type = TransformOperation::TransformOperationRotate;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.rotate.axis.x = x;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.rotate.axis.y = y;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.rotate.axis.z = z;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.rotate.angle = degrees;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_.push_back(to_add);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decomposed_transform_dirty_ = true;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TransformOperations::AppendScale(SkMScalar x, SkMScalar y, SkMScalar z) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperation to_add;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.matrix.Scale3d(x, y, z);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.type = TransformOperation::TransformOperationScale;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.scale.x = x;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.scale.y = y;
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.scale.z = z;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_.push_back(to_add);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decomposed_transform_dirty_ = true;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TransformOperations::AppendSkew(SkMScalar x, SkMScalar y) {
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperation to_add;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.matrix.SkewX(x);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.matrix.SkewY(y);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.type = TransformOperation::TransformOperationSkew;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.skew.x = x;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.skew.y = y;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_.push_back(to_add);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decomposed_transform_dirty_ = true;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TransformOperations::AppendPerspective(SkMScalar depth) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperation to_add;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.matrix.ApplyPerspectiveDepth(depth);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.type = TransformOperation::TransformOperationPerspective;
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.perspective_depth = depth;
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_.push_back(to_add);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decomposed_transform_dirty_ = true;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TransformOperations::AppendMatrix(const gfx::Transform& matrix) {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TransformOperation to_add;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.matrix = matrix;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_add.type = TransformOperation::TransformOperationMatrix;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_.push_back(to_add);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  decomposed_transform_dirty_ = true;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TransformOperations::AppendIdentity() {
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operations_.push_back(TransformOperation());
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TransformOperations::IsIdentity() const {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < operations_.size(); ++i) {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!operations_[i].IsIdentity())
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TransformOperations::BlendInternal(const TransformOperations& from,
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                        SkMScalar progress,
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        gfx::Transform* result) const {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool from_identity = from.IsIdentity();
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool to_identity = IsIdentity();
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (from_identity && to_identity)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (MatchesTypes(from)) {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t num_operations =
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::max(from_identity ? 0 : from.operations_.size(),
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 to_identity ? 0 : operations_.size());
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < num_operations; ++i) {
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Transform blended;
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!TransformOperation::BlendTransformOperations(
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          from_identity ? 0 : &from.operations_[i],
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          to_identity ? 0 : &operations_[i],
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          progress,
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &blended))
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return false;
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result->PreconcatTransform(blended);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ComputeDecomposedTransform() || !from.ComputeDecomposedTransform())
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::DecomposedTransform to_return;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!gfx::BlendDecomposedTransforms(&to_return,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      *decomposed_transform_.get(),
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      *from.decomposed_transform_.get(),
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      progress))
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *result = ComposeTransform(to_return);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TransformOperations::ComputeDecomposedTransform() const {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (decomposed_transform_dirty_) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!decomposed_transform_)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      decomposed_transform_.reset(new gfx::DecomposedTransform());
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Transform transform = Apply();
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!gfx::DecomposeTransform(decomposed_transform_.get(), transform))
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    decomposed_transform_dirty_ = false;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
330