// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CC_MATH_UTIL_H_ #define CC_MATH_UTIL_H_ #include "base/logging.h" #include "cc/cc_export.h" #include "ui/gfx/point_f.h" #include "ui/gfx/point3_f.h" #include "ui/gfx/transform.h" namespace WebKit { class WebTransformationMatrix; } namespace gfx { class QuadF; class Rect; class RectF; class Vector2dF; } namespace cc { struct HomogeneousCoordinate { HomogeneousCoordinate(double newX, double newY, double newZ, double newW) : x(newX) , y(newY) , z(newZ) , w(newW) { } bool shouldBeClipped() const { return w <= 0; } gfx::PointF cartesianPoint2d() const { if (w == 1) return gfx::PointF(x, y); // For now, because this code is used privately only by MathUtil, it should never be called when w == 0, and we do not yet need to handle that case. DCHECK(w); double invW = 1.0 / w; return gfx::PointF(x * invW, y * invW); } gfx::Point3F cartesianPoint3d() const { if (w == 1) return gfx::Point3F(x, y, z); // For now, because this code is used privately only by MathUtil, it should never be called when w == 0, and we do not yet need to handle that case. DCHECK(w); double invW = 1.0 / w; return gfx::Point3F(x * invW, y * invW, z * invW); } double x; double y; double z; double w; }; class CC_EXPORT MathUtil { public: static const double PI_DOUBLE; static const float PI_FLOAT; static const double EPSILON; static double Deg2Rad(double deg) { return deg * PI_DOUBLE / 180; } static double Rad2Deg(double rad) { return rad * 180 / PI_DOUBLE; } static float Deg2Rad(float deg) { return deg * PI_FLOAT / 180; } static float Rad2Deg(float rad) { return rad * 180 / PI_FLOAT; } // Background: WebTransformationMatrix code in WebCore does not do the right thing in // mapRect / mapQuad / projectQuad when there is a perspective projection that causes // one of the transformed vertices to go to w < 0. In those cases, it is necessary to // perform clipping in homogeneous coordinates, after applying the transform, before // dividing-by-w to convert to cartesian coordinates. // // These functions return the axis-aligned rect that encloses the correctly clipped, // transformed polygon. static gfx::Rect mapClippedRect(const WebKit::WebTransformationMatrix&, const gfx::Rect&); static gfx::RectF mapClippedRect(const WebKit::WebTransformationMatrix&, const gfx::RectF&); static gfx::RectF projectClippedRect(const WebKit::WebTransformationMatrix&, const gfx::RectF&); // Returns an array of vertices that represent the clipped polygon. After returning, indexes from // 0 to numVerticesInClippedQuad are valid in the clippedQuad array. Note that // numVerticesInClippedQuad may be zero, which means the entire quad was clipped, and // none of the vertices in the array are valid. static void mapClippedQuad(const WebKit::WebTransformationMatrix&, const gfx::QuadF& srcQuad, gfx::PointF clippedQuad[8], int& numVerticesInClippedQuad); static gfx::RectF computeEnclosingRectOfVertices(gfx::PointF vertices[], int numVertices); static gfx::RectF computeEnclosingClippedRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4); // NOTE: These functions do not do correct clipping against w = 0 plane, but they // correctly detect the clipped condition via the boolean clipped. static gfx::QuadF mapQuad(const WebKit::WebTransformationMatrix&, const gfx::QuadF&, bool& clipped); static gfx::PointF mapPoint(const WebKit::WebTransformationMatrix&, const gfx::PointF&, bool& clipped); static gfx::Point3F mapPoint(const WebKit::WebTransformationMatrix&, const gfx::Point3F&, bool& clipped); static gfx::QuadF projectQuad(const WebKit::WebTransformationMatrix&, const gfx::QuadF&, bool& clipped); static gfx::PointF projectPoint(const WebKit::WebTransformationMatrix&, const gfx::PointF&, bool& clipped); static void flattenTransformTo2d(WebKit::WebTransformationMatrix&); static gfx::Vector2dF computeTransform2dScaleComponents(const WebKit::WebTransformationMatrix&); // Returns the smallest angle between the given two vectors in degrees. Neither vector is // assumed to be normalized. static float smallestAngleBetweenVectors(gfx::Vector2dF, gfx::Vector2dF); // Projects the |source| vector onto |destination|. Neither vector is assumed to be normalized. static gfx::Vector2dF projectVector(gfx::Vector2dF source, gfx::Vector2dF destination); // Temporary API to ease migration from WebKit::WebTransformationMatrix // to gfx::Transform. // // TODO(shawnsingh, vollick) we should phase out as much as possible of // these temporary functions, putting functionality into gfx::Transform. static bool isInvertible(const gfx::Transform&); static bool isBackFaceVisible(const gfx::Transform&); static bool isIdentity(const gfx::Transform&); static bool isIdentityOrTranslation(const gfx::Transform&); static bool hasPerspective(const gfx::Transform&); static void makeIdentity(gfx::Transform*); static void rotateEulerAngles(gfx::Transform*, double eulerX, double eulerY, double eulerZ); static void rotateAxisAngle(gfx::Transform*, double i, double j, double k, double degrees); static gfx::Transform inverse(const gfx::Transform&); static gfx::Transform to2dTransform(const gfx::Transform&); // Note carefully: the args here are labeled as per Webcore indexing conventions. static gfx::Transform createGfxTransform(double m11, double m12, double m13, double m14, double m21, double m22, double m23, double m24, double m31, double m32, double m33, double m34, double m41, double m42, double m43, double m44); static gfx::Transform createGfxTransform(double a, double b, double c, double d, double e, double f); }; // TODO(shawnsingh, vollick) this is a temporary home, should eventually // be phased out in favor of gfx::Transform API. gfx::Transform CC_EXPORT operator*(const gfx::Transform&, const gfx::Transform&); } // namespace cc #endif // CC_MATH_UTIL_H_