| /* |
| * Copyright (C) 2009 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h" |
| |
| #include "third_party/blink/renderer/platform/transforms/rotation.h" |
| #include "ui/gfx/geometry/quaternion.h" |
| |
| #include <algorithm> |
| |
| namespace blink { |
| |
| scoped_refptr<TransformOperation> Matrix3DTransformOperation::Accumulate( |
| const TransformOperation& other_op) { |
| DCHECK(other_op.IsSameType(*this)); |
| const auto& other = To<Matrix3DTransformOperation>(other_op); |
| |
| // If either matrix is non-invertible, fail and fallback to replace. |
| if (!matrix_.IsInvertible() || !other.matrix_.IsInvertible()) |
| return nullptr; |
| |
| // Similar to interpolation, accumulating 3D matrices is done by decomposing |
| // them, accumulating the individual functions, and then recomposing. |
| |
| TransformationMatrix::DecomposedType from_decomp; |
| TransformationMatrix::DecomposedType to_decomp; |
| if (!matrix_.Decompose(from_decomp) || !other.matrix_.Decompose(to_decomp)) |
| return nullptr; |
| |
| // Scale is accumulated using 1-based addition. |
| from_decomp.scale_x += to_decomp.scale_x - 1; |
| from_decomp.scale_y += to_decomp.scale_y - 1; |
| from_decomp.scale_z += to_decomp.scale_z - 1; |
| |
| // Skew can be added. |
| from_decomp.skew_xy += to_decomp.skew_xy; |
| from_decomp.skew_xz += to_decomp.skew_xz; |
| from_decomp.skew_yz += to_decomp.skew_yz; |
| |
| // To accumulate quaternions, we multiply them. This is equivalent to 'adding' |
| // the rotations that they represent. |
| gfx::Quaternion from_quaternion( |
| from_decomp.quaternion_x, from_decomp.quaternion_y, |
| from_decomp.quaternion_z, from_decomp.quaternion_w); |
| gfx::Quaternion to_quaternion(to_decomp.quaternion_x, to_decomp.quaternion_y, |
| to_decomp.quaternion_z, to_decomp.quaternion_w); |
| |
| gfx::Quaternion result_quaternion = from_quaternion * to_quaternion; |
| from_decomp.quaternion_x = result_quaternion.x(); |
| from_decomp.quaternion_y = result_quaternion.y(); |
| from_decomp.quaternion_z = result_quaternion.z(); |
| from_decomp.quaternion_w = result_quaternion.w(); |
| |
| // Translate is a simple addition. |
| from_decomp.translate_x += to_decomp.translate_x; |
| from_decomp.translate_y += to_decomp.translate_y; |
| from_decomp.translate_z += to_decomp.translate_z; |
| |
| // We sum the perspective components; note that w is 1-based. |
| from_decomp.perspective_x += to_decomp.perspective_x; |
| from_decomp.perspective_y += to_decomp.perspective_y; |
| from_decomp.perspective_z += to_decomp.perspective_z; |
| from_decomp.perspective_w += to_decomp.perspective_w - 1; |
| |
| TransformationMatrix result; |
| result.Recompose(from_decomp); |
| return Matrix3DTransformOperation::Create(result); |
| } |
| |
| scoped_refptr<TransformOperation> Matrix3DTransformOperation::Blend( |
| const TransformOperation* from, |
| double progress, |
| bool blend_to_identity) { |
| DCHECK(!from || CanBlendWith(*from)); |
| |
| // Convert the TransformOperations into matrices. Fail the blend operation |
| // if either of the matrices is non-invertible. |
| FloatSize size; |
| TransformationMatrix from_t; |
| TransformationMatrix to_t; |
| if (from) { |
| from->Apply(from_t, size); |
| if (!from_t.IsInvertible()) |
| return nullptr; |
| } |
| |
| Apply(to_t, size); |
| if (!to_t.IsInvertible()) |
| return nullptr; |
| |
| if (blend_to_identity) |
| std::swap(from_t, to_t); |
| |
| to_t.Blend(from_t, progress); |
| return Matrix3DTransformOperation::Create(to_t); |
| } |
| |
| scoped_refptr<TransformOperation> Matrix3DTransformOperation::Zoom( |
| double factor) { |
| TransformationMatrix result = matrix_; |
| result.Zoom(factor); |
| return Create(result); |
| } |
| |
| } // namespace blink |