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