transform.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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)
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/point3_f.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/safe_integer_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/transform_util.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/gfx/vector3d_f.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Taken from SkMatrix44.
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst double kEpsilon = 1e-8;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double TanDegrees(double degrees) {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double radians = degrees * M_PI / 180;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::tan(radians);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Transform::Transform(
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double col1row1, double col2row1, double col3row1, double col4row1,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double col1row2, double col2row2, double col3row2, double col4row2,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double col1row3, double col2row3, double col3row3, double col4row3,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double col1row4, double col2row4, double col3row4, double col4row4)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : matrix_(SkMatrix44::kUninitialized_Constructor)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 0, col1row1);
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 0, col1row2);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 0, col1row3);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(3, 0, col1row4);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 1, col2row1);
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 1, col2row2);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 1, col2row3);
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(3, 1, col2row4);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 2, col3row1);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 2, col3row2);
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 2, col3row3);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(3, 2, col3row4);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 3, col4row1);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 3, col4row2);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 3, col4row3);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(3, 3, col4row4);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Transform::Transform(
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double col1row1, double col2row1,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double col1row2, double col2row2,
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double x_translation, double y_translation)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : matrix_(SkMatrix44::kIdentity_Constructor)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 0, col1row1);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 0, col1row2);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 1, col2row1);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 1, col2row2);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 3, x_translation);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 3, y_translation);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAboutXAxis(double degrees) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double radians = degrees * M_PI / 180;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cosTheta = std::cos(radians);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double sinTheta = std::sin(radians);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.set3x3(1, 0, 0,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, cosTheta, sinTheta,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, -sinTheta, cosTheta);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rot.set3x3(1, 0, 0,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, cosTheta, sinTheta,
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, -sinTheta, cosTheta);
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAboutYAxis(double degrees) {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double radians = degrees * M_PI / 180;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cosTheta = std::cos(radians);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double sinTheta = std::sin(radians);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Note carefully the placement of the -sinTheta for rotation about
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // y-axis is different than rotation about x-axis or z-axis.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.set3x3(cosTheta, 0, -sinTheta,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, 1, 0,
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     sinTheta, 0, cosTheta);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rot.set3x3(cosTheta, 0, -sinTheta,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, 1, 0,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               sinTheta, 0, cosTheta);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAboutZAxis(double degrees) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double radians = degrees * M_PI / 180;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cosTheta = std::cos(radians);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double sinTheta = std::sin(radians);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.set3x3(cosTheta, sinTheta, 0,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     -sinTheta, cosTheta, 0,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     0, 0, 1);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rot.set3x3(cosTheta, sinTheta, 0,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               -sinTheta, cosTheta, 0,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               0, 0, 1);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::RotateAbout(const Vector3dF& axis, double degrees) {
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity()) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()),
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  SkDoubleToMScalar(axis.y()),
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  SkDoubleToMScalar(axis.z()),
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  SkDoubleToMScalar(degrees));
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 rot(SkMatrix44::kUninitialized_Constructor);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rot.setRotateDegreesAbout(SkDoubleToMScalar(axis.x()),
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              SkDoubleToMScalar(axis.y()),
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              SkDoubleToMScalar(axis.z()),
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              SkDoubleToMScalar(degrees));
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(rot);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::Scale(double x, double y) {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.preScale(SkDoubleToMScalar(x), SkDoubleToMScalar(y), 1);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::Scale3d(double x, double y, double z) {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.preScale(SkDoubleToMScalar(x),
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SkDoubleToMScalar(y),
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   SkDoubleToMScalar(z));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::Translate(double x, double y) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.preTranslate(SkDoubleToMScalar(x), SkDoubleToMScalar(y), 0);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::Translate3d(double x, double y, double z) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.preTranslate(SkDoubleToMScalar(x),
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       SkDoubleToMScalar(y),
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       SkDoubleToMScalar(z));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::SkewX(double angle_x) {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.setDouble(0, 1, TanDegrees(angle_x));
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 skew(SkMatrix44::kIdentity_Constructor);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    skew.setDouble(0, 1, TanDegrees(angle_x));
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(skew);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::SkewY(double angle_y) {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.setDouble(1, 0, TanDegrees(angle_y));
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 skew(SkMatrix44::kIdentity_Constructor);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    skew.setDouble(1, 0, TanDegrees(angle_y));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(skew);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::ApplyPerspectiveDepth(double depth) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (depth == 0)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.setDouble(3, 2, -1.0 / depth);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkMatrix44 m(SkMatrix44::kIdentity_Constructor);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    m.setDouble(3, 2, -1.0 / depth);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matrix_.preConcat(m);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::PreconcatTransform(const Transform& transform) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.preConcat(transform.matrix_);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::ConcatTransform(const Transform& transform) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.postConcat(transform.matrix_);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::IsIdentityOrIntegerTranslation() const {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsIdentityOrTranslation())
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool no_fractional_translation =
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<int>(matrix_.getDouble(0, 3)) == matrix_.getDouble(0, 3) &&
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<int>(matrix_.getDouble(1, 3)) == matrix_.getDouble(1, 3) &&
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<int>(matrix_.getDouble(2, 3)) == matrix_.getDouble(2, 3);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return no_fractional_translation;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::IsBackFaceVisible() const {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute whether a layer with a forward-facing normal of (0, 0, 1, 0)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // would have its back face visible after applying the transform.
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is done by transforming the normal and seeing if the resulting z
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // value is positive or negative. However, note that transforming a normal
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // actually requires using the inverse-transpose of the original transform.
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We can avoid inverting and transposing the matrix since we know we want
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to transform only the specific normal vector (0, 0, 1, 0). In this case,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we only need the 3rd row, 3rd column of the inverse-transpose. We can
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // calculate only the 3rd row 3rd column element of the inverse, skipping
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // everything else.
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For more information, refer to:
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   http://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double determinant = matrix_.determinant();
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If matrix was not invertible, then just assume back face is not visible.
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (std::abs(determinant) <= kEpsilon)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute the cofactor of the 3rd row, 3rd column.
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_1 =
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 0) *
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 1) *
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 3);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_2 =
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 1) *
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 3) *
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 0);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_3 =
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 3) *
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 0) *
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 1);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_4 =
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 0) *
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 3) *
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 1);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_5 =
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 1) *
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 0) *
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 3);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor_part_6 =
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 3) *
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 1) *
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 0);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double cofactor33 =
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_1 +
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_2 +
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_3 -
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_4 -
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_5 -
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cofactor_part_6;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Technically the transformed z component is cofactor33 / determinant.  But
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we can avoid the costly division because we only care about the resulting
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // +/- sign; we can check this equivalently by multiplication.
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return cofactor33 * determinant < 0;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::GetInverse(Transform* transform) const {
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!matrix_.invert(&transform->matrix_)) {
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Initialize the return value to identity if this matrix turned
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // out to be un-invertible.
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    transform->MakeIdentity();
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool Transform::Preserves2dAxisAlignment() const {
3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Check whether an axis aligned 2-dimensional rect would remain axis-aligned
3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // after being transformed by this matrix (and implicitly projected by
3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // dropping any non-zero z-values).
3047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  //
3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // The 4th column can be ignored because translations don't affect axis
3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // alignment. The 3rd column can be ignored because we are assuming 2d
3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // inputs, where z-values will be zero. The 3rd row can also be ignored
3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // because we are assuming 2d outputs, and any resulting z-value is dropped
3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // anyway. For the inner 2x2 portion, the only effects that keep a rect axis
3107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // aligned are (1) swapping axes and (2) scaling axes. This can be checked by
3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // verifying only 1 element of every column and row is non-zero.  Degenerate
3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // cases that project the x or y dimension to zero are considered to preserve
3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // axis alignment.
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  //
3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the matrix does have perspective component that is affected by x or y
3167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // values: The current implementation conservatively assumes that axis
3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // alignment is not preserved.
3187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool has_x_or_y_perspective = matrix_.getDouble(3, 0) != 0 ||
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      matrix_.getDouble(3, 1) != 0;
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_row_0 = 0;
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_row_1 = 0;
3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_col_0 = 0;
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int num_non_zero_in_col_1 = 0;
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (std::abs(matrix_.getDouble(0, 0)) > kEpsilon) {
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_0++;
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_0++;
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (std::abs(matrix_.getDouble(0, 1)) > kEpsilon) {
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_0++;
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_1++;
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (std::abs(matrix_.getDouble(1, 0)) > kEpsilon) {
3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_1++;
3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_0++;
3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (std::abs(matrix_.getDouble(1, 1)) > kEpsilon) {
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_row_1++;
3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    num_non_zero_in_col_1++;
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return
3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_row_0 <= 1 &&
3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_row_1 <= 1 &&
3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_col_0 <= 1 &&
3517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      num_non_zero_in_col_1 <= 1 &&
3527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      !has_x_or_y_perspective;
3537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::Transpose() {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.transpose();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::FlattenTo2d() {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 0, 0.0);
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 1, 0.0);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(0, 2, 0.0);
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(1, 2, 0.0);
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 2, 1.0);
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(3, 2, 0.0);
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_.setDouble(2, 3, 0.0);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Transform::TransformPoint(Point& point) const {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(matrix_, point);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Transform::TransformPoint(Point3F& point) const {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(matrix_, point);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Transform::TransformPointReverse(Point& point) const {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sad): Try to avoid trying to invert the matrix.
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!matrix_.invert(&inverse))
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(inverse, point);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Transform::TransformPointReverse(Point3F& point) const {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sad): Try to avoid trying to invert the matrix.
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!matrix_.invert(&inverse))
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformPointInternal(inverse, point);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Transform::TransformRect(RectF* rect) const {
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect src = RectFToSkRect(*rect);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkMatrix& matrix = matrix_;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  matrix.mapRect(&src);
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *rect = SkRectToRectF(src);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::TransformRectReverse(RectF* rect) const {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matrix_.isIdentity())
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMatrix44 inverse(SkMatrix44::kUninitialized_Constructor);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!matrix_.invert(&inverse))
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkMatrix& matrix = inverse;
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect src = RectFToSkRect(*rect);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  matrix.mapRect(&src);
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *rect = SkRectToRectF(src);
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Transform::Blend(const Transform& from, double progress) {
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DecomposedTransform to_decomp;
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DecomposedTransform from_decomp;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!DecomposeTransform(&to_decomp, *this) ||
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !DecomposeTransform(&from_decomp, from))
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BlendDecomposedTransforms(&to_decomp, to_decomp, from_decomp, progress))
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix_ = ComposeTransform(to_decomp).matrix();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Transform::TransformPointInternal(const SkMatrix44& xform,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Point3F& point) const {
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (xform.isIdentity())
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMScalar p[4] = {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(point.x()),
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(point.y()),
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(point.z()),
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(1)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  xform.mapMScalars(p);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p[3] != 1 && abs(p[3]) > 0) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    point.SetPoint(p[0] / p[3], p[1] / p[3], p[2]/ p[3]);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    point.SetPoint(p[0], p[1], p[2]);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Transform::TransformPointInternal(const SkMatrix44& xform,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       Point& point) const {
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (xform.isIdentity())
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkMScalar p[4] = {
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(point.x()),
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(point.y()),
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(0),
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkDoubleToMScalar(1)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  xform.mapMScalars(p);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  point.SetPoint(ToRoundedInt(p[0]), ToRoundedInt(p[1]));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string Transform::ToString() const {
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::StringPrintf(
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "[ %+0.4f %+0.4f %+0.4f %+0.4f  \n"
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  %+0.4f %+0.4f %+0.4f %+0.4f  \n"
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  %+0.4f %+0.4f %+0.4f %+0.4f  \n"
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "  %+0.4f %+0.4f %+0.4f %+0.4f ]\n",
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 0),
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 1),
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 2),
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(0, 3),
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 0),
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 1),
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 2),
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(1, 3),
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(2, 0),
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(2, 1),
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(2, 2),
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(2, 3),
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 0),
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 1),
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 2),
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      matrix_.getDouble(3, 3));
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
499