blob: f02ea5f9e9fb43781ae063a3e02956fe5b8d3339 [file] [log] [blame]
/*
* Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "third_party/blink/renderer/platform/transforms/rotate_transform_operation.h"
#include "third_party/blink/renderer/platform/geometry/blend.h"
namespace blink {
bool RotateTransformOperation::operator==(
const TransformOperation& other) const {
if (!IsSameType(other))
return false;
const Rotation& other_rotation = ToRotateTransformOperation(other).rotation_;
return rotation_.axis == other_rotation.axis &&
rotation_.angle == other_rotation.angle;
}
bool RotateTransformOperation::GetCommonAxis(const RotateTransformOperation* a,
const RotateTransformOperation* b,
FloatPoint3D& result_axis,
double& result_angle_a,
double& result_angle_b) {
return Rotation::GetCommonAxis(a ? a->rotation_ : Rotation(),
b ? b->rotation_ : Rotation(), result_axis,
result_angle_a, result_angle_b);
}
scoped_refptr<TransformOperation> RotateTransformOperation::Blend(
const TransformOperation* from,
double progress,
bool blend_to_identity) {
if (from && !IsMatchingOperationType(from->GetType()))
return this;
if (blend_to_identity)
return RotateTransformOperation::Create(
Rotation(Axis(), Angle() * (1 - progress)), type_);
// Optimize for single axis rotation
if (!from)
return RotateTransformOperation::Create(
Rotation(Axis(), Angle() * progress), type_);
// Apply spherical linear interpolation. Rotate around a common axis if
// possible. Otherwise, convert rotations to 4x4 matrix representations and
// interpolate the matrix decompositions. The 'from' and 'to' transforms can
// be of different types (based on axis), but must both have equivalent
// rotate3d representations.
DCHECK(from->PrimitiveType() == OperationType::kRotate3D);
OperationType type =
from->IsSameType(*this) ? type_ : OperationType::kRotate3D;
const RotateTransformOperation& from_rotate =
ToRotateTransformOperation(*from);
return RotateTransformOperation::Create(
Rotation::Slerp(from_rotate.rotation_, rotation_, progress), type);
}
bool RotateTransformOperation::CanBlendWith(
const TransformOperation& other) const {
return other.IsSameType(*this);
}
RotateAroundOriginTransformOperation::RotateAroundOriginTransformOperation(
double angle,
double origin_x,
double origin_y)
: RotateTransformOperation(Rotation(FloatPoint3D(0, 0, 1), angle),
kRotateAroundOrigin),
origin_x_(origin_x),
origin_y_(origin_y) {}
void RotateAroundOriginTransformOperation::Apply(
TransformationMatrix& transform,
const FloatSize& box_size) const {
transform.Translate(origin_x_, origin_y_);
RotateTransformOperation::Apply(transform, box_size);
transform.Translate(-origin_x_, -origin_y_);
}
bool RotateAroundOriginTransformOperation::operator==(
const TransformOperation& other) const {
if (!IsSameType(other))
return false;
const RotateAroundOriginTransformOperation& other_rotate =
ToRotateAroundOriginTransformOperation(other);
const Rotation& other_rotation = other_rotate.rotation_;
return rotation_.axis == other_rotation.axis &&
rotation_.angle == other_rotation.angle &&
origin_x_ == other_rotate.origin_x_ &&
origin_y_ == other_rotate.origin_y_;
}
scoped_refptr<TransformOperation> RotateAroundOriginTransformOperation::Blend(
const TransformOperation* from,
double progress,
bool blend_to_identity) {
if (from && !from->IsSameType(*this))
return this;
if (blend_to_identity) {
return RotateAroundOriginTransformOperation::Create(
Angle() * (1 - progress), origin_x_, origin_y_);
}
if (!from) {
return RotateAroundOriginTransformOperation::Create(Angle() * progress,
origin_x_, origin_y_);
}
const RotateAroundOriginTransformOperation& from_rotate =
ToRotateAroundOriginTransformOperation(*from);
return RotateAroundOriginTransformOperation::Create(
blink::Blend(from_rotate.Angle(), Angle(), progress),
blink::Blend(from_rotate.origin_x_, origin_x_, progress),
blink::Blend(from_rotate.origin_y_, origin_y_, progress));
}
scoped_refptr<TransformOperation> RotateAroundOriginTransformOperation::Zoom(
double factor) {
return Create(Angle(), origin_x_ * factor, origin_y_ * factor);
}
} // namespace blink