diff options
Diffstat (limited to 'chromium/cc/animation/transform_operation.cc')
-rw-r--r-- | chromium/cc/animation/transform_operation.cc | 240 |
1 files changed, 187 insertions, 53 deletions
diff --git a/chromium/cc/animation/transform_operation.cc b/chromium/cc/animation/transform_operation.cc index dacea06d797..93f40f37f1a 100644 --- a/chromium/cc/animation/transform_operation.cc +++ b/chromium/cc/animation/transform_operation.cc @@ -2,14 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <algorithm> #include <cmath> #include <limits> +#include "base/logging.h" #include "cc/animation/transform_operation.h" +#include "ui/gfx/box_f.h" #include "ui/gfx/vector3d_f.h" namespace { -const double kAngleEpsilon = 1e-4; +const SkMScalar kAngleEpsilon = 1e-4; } namespace cc { @@ -24,10 +27,10 @@ static bool IsOperationIdentity(const TransformOperation* operation) { static bool ShareSameAxis(const TransformOperation* from, const TransformOperation* to, - double* axis_x, - double* axis_y, - double* axis_z, - double* angle_from) { + SkMScalar* axis_x, + SkMScalar* axis_y, + SkMScalar* axis_z, + SkMScalar* angle_from) { if (IsOperationIdentity(from) && IsOperationIdentity(to)) return false; @@ -47,20 +50,21 @@ static bool ShareSameAxis(const TransformOperation* from, return true; } - double length_2 = from->rotate.axis.x * from->rotate.axis.x + - from->rotate.axis.y * from->rotate.axis.y + - from->rotate.axis.z * from->rotate.axis.z; - double other_length_2 = to->rotate.axis.x * to->rotate.axis.x + - to->rotate.axis.y * to->rotate.axis.y + - to->rotate.axis.z * to->rotate.axis.z; + SkMScalar length_2 = from->rotate.axis.x * from->rotate.axis.x + + from->rotate.axis.y * from->rotate.axis.y + + from->rotate.axis.z * from->rotate.axis.z; + SkMScalar other_length_2 = to->rotate.axis.x * to->rotate.axis.x + + to->rotate.axis.y * to->rotate.axis.y + + to->rotate.axis.z * to->rotate.axis.z; if (length_2 <= kAngleEpsilon || other_length_2 <= kAngleEpsilon) return false; - double dot = to->rotate.axis.x * from->rotate.axis.x + - to->rotate.axis.y * from->rotate.axis.y + - to->rotate.axis.z * from->rotate.axis.z; - double error = std::abs(1.0 - (dot * dot) / (length_2 * other_length_2)); + SkMScalar dot = to->rotate.axis.x * from->rotate.axis.x + + to->rotate.axis.y * from->rotate.axis.y + + to->rotate.axis.z * from->rotate.axis.z; + SkMScalar error = + std::abs(SK_MScalar1 - (dot * dot) / (length_2 * other_length_2)); bool result = error < kAngleEpsilon; if (result) { *axis_x = to->rotate.axis.x; @@ -73,14 +77,16 @@ static bool ShareSameAxis(const TransformOperation* from, return result; } -static double BlendDoubles(double from, double to, double progress) { +static SkMScalar BlendSkMScalars(SkMScalar from, + SkMScalar to, + SkMScalar progress) { return from * (1 - progress) + to * progress; } bool TransformOperation::BlendTransformOperations( const TransformOperation* from, const TransformOperation* to, - double progress, + SkMScalar progress, gfx::Transform* result) { if (IsOperationIdentity(from) && IsOperationIdentity(to)) return true; @@ -94,26 +100,26 @@ bool TransformOperation::BlendTransformOperations( switch (interpolation_type) { case TransformOperation::TransformOperationTranslate: { - double from_x = IsOperationIdentity(from) ? 0 : from->translate.x; - double from_y = IsOperationIdentity(from) ? 0 : from->translate.y; - double from_z = IsOperationIdentity(from) ? 0 : from->translate.z; - double to_x = IsOperationIdentity(to) ? 0 : to->translate.x; - double to_y = IsOperationIdentity(to) ? 0 : to->translate.y; - double to_z = IsOperationIdentity(to) ? 0 : to->translate.z; - result->Translate3d(BlendDoubles(from_x, to_x, progress), - BlendDoubles(from_y, to_y, progress), - BlendDoubles(from_z, to_z, progress)); + SkMScalar from_x = IsOperationIdentity(from) ? 0 : from->translate.x; + SkMScalar from_y = IsOperationIdentity(from) ? 0 : from->translate.y; + SkMScalar from_z = IsOperationIdentity(from) ? 0 : from->translate.z; + SkMScalar to_x = IsOperationIdentity(to) ? 0 : to->translate.x; + SkMScalar to_y = IsOperationIdentity(to) ? 0 : to->translate.y; + SkMScalar to_z = IsOperationIdentity(to) ? 0 : to->translate.z; + result->Translate3d(BlendSkMScalars(from_x, to_x, progress), + BlendSkMScalars(from_y, to_y, progress), + BlendSkMScalars(from_z, to_z, progress)); break; } case TransformOperation::TransformOperationRotate: { - double axis_x = 0; - double axis_y = 0; - double axis_z = 1; - double from_angle = 0; - double to_angle = IsOperationIdentity(to) ? 0 : to->rotate.angle; + SkMScalar axis_x = 0; + SkMScalar axis_y = 0; + SkMScalar axis_z = 1; + SkMScalar from_angle = 0; + SkMScalar to_angle = IsOperationIdentity(to) ? 0 : to->rotate.angle; if (ShareSameAxis(from, to, &axis_x, &axis_y, &axis_z, &from_angle)) { result->RotateAbout(gfx::Vector3dF(axis_x, axis_y, axis_z), - BlendDoubles(from_angle, to_angle, progress)); + BlendSkMScalars(from_angle, to_angle, progress)); } else { gfx::Transform to_matrix; if (!IsOperationIdentity(to)) @@ -128,33 +134,35 @@ bool TransformOperation::BlendTransformOperations( break; } case TransformOperation::TransformOperationScale: { - double from_x = IsOperationIdentity(from) ? 1 : from->scale.x; - double from_y = IsOperationIdentity(from) ? 1 : from->scale.y; - double from_z = IsOperationIdentity(from) ? 1 : from->scale.z; - double to_x = IsOperationIdentity(to) ? 1 : to->scale.x; - double to_y = IsOperationIdentity(to) ? 1 : to->scale.y; - double to_z = IsOperationIdentity(to) ? 1 : to->scale.z; - result->Scale3d(BlendDoubles(from_x, to_x, progress), - BlendDoubles(from_y, to_y, progress), - BlendDoubles(from_z, to_z, progress)); + SkMScalar from_x = IsOperationIdentity(from) ? 1 : from->scale.x; + SkMScalar from_y = IsOperationIdentity(from) ? 1 : from->scale.y; + SkMScalar from_z = IsOperationIdentity(from) ? 1 : from->scale.z; + SkMScalar to_x = IsOperationIdentity(to) ? 1 : to->scale.x; + SkMScalar to_y = IsOperationIdentity(to) ? 1 : to->scale.y; + SkMScalar to_z = IsOperationIdentity(to) ? 1 : to->scale.z; + result->Scale3d(BlendSkMScalars(from_x, to_x, progress), + BlendSkMScalars(from_y, to_y, progress), + BlendSkMScalars(from_z, to_z, progress)); break; } case TransformOperation::TransformOperationSkew: { - double from_x = IsOperationIdentity(from) ? 0 : from->skew.x; - double from_y = IsOperationIdentity(from) ? 0 : from->skew.y; - double to_x = IsOperationIdentity(to) ? 0 : to->skew.x; - double to_y = IsOperationIdentity(to) ? 0 : to->skew.y; - result->SkewX(BlendDoubles(from_x, to_x, progress)); - result->SkewY(BlendDoubles(from_y, to_y, progress)); + SkMScalar from_x = IsOperationIdentity(from) ? 0 : from->skew.x; + SkMScalar from_y = IsOperationIdentity(from) ? 0 : from->skew.y; + SkMScalar to_x = IsOperationIdentity(to) ? 0 : to->skew.x; + SkMScalar to_y = IsOperationIdentity(to) ? 0 : to->skew.y; + result->SkewX(BlendSkMScalars(from_x, to_x, progress)); + result->SkewY(BlendSkMScalars(from_y, to_y, progress)); break; } case TransformOperation::TransformOperationPerspective: { - double from_perspective_depth = IsOperationIdentity(from) ? - std::numeric_limits<double>::max() : from->perspective_depth; - double to_perspective_depth = IsOperationIdentity(to) ? - std::numeric_limits<double>::max() : to->perspective_depth; - result->ApplyPerspectiveDepth( - BlendDoubles(from_perspective_depth, to_perspective_depth, progress)); + SkMScalar from_perspective_depth = + IsOperationIdentity(from) ? std::numeric_limits<SkMScalar>::max() + : from->perspective_depth; + SkMScalar to_perspective_depth = IsOperationIdentity(to) + ? std::numeric_limits<SkMScalar>::max() + : to->perspective_depth; + result->ApplyPerspectiveDepth(BlendSkMScalars( + from_perspective_depth, to_perspective_depth, progress)); break; } case TransformOperation::TransformOperationMatrix: { @@ -177,4 +185,130 @@ bool TransformOperation::BlendTransformOperations( return true; } +static void ApplyScaleToBox(float x_scale, + float y_scale, + float z_scale, + gfx::BoxF* box) { + if (x_scale < 0) + box->set_x(-box->right()); + if (y_scale < 0) + box->set_y(-box->bottom()); + if (z_scale < 0) + box->set_z(-box->front()); + box->Scale(std::abs(x_scale), std::abs(y_scale), std::abs(z_scale)); +} + +static void UnionBoxWithZeroScale(gfx::BoxF* box) { + float min_x = std::min(box->x(), 0.f); + float min_y = std::min(box->y(), 0.f); + float min_z = std::min(box->z(), 0.f); + float max_x = std::max(box->right(), 0.f); + float max_y = std::max(box->bottom(), 0.f); + float max_z = std::max(box->front(), 0.f); + *box = gfx::BoxF( + min_x, min_y, min_z, max_x - min_x, max_y - min_y, max_z - min_z); +} + +bool TransformOperation::BlendedBoundsForBox(const gfx::BoxF& box, + const TransformOperation* from, + const TransformOperation* to, + SkMScalar min_progress, + SkMScalar max_progress, + gfx::BoxF* bounds) { + bool is_identity_from = IsOperationIdentity(from); + bool is_identity_to = IsOperationIdentity(to); + if (is_identity_from && is_identity_to) { + *bounds = box; + return true; + } + + TransformOperation::Type interpolation_type = + TransformOperation::TransformOperationIdentity; + if (is_identity_to) + interpolation_type = from->type; + else + interpolation_type = to->type; + + switch (interpolation_type) { + case TransformOperation::TransformOperationTranslate: { + SkMScalar from_x, from_y, from_z; + if (is_identity_from) { + from_x = from_y = from_z = 0.0; + } else { + from_x = from->translate.x; + from_y = from->translate.y; + from_z = from->translate.z; + } + SkMScalar to_x, to_y, to_z; + if (is_identity_to) { + to_x = to_y = to_z = 0.0; + } else { + to_x = to->translate.x; + to_y = to->translate.y; + to_z = to->translate.z; + } + *bounds = box; + *bounds += gfx::Vector3dF(BlendSkMScalars(from_x, to_x, min_progress), + BlendSkMScalars(from_y, to_y, min_progress), + BlendSkMScalars(from_z, to_z, min_progress)); + gfx::BoxF bounds_max = box; + bounds_max += gfx::Vector3dF(BlendSkMScalars(from_x, to_x, max_progress), + BlendSkMScalars(from_y, to_y, max_progress), + BlendSkMScalars(from_z, to_z, max_progress)); + bounds->Union(bounds_max); + return true; + } + case TransformOperation::TransformOperationScale: { + SkMScalar from_x, from_y, from_z; + if (is_identity_from) { + from_x = from_y = from_z = 1.0; + } else { + from_x = from->scale.x; + from_y = from->scale.y; + from_z = from->scale.z; + } + SkMScalar to_x, to_y, to_z; + if (is_identity_to) { + to_x = to_y = to_z = 1.0; + } else { + to_x = to->scale.x; + to_y = to->scale.y; + to_z = to->scale.z; + } + *bounds = box; + ApplyScaleToBox( + SkMScalarToFloat(BlendSkMScalars(from_x, to_x, min_progress)), + SkMScalarToFloat(BlendSkMScalars(from_y, to_y, min_progress)), + SkMScalarToFloat(BlendSkMScalars(from_z, to_z, min_progress)), + bounds); + gfx::BoxF bounds_max = box; + ApplyScaleToBox( + SkMScalarToFloat(BlendSkMScalars(from_x, to_x, max_progress)), + SkMScalarToFloat(BlendSkMScalars(from_y, to_y, max_progress)), + SkMScalarToFloat(BlendSkMScalars(from_z, to_z, max_progress)), + &bounds_max); + if (!bounds->IsEmpty() && !bounds_max.IsEmpty()) { + bounds->Union(bounds_max); + } else if (!bounds->IsEmpty()) { + UnionBoxWithZeroScale(bounds); + } else if (!bounds_max.IsEmpty()) { + UnionBoxWithZeroScale(&bounds_max); + *bounds = bounds_max; + } + + return true; + } + case TransformOperation::TransformOperationIdentity: + *bounds = box; + return true; + case TransformOperation::TransformOperationRotate: + case TransformOperation::TransformOperationSkew: + case TransformOperation::TransformOperationPerspective: + case TransformOperation::TransformOperationMatrix: + return false; + } + NOTREACHED(); + return false; +} + } // namespace cc |