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 "RotateTransformOperation.h" 24 25 #include <algorithm> 26 #include <wtf/MathExtras.h> 27 28 using namespace std; 29 30 namespace WebCore { 31 32 PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity) 33 { 34 if (from && !from->isSameType(*this)) 35 return this; 36 37 if (blendToIdentity) 38 return RotateTransformOperation::create(m_x, m_y, m_z, m_angle - m_angle * progress, m_type); 39 40 const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from); 41 42 // Optimize for single axis rotation 43 if (!fromOp || (fromOp->m_x == 0 && fromOp->m_y == 0 && fromOp->m_z == 1) || 44 (fromOp->m_x == 0 && fromOp->m_y == 1 && fromOp->m_z == 0) || 45 (fromOp->m_x == 1 && fromOp->m_y == 0 && fromOp->m_z == 0)) { 46 double fromAngle = fromOp ? fromOp->m_angle : 0; 47 return RotateTransformOperation::create(fromOp ? fromOp->m_x : m_x, 48 fromOp ? fromOp->m_y : m_y, 49 fromOp ? fromOp->m_z : m_z, 50 fromAngle + (m_angle - fromAngle) * progress, m_type); 51 } 52 53 const RotateTransformOperation* toOp = this; 54 55 // Create the 2 rotation matrices 56 TransformationMatrix fromT; 57 TransformationMatrix toT; 58 fromT.rotate3d((float)(fromOp ? fromOp->m_x : 0), 59 (float)(fromOp ? fromOp->m_y : 0), 60 (float)(fromOp ? fromOp->m_z : 1), 61 (float)(fromOp ? fromOp->m_angle : 0)); 62 63 toT.rotate3d((float)(toOp ? toOp->m_x : 0), 64 (float)(toOp ? toOp->m_y : 0), 65 (float)(toOp ? toOp->m_z : 1), 66 (float)(toOp ? toOp->m_angle : 0)); 67 68 // Blend them 69 toT.blend(fromT, progress); 70 71 // Extract the result as a quaternion 72 TransformationMatrix::DecomposedType decomp; 73 toT.decompose(decomp); 74 75 // Convert that to Axis/Angle form 76 double x = -decomp.quaternionX; 77 double y = -decomp.quaternionY; 78 double z = -decomp.quaternionZ; 79 double length = sqrt(x * x + y * y + z * z); 80 double angle = 0; 81 82 if (length > 0.00001) { 83 x /= length; 84 y /= length; 85 z /= length; 86 angle = rad2deg(acos(decomp.quaternionW) * 2); 87 } else { 88 x = 0; 89 y = 0; 90 z = 1; 91 } 92 return RotateTransformOperation::create(x, y, z, angle, ROTATE_3D); 93 } 94 95 } // namespace WebCore 96