18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RotateTransformOperation.h"
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <algorithm>
268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <wtf/MathExtras.h>
278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianusing namespace std;
298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (from && !from->isSameType(*this))
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this;
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (blendToIdentity)
388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return RotateTransformOperation::create(m_x, m_y, m_z, m_angle - m_angle * progress, m_type);
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from);
418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Optimize for single axis rotation
438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!fromOp || (fromOp->m_x == 0 && fromOp->m_y == 0 && fromOp->m_z == 1) ||
448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   (fromOp->m_x == 0 && fromOp->m_y == 1 && fromOp->m_z == 0) ||
458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   (fromOp->m_x == 1 && fromOp->m_y == 0 && fromOp->m_z == 0)) {
468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        double fromAngle = fromOp ? fromOp->m_angle : 0;
478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return RotateTransformOperation::create(fromOp ? fromOp->m_x : m_x,
488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                                fromOp ? fromOp->m_y : m_y,
498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                                fromOp ? fromOp->m_z : m_z,
508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                                fromAngle + (m_angle - fromAngle) * progress, m_type);
518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    const RotateTransformOperation* toOp = this;
548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Create the 2 rotation matrices
568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix fromT;
578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix toT;
588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    fromT.rotate3d((float)(fromOp ? fromOp->m_x : 0),
598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   (float)(fromOp ? fromOp->m_y : 0),
608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   (float)(fromOp ? fromOp->m_z : 1),
618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                   (float)(fromOp ? fromOp->m_angle : 0));
628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    toT.rotate3d((float)(toOp ? toOp->m_x : 0),
648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                 (float)(toOp ? toOp->m_y : 0),
658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                 (float)(toOp ? toOp->m_z : 1),
668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                 (float)(toOp ? toOp->m_angle : 0));
678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Blend them
698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    toT.blend(fromT, progress);
708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Extract the result as a quaternion
728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    TransformationMatrix::DecomposedType decomp;
738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    toT.decompose(decomp);
748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Convert that to Axis/Angle form
768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double x = -decomp.quaternionX;
778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double y = -decomp.quaternionY;
788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double z = -decomp.quaternionZ;
798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double length = sqrt(x * x + y * y + z * z);
808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    double angle = 0;
818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (length > 0.00001) {
838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x /= length;
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y /= length;
858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z /= length;
868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        angle = rad2deg(acos(decomp.quaternionW) * 2);
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    } else {
888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        x = 0;
898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        y = 0;
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        z = 1;
918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return RotateTransformOperation::create(x, y, z, angle, ROTATE_3D);
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
96