15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// MSVC++ requires this to be set before any other includes to get M_PI.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define _USE_MATH_DEFINES
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/transform.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cmath>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/logging.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/gfx/box_f.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/point3_f.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/safe_integer_conversions.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/transform_util.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/gfx/vector3d_f.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Taken from SkMatrix44.
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const SkMScalar kEpsilon = 1e-8f;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)SkMScalar TanDegrees(double degrees) {
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  double radians = degrees * M_PI / 180;
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return SkDoubleToMScalar(std::tan(radians));
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)inline bool ApproximatelyZero(SkMScalar x, SkMScalar tolerance) {
368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return std::abs(x) <= tolerance;
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)inline bool ApproximatelyOne(SkMScalar x, SkMScalar tolerance) {
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return std::abs(x - SkDoubleToMScalar(1.0)) <= tolerance;
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Transform::Transform(SkMScalar col1row1,
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col2row1,
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col3row1,
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col4row1,
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col1row2,
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col2row2,
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col3row2,
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col4row2,
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col1row3,
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col2row3,
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col3row3,
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col4row3,
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col1row4,
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col2row4,
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col3row4,
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col4row4)
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : matrix_(SkMatrix44::kUninitialized_Constructor) {
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 0, col1row1);
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 0, col1row2);
6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 0, col1row3);
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(3, 0, col1row4);
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 1, col2row1);
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 1, col2row2);
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 1, col2row3);
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(3, 1, col2row4);
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 2, col3row1);
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 2, col3row2);
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 2, col3row3);
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(3, 2, col3row4);
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 3, col4row1);
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 3, col4row2);
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 3, col4row3);
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(3, 3, col4row4);
8158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)Transform::Transform(SkMScalar col1row1,
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col2row1,
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col1row2,
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar col2row2,
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar x_translation,
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     SkMScalar y_translation)
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : matrix_(SkMatrix44::kIdentity_Constructor) {
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 0, col1row1);
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 0, col1row2);
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 1, col2row1);
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 1, col2row2);
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 3, x_translation);
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 3, y_translation);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAboutXAxis(double degrees) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double radians = degrees * M_PI / 180;
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SkMScalar cosTheta = SkDoubleToMScalar(std::cos(radians));
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SkMScalar sinTheta = SkDoubleToMScalar(std::sin(radians));
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.set3x3(1, 0, 0,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, cosTheta, sinTheta,
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, -sinTheta, cosTheta);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rot.set3x3(1, 0, 0,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, cosTheta, sinTheta,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, -sinTheta, cosTheta);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAboutYAxis(double degrees) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double radians = degrees * M_PI / 180;
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SkMScalar cosTheta = SkDoubleToMScalar(std::cos(radians));
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SkMScalar sinTheta = SkDoubleToMScalar(std::sin(radians));
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Note carefully the placement of the -sinTheta for rotation about
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // y-axis is different than rotation about x-axis or z-axis.
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.set3x3(cosTheta, 0, -sinTheta,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, 1, 0,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     sinTheta, 0, cosTheta);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rot.set3x3(cosTheta, 0, -sinTheta,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, 1, 0,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               sinTheta, 0, cosTheta);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAboutZAxis(double degrees) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double radians = degrees * M_PI / 180;
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SkMScalar cosTheta = SkDoubleToMScalar(std::cos(radians));
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  SkMScalar sinTheta = SkDoubleToMScalar(std::sin(radians));
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.set3x3(cosTheta, sinTheta, 0,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     -sinTheta, cosTheta, 0,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, 0, 1);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rot.set3x3(cosTheta, sinTheta, 0,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               -sinTheta, cosTheta, 0,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, 0, 1);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAbout(const Vector3dF& axis, double degrees) {
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    matrix_.setRotateDegreesAbout(SkFloatToMScalar(axis.x()),
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  SkFloatToMScalar(axis.y()),
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  SkFloatToMScalar(axis.z()),
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                  degrees);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    rot.setRotateDegreesAbout(SkFloatToMScalar(axis.x()),
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              SkFloatToMScalar(axis.y()),
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              SkFloatToMScalar(axis.z()),
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                              degrees);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void Transform::Scale(SkMScalar x, SkMScalar y) { matrix_.preScale(x, y, 1); }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void Transform::Scale3d(SkMScalar x, SkMScalar y, SkMScalar z) {
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.preScale(x, y, z);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void Transform::Translate(SkMScalar x, SkMScalar y) {
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.preTranslate(x, y, 0);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void Transform::Translate3d(SkMScalar x, SkMScalar y, SkMScalar z) {
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.preTranslate(x, y, z);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void Transform::SkewX(double angle_x) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    matrix_.set(0, 1, TanDegrees(angle_x));
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 skew(SkMatrix44::kIdentity_Constructor);
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    skew.set(0, 1, TanDegrees(angle_x));
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(skew);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void Transform::SkewY(double angle_y) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    matrix_.set(1, 0, TanDegrees(angle_y));
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 skew(SkMatrix44::kIdentity_Constructor);
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    skew.set(1, 0, TanDegrees(angle_y));
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(skew);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void Transform::ApplyPerspectiveDepth(SkMScalar depth) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (depth == 0)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    matrix_.set(3, 2, -1.0 / depth);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 m(SkMatrix44::kIdentity_Constructor);
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    m.set(3, 2, -1.0 / depth);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(m);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::PreconcatTransform(const Transform& transform) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.preConcat(transform.matrix_);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::ConcatTransform(const Transform& transform) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.postConcat(transform.matrix_);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool Transform::IsApproximatelyIdentityOrTranslation(
2228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    SkMScalar tolerance) const {
2238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK_GE(tolerance, 0);
2248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return
2258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyOne(matrix_.get(0, 0), tolerance) &&
2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyZero(matrix_.get(1, 0), tolerance) &&
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyZero(matrix_.get(2, 0), tolerance) &&
2288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      matrix_.get(3, 0) == 0 &&
2298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyZero(matrix_.get(0, 1), tolerance) &&
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyOne(matrix_.get(1, 1), tolerance) &&
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyZero(matrix_.get(2, 1), tolerance) &&
2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      matrix_.get(3, 1) == 0 &&
2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyZero(matrix_.get(0, 2), tolerance) &&
2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyZero(matrix_.get(1, 2), tolerance) &&
2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ApproximatelyOne(matrix_.get(2, 2), tolerance) &&
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      matrix_.get(3, 2) == 0 &&
2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      matrix_.get(3, 3) == 1;
2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::IsIdentityOrIntegerTranslation() const {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsIdentityOrTranslation())
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool no_fractional_translation =
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      static_cast<int>(matrix_.get(0, 3)) == matrix_.get(0, 3) &&
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      static_cast<int>(matrix_.get(1, 3)) == matrix_.get(1, 3) &&
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      static_cast<int>(matrix_.get(2, 3)) == matrix_.get(2, 3);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return no_fractional_translation;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::IsBackFaceVisible() const {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute whether a layer with a forward-facing normal of (0, 0, 1, 0)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // would have its back face visible after applying the transform.
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is done by transforming the normal and seeing if the resulting z
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // value is positive or negative. However, note that transforming a normal
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // actually requires using the inverse-transpose of the original transform.
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We can avoid inverting and transposing the matrix since we know we want
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to transform only the specific normal vector (0, 0, 1, 0). In this case,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we only need the 3rd row, 3rd column of the inverse-transpose. We can
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // calculate only the 3rd row 3rd column element of the inverse, skipping
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // everything else.
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For more information, refer to:
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   http://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double determinant = matrix_.determinant();
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If matrix was not invertible, then just assume back face is not visible.
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (std::abs(determinant) <= kEpsilon)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute the cofactor of the 3rd row, 3rd column.
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_1 =
28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 0) * matrix_.get(1, 1) * matrix_.get(3, 3);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_2 =
28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 1) * matrix_.get(1, 3) * matrix_.get(3, 0);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_3 =
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 3) * matrix_.get(1, 0) * matrix_.get(3, 1);
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_4 =
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 0) * matrix_.get(1, 3) * matrix_.get(3, 1);
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_5 =
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 1) * matrix_.get(1, 0) * matrix_.get(3, 3);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_6 =
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 3) * matrix_.get(1, 1) * matrix_.get(3, 0);
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor33 =
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_1 +
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_2 +
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_3 -
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_4 -
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_5 -
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_6;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Technically the transformed z component is cofactor33 / determinant.  But
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we can avoid the costly division because we only care about the resulting
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // +/- sign; we can check this equivalently by multiplication.
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cofactor33 * determinant < 0;
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::GetInverse(Transform* transform) const {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!matrix_.invert(&transform->matrix_)) {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Initialize the return value to identity if this matrix turned
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // out to be un-invertible.
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    transform->MakeIdentity();
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool Transform::Preserves2dAxisAlignment() const {
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Check whether an axis aligned 2-dimensional rect would remain axis-aligned
3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // after being transformed by this matrix (and implicitly projected by
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // dropping any non-zero z-values).
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  //
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The 4th column can be ignored because translations don't affect axis
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // alignment. The 3rd column can be ignored because we are assuming 2d
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // inputs, where z-values will be zero. The 3rd row can also be ignored
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // because we are assuming 2d outputs, and any resulting z-value is dropped
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // anyway. For the inner 2x2 portion, the only effects that keep a rect axis
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // aligned are (1) swapping axes and (2) scaling axes. This can be checked by
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // verifying only 1 element of every column and row is non-zero.  Degenerate
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // cases that project the x or y dimension to zero are considered to preserve
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // axis alignment.
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  //
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the matrix does have perspective component that is affected by x or y
3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // values: The current implementation conservatively assumes that axis
3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // alignment is not preserved.
3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool has_x_or_y_perspective =
34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(3, 0) != 0 || matrix_.get(3, 1) != 0;
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_row_0 = 0;
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_row_1 = 0;
3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_col_0 = 0;
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_col_1 = 0;
3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (std::abs(matrix_.get(0, 0)) > kEpsilon) {
3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_0++;
3517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_0++;
3527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (std::abs(matrix_.get(0, 1)) > kEpsilon) {
3557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_0++;
3567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_1++;
3577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (std::abs(matrix_.get(1, 0)) > kEpsilon) {
3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_1++;
3617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_0++;
3627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (std::abs(matrix_.get(1, 1)) > kEpsilon) {
3657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_1++;
3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_1++;
3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_row_0 <= 1 &&
3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_row_1 <= 1 &&
3727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_col_0 <= 1 &&
3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_col_1 <= 1 &&
3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      !has_x_or_y_perspective;
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::Transpose() {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.transpose();
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::FlattenTo2d() {
38258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 0, 0.0);
38358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 1, 0.0);
38458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(0, 2, 0.0);
38558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(1, 2, 0.0);
38658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 2, 1.0);
38758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(3, 2, 0.0);
38858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  matrix_.set(2, 3, 0.0);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)Vector2dF Transform::To2dTranslation() const {
39258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return gfx::Vector2dF(SkMScalarToFloat(matrix_.get(0, 3)),
39358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                        SkMScalarToFloat(matrix_.get(1, 3)));
3943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void Transform::TransformPoint(Point* point) const {
397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(point);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(matrix_, point);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void Transform::TransformPoint(Point3F* point) const {
402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(point);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(matrix_, point);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool Transform::TransformPointReverse(Point* point) const {
407d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(point);
408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sad): Try to avoid trying to invert the matrix.
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!matrix_.invert(&inverse))
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(inverse, point);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool Transform::TransformPointReverse(Point3F* point) const {
419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(point);
420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sad): Try to avoid trying to invert the matrix.
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!matrix_.invert(&inverse))
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(inverse, point);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::TransformRect(RectF* rect) const {
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect src = RectFToSkRect(*rect);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkMatrix& matrix = matrix_;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  matrix.mapRect(&src);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *rect = SkRectToRectF(src);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::TransformRectReverse(RectF* rect) const {
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!matrix_.invert(&inverse))
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkMatrix& matrix = inverse;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect src = RectFToSkRect(*rect);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  matrix.mapRect(&src);
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *rect = SkRectToRectF(src);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void Transform::TransformBox(BoxF* box) const {
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BoxF bounds;
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool first_point = true;
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (int corner = 0; corner < 8; ++corner) {
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    gfx::Point3F point = box->origin();
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    point += gfx::Vector3dF(corner & 1 ? box->width() : 0.f,
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            corner & 2 ? box->height() : 0.f,
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            corner & 4 ? box->depth() : 0.f);
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    TransformPoint(&point);
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (first_point) {
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      bounds.set_origin(point);
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      first_point = false;
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      bounds.ExpandTo(point);
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *box = bounds;
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Transform::TransformBoxReverse(BoxF* box) const {
4754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Transform inverse = *this;
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!GetInverse(&inverse))
4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  inverse.TransformBox(box);
4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
48268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool Transform::Blend(const Transform& from, double progress) {
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DecomposedTransform to_decomp;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DecomposedTransform from_decomp;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!DecomposeTransform(&to_decomp, *this) ||
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !DecomposeTransform(&from_decomp, from))
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BlendDecomposedTransforms(&to_decomp, to_decomp, from_decomp, progress))
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_ = ComposeTransform(to_decomp).matrix();
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Transform::TransformPointInternal(const SkMatrix44& xform,
497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       Point3F* point) const {
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (xform.isIdentity())
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SkMScalar p[4] = {SkFloatToMScalar(point->x()), SkFloatToMScalar(point->y()),
502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    SkFloatToMScalar(point->z()), 1};
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  xform.mapMScalars(p);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (p[3] != SK_MScalar1 && p[3] != 0.f) {
5078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    float w_inverse = SK_MScalar1 / p[3];
5088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    point->SetPoint(p[0] * w_inverse, p[1] * w_inverse, p[2] * w_inverse);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    point->SetPoint(p[0], p[1], p[2]);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Transform::TransformPointInternal(const SkMatrix44& xform,
515d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                       Point* point) const {
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (xform.isIdentity())
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
519d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  SkMScalar p[4] = {SkFloatToMScalar(point->x()), SkFloatToMScalar(point->y()),
520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    0, 1};
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  xform.mapMScalars(p);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
524d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  point->SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1]));
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string Transform::ToString() const {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::StringPrintf(
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "[ %+0.4f %+0.4f %+0.4f %+0.4f  \n"
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  %+0.4f %+0.4f %+0.4f %+0.4f  \n"
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  %+0.4f %+0.4f %+0.4f %+0.4f  \n"
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  %+0.4f %+0.4f %+0.4f %+0.4f ]\n",
53358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 0),
53458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 1),
53558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 2),
53658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(0, 3),
53758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(1, 0),
53858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(1, 1),
53958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(1, 2),
54058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(1, 3),
54158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(2, 0),
54258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(2, 1),
54358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(2, 2),
54458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(2, 3),
54558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(3, 0),
54658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(3, 1),
54758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(3, 2),
54858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      matrix_.get(3, 3));
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
552