1 /* 2 * Copyright (C) 1999 Antti Koivisto (koivisto (at) kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 * 20 */ 21 22 #include "config.h" 23 #include "core/platform/graphics/transforms/RotateTransformOperation.h" 24 25 #include <algorithm> 26 #include "core/platform/animation/AnimationUtilities.h" 27 #include "wtf/MathExtras.h" 28 29 using namespace std; 30 31 namespace WebCore { 32 33 PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) 34 { 35 if (from && !from->isSameType(*this)) 36 return this; 37 38 if (blendToIdentity) 39 return RotateTransformOperation::create(m_x, m_y, m_z, m_angle - m_angle * progress, m_type); 40 41 const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from); 42 43 // Optimize for single axis rotation 44 if (!fromOp || (fromOp->m_x == 0 && fromOp->m_y == 0 && fromOp->m_z == 1) || 45 (fromOp->m_x == 0 && fromOp->m_y == 1 && fromOp->m_z == 0) || 46 (fromOp->m_x == 1 && fromOp->m_y == 0 && fromOp->m_z == 0)) { 47 double fromAngle = fromOp ? fromOp->m_angle : 0; 48 return RotateTransformOperation::create(fromOp ? fromOp->m_x : m_x, 49 fromOp ? fromOp->m_y : m_y, 50 fromOp ? fromOp->m_z : m_z, 51 WebCore::blend(fromAngle, m_angle, progress), m_type); 52 } 53 54 const RotateTransformOperation* toOp = this; 55 56 // Create the 2 rotation matrices 57 TransformationMatrix fromT; 58 TransformationMatrix toT; 59 fromT.rotate3d((fromOp ? fromOp->m_x : 0), 60 (fromOp ? fromOp->m_y : 0), 61 (fromOp ? fromOp->m_z : 1), 62 (fromOp ? fromOp->m_angle : 0)); 63 64 toT.rotate3d((toOp ? toOp->m_x : 0), 65 (toOp ? toOp->m_y : 0), 66 (toOp ? toOp->m_z : 1), 67 (toOp ? toOp->m_angle : 0)); 68 69 // Blend them 70 toT.blend(fromT, progress); 71 72 // Extract the result as a quaternion 73 TransformationMatrix::DecomposedType decomp; 74 toT.decompose(decomp); 75 76 // Convert that to Axis/Angle form 77 double x = -decomp.quaternionX; 78 double y = -decomp.quaternionY; 79 double z = -decomp.quaternionZ; 80 double length = sqrt(x * x + y * y + z * z); 81 double angle = 0; 82 83 if (length > 0.00001) { 84 x /= length; 85 y /= length; 86 z /= length; 87 angle = rad2deg(acos(decomp.quaternionW) * 2); 88 } else { 89 x = 0; 90 y = 0; 91 z = 1; 92 } 93 return RotateTransformOperation::create(x, y, z, angle, Rotate3D); 94 } 95 96 } // namespace WebCore 97