| Index: ui/gfx/transform.cc
|
| diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc
|
| index bfd137adc7344d7fb29f2c10fb0ddb7b3c32b8bf..5d4463efd077dda55454cd9459551b9b6876504a 100644
|
| --- a/ui/gfx/transform.cc
|
| +++ b/ui/gfx/transform.cc
|
| @@ -3,13 +3,33 @@
|
| // found in the LICENSE file.
|
|
|
| #include "ui/gfx/transform.h"
|
| -
|
| -#include <cmath>
|
| -
|
| -#include "ui/gfx/point.h"
|
| +#include "ui/gfx/point3.h"
|
| #include "ui/gfx/rect.h"
|
| #include "ui/gfx/skia_util.h"
|
|
|
| +namespace {
|
| +
|
| +static int SymmetricRound(float x) {
|
| + return static_cast<int>(
|
| + x > 0
|
| + ? std::floor(x + 0.5f)
|
| + : std::ceil(x - 0.5f));
|
| +}
|
| +
|
| +static const float EPSILON = 1e-6f;
|
| +
|
| +static bool ApproximatelyEqual(float a, float b) {
|
| + if (a == 0) {
|
| + return fabs(b) < EPSILON;
|
| + }
|
| + if (b == 0) {
|
| + return fabs(a) < EPSILON;
|
| + }
|
| + return fabs(a - b) / std::max(fabs(a), fabs(b)) < EPSILON;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| namespace ui {
|
|
|
| Transform::Transform() {
|
| @@ -18,97 +38,164 @@ Transform::Transform() {
|
|
|
| Transform::~Transform() {}
|
|
|
| +bool Transform::operator==(const Transform& rhs) const {
|
| + for (int i = 0; i < 4; ++i) {
|
| + for (int j = 0; j < 4; ++j) {
|
| + if (!ApproximatelyEqual(matrix_.get(i,j), rhs.matrix_.get(i,j))) {
|
| + return false;
|
| + }
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool Transform::operator!=(const Transform& rhs) const {
|
| + return !(*this == rhs);
|
| +}
|
| +
|
| void Transform::SetRotate(float degree) {
|
| - matrix_.setRotate(SkFloatToScalar(degree));
|
| + matrix_.setRotateDegreesAbout(0, 0, 1, SkFloatToScalar(degree));
|
| }
|
|
|
| void Transform::SetScaleX(float x) {
|
| - matrix_.setScaleX(SkFloatToScalar(x));
|
| + matrix_.set(0, 0, SkFloatToScalar(x));
|
| }
|
|
|
| void Transform::SetScaleY(float y) {
|
| - matrix_.setScaleY(SkFloatToScalar(y));
|
| + matrix_.set(1, 1, SkFloatToScalar(y));
|
| }
|
|
|
| void Transform::SetScale(float x, float y) {
|
| - matrix_.setScale(SkFloatToScalar(x), SkFloatToScalar(y));
|
| + matrix_.setScale(
|
| + SkFloatToScalar(x),
|
| + SkFloatToScalar(y),
|
| + matrix_.get(2, 2));
|
| }
|
|
|
| void Transform::SetTranslateX(float x) {
|
| - matrix_.setTranslateX(SkFloatToScalar(x));
|
| + matrix_.set(0, 3, SkFloatToScalar(x));
|
| }
|
|
|
| void Transform::SetTranslateY(float y) {
|
| - matrix_.setTranslateY(SkFloatToScalar(y));
|
| + matrix_.set(1, 3, SkFloatToScalar(y));
|
| }
|
|
|
| void Transform::SetTranslate(float x, float y) {
|
| - matrix_.setTranslate(SkFloatToScalar(x), SkFloatToScalar(y));
|
| + matrix_.setTranslate(
|
| + SkFloatToScalar(x),
|
| + SkFloatToScalar(y),
|
| + matrix_.get(2, 3));
|
| }
|
|
|
| void Transform::ConcatRotate(float degree) {
|
| - matrix_.postRotate(SkFloatToScalar(degree));
|
| + SkMatrix44 rot;
|
| + rot.setRotateDegreesAbout(0, 0, 1, SkFloatToScalar(degree));
|
| + matrix_.postConcat(rot);
|
| }
|
|
|
| void Transform::ConcatScale(float x, float y) {
|
| - matrix_.postScale(SkFloatToScalar(x), SkFloatToScalar(y));
|
| + SkMatrix44 scale;
|
| + scale.setScale(SkFloatToScalar(x), SkFloatToScalar(y), 1);
|
| + matrix_.postConcat(scale);
|
| }
|
|
|
| void Transform::ConcatTranslate(float x, float y) {
|
| - matrix_.postTranslate(SkFloatToScalar(x), SkFloatToScalar(y));
|
| + SkMatrix44 translate;
|
| + translate.setTranslate(SkFloatToScalar(x), SkFloatToScalar(y), 0);
|
| + matrix_.postConcat(translate);
|
| }
|
|
|
| -bool Transform::PreconcatTransform(const Transform& transform) {
|
| - return matrix_.setConcat(matrix_, transform.matrix_);
|
| +void Transform::PreconcatTransform(const Transform& transform) {
|
| + if (!transform.matrix_.isIdentity()) {
|
| + matrix_.preConcat(transform.matrix_);
|
| + }
|
| }
|
|
|
| -bool Transform::ConcatTransform(const Transform& transform) {
|
| - return matrix_.setConcat(transform.matrix_, matrix_);
|
| +void Transform::ConcatTransform(const Transform& transform) {
|
| + if (!transform.matrix_.isIdentity()) {
|
| + matrix_.postConcat(transform.matrix_);
|
| + }
|
| }
|
|
|
| bool Transform::HasChange() const {
|
| return !matrix_.isIdentity();
|
| }
|
|
|
| -bool Transform::TransformPoint(gfx::Point* point) const {
|
| - SkPoint skp;
|
| - matrix_.mapXY(SkIntToScalar(point->x()), SkIntToScalar(point->y()), &skp);
|
| - point->SetPoint(static_cast<int>(std::floor(skp.fX)),
|
| - static_cast<int>(std::floor(skp.fY)));
|
| +void Transform::TransformPoint(gfx::Point& point) const {
|
| + TransformPointInternal(matrix_, point);
|
| +}
|
| +
|
| +void Transform::TransformPoint(gfx::Point3f& point) const {
|
| + TransformPointInternal(matrix_, point);
|
| +}
|
| +
|
| +bool Transform::TransformPointReverse(gfx::Point& point) const {
|
| + // TODO(sad): Try to avoid trying to invert the matrix.
|
| + SkMatrix44 inverse;
|
| + if (!matrix_.invert(&inverse))
|
| + return false;
|
| +
|
| + TransformPointInternal(inverse, point);
|
| return true;
|
| }
|
|
|
| -bool Transform::TransformPointReverse(gfx::Point* point) const {
|
| - SkMatrix inverse;
|
| +bool Transform::TransformPointReverse(gfx::Point3f& point) const {
|
| // TODO(sad): Try to avoid trying to invert the matrix.
|
| - if (matrix_.invert(&inverse)) {
|
| - SkPoint skp;
|
| - inverse.mapXY(SkIntToScalar(point->x()), SkIntToScalar(point->y()), &skp);
|
| - point->SetPoint(static_cast<int>(std::floor(skp.fX)),
|
| - static_cast<int>(std::floor(skp.fY)));
|
| - return true;
|
| - }
|
| - return false;
|
| + SkMatrix44 inverse;
|
| + if (!matrix_.invert(&inverse))
|
| + return false;
|
| +
|
| + TransformPointInternal(inverse, point);
|
| + return true;
|
| }
|
|
|
| -bool Transform::TransformRect(gfx::Rect* rect) const {
|
| +void Transform::TransformRect(gfx::Rect* rect) const {
|
| SkRect src = gfx::RectToSkRect(*rect);
|
| - if (!matrix_.mapRect(&src))
|
| - return false;
|
| + const SkMatrix& matrix = matrix_;
|
| + matrix.mapRect(&src);
|
| *rect = gfx::SkRectToRect(src);
|
| - return true;
|
| }
|
|
|
| bool Transform::TransformRectReverse(gfx::Rect* rect) const {
|
| - SkMatrix inverse;
|
| + SkMatrix44 inverse;
|
| if (!matrix_.invert(&inverse))
|
| return false;
|
| -
|
| + const SkMatrix& matrix = inverse;
|
| SkRect src = gfx::RectToSkRect(*rect);
|
| - if (!inverse.mapRect(&src))
|
| - return false;
|
| + matrix.mapRect(&src);
|
| *rect = gfx::SkRectToRect(src);
|
| return true;
|
| }
|
|
|
| +void Transform::TransformPointInternal(const SkMatrix44& xform,
|
| + gfx::Point3f& point) const {
|
| + SkScalar p[4] = {
|
| + SkFloatToScalar(point.x()),
|
| + SkFloatToScalar(point.y()),
|
| + SkFloatToScalar(point.z()),
|
| + 1 };
|
| +
|
| + xform.map(p);
|
| +
|
| + if (p[3] != 1 && abs(p[3]) > 0) {
|
| + point.SetPoint(p[0] / p[3], p[1] / p[3], p[2]/ p[3]);
|
| + } else {
|
| + point.SetPoint(p[0], p[1], p[2]);
|
| + }
|
| +}
|
| +
|
| +void Transform::TransformPointInternal(const SkMatrix44& xform,
|
| + gfx::Point& point) const {
|
| + SkScalar p[4] = {
|
| + SkIntToScalar(point.x()),
|
| + SkIntToScalar(point.y()),
|
| + 0,
|
| + 1 };
|
| +
|
| + xform.map(p);
|
| +
|
| + point.SetPoint(SymmetricRound(p[0]),
|
| + SymmetricRound(p[1]));
|
| +}
|
| +
|
| } // namespace ui
|
|
|