[Win][Direct2D] Provide Direct2D-based geometry and transform cast operations
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Sep 2016 19:54:53 +0000 (19:54 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Sep 2016 19:54:53 +0000 (19:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161818

Reviewed by Dean Jackson.

Source/WebCore:

Tested by new TestWebKitAPI tests.

Add new casting operators to and from various Direct2D data types.

* PlatformWin.cmake:
* platform/graphics/FloatPoint.h:
(WebCore::FloatPoint::FloatPoint):
* platform/graphics/FloatRect.h:
* platform/graphics/FloatSize.h:
(WebCore::FloatSize::FloatSize):
* platform/graphics/IntPoint.h:
* platform/graphics/IntRect.h:
* platform/graphics/IntSize.h:
* platform/graphics/transforms/AffineTransform.h:
* platform/graphics/transforms/TransformationMatrix.h:
* platform/graphics/win/FloatPointDirect2D.cpp:
* platform/graphics/win/FloatRectDirect2D.cpp:
* platform/graphics/win/FloatSizeDirect2D.cpp:
* platform/graphics/win/IntPointWin.cpp:
(WebCore::IntPoint::IntPoint):
(WebCore::IntPoint::operator D2D1_POINT_2F):
(WebCore::IntPoint::operator D2D1_POINT_2U):
* platform/graphics/win/IntRectWin.cpp:
(WebCore::IntRect::IntRect):
(WebCore::IntRect::operator D2D1_RECT_F):
(WebCore::IntRect::operator D2D1_RECT_U):
* platform/graphics/win/IntSizeWin.cpp:
(WebCore::IntSize::IntSize):
(WebCore::IntSize::operator D2D1_SIZE_U):
(WebCore::IntSize::operator D2D1_SIZE_F):
* platform/graphics/win/TransformationMatrixDirect2D.cpp: Added.
(WebCore::TransformationMatrix::TransformationMatrix):
(WebCore::TransformationMatrix::operator D2D1_MATRIX_3X2_F):
(WebCore::AffineTransform::AffineTransform):
(WebCore::AffineTransform::operator D2D1_MATRIX_3X2_F):

Source/WebKit:

* PlatformWin.cmake: Link to Direct2D on Windows.

Tools:

Add several new test suites for the various geometric primitives in WebCore.

* TestWebKitAPI/PlatformWin.cmake: Add new files for test cases.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Ditto.
* TestWebKitAPI/Tests/WebCore/AffineTransform.cpp: Added.
* TestWebKitAPI/Tests/WebCore/FloatPoint.cpp: Added.
* TestWebKitAPI/Tests/WebCore/FloatRect.cpp: Added.
* TestWebKitAPI/Tests/WebCore/FloatSize.cpp: Added.
* TestWebKitAPI/Tests/WebCore/IntPoint.cpp: Added.
* TestWebKitAPI/Tests/WebCore/IntRect.cpp: Added.
* TestWebKitAPI/Tests/WebCore/IntSize.cpp: Added.
* TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp: Add some new
Windows-focused test cases.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@205871 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
Source/WebCore/ChangeLog
Source/WebCore/PlatformWin.cmake
Source/WebCore/platform/graphics/FloatPoint.h
Source/WebCore/platform/graphics/FloatRect.h
Source/WebCore/platform/graphics/FloatSize.h
Source/WebCore/platform/graphics/IntPoint.h
Source/WebCore/platform/graphics/IntRect.h
Source/WebCore/platform/graphics/IntSize.h
Source/WebCore/platform/graphics/transforms/AffineTransform.h
Source/WebCore/platform/graphics/transforms/TransformationMatrix.h
Source/WebCore/platform/graphics/win/FloatPointDirect2D.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/FloatRectDirect2D.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/FloatSizeDirect2D.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/win/IntPointWin.cpp
Source/WebCore/platform/graphics/win/IntRectWin.cpp
Source/WebCore/platform/graphics/win/IntSizeWin.cpp
Source/WebCore/platform/graphics/win/TransformationMatrixDirect2D.cpp [new file with mode: 0644]
Source/WebKit/ChangeLog
Source/WebKit/PlatformWin.cmake
Tools/ChangeLog
Tools/TestWebKitAPI/PlatformWin.cmake
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp

index f78b07c..417e38c 100644 (file)
@@ -1,3 +1,46 @@
+2016-09-12  Brent Fulgham  <bfulgham@apple.com>
+
+        [Win][Direct2D] Provide Direct2D-based geometry and transform cast operations
+        https://bugs.webkit.org/show_bug.cgi?id=161818
+
+        Reviewed by Dean Jackson.
+
+        Tested by new TestWebKitAPI tests.
+
+        Add new casting operators to and from various Direct2D data types.
+
+        * PlatformWin.cmake:
+        * platform/graphics/FloatPoint.h:
+        (WebCore::FloatPoint::FloatPoint):
+        * platform/graphics/FloatRect.h:
+        * platform/graphics/FloatSize.h:
+        (WebCore::FloatSize::FloatSize):
+        * platform/graphics/IntPoint.h:
+        * platform/graphics/IntRect.h:
+        * platform/graphics/IntSize.h:
+        * platform/graphics/transforms/AffineTransform.h:
+        * platform/graphics/transforms/TransformationMatrix.h:
+        * platform/graphics/win/FloatPointDirect2D.cpp:
+        * platform/graphics/win/FloatRectDirect2D.cpp:
+        * platform/graphics/win/FloatSizeDirect2D.cpp:
+        * platform/graphics/win/IntPointWin.cpp:
+        (WebCore::IntPoint::IntPoint):
+        (WebCore::IntPoint::operator D2D1_POINT_2F):
+        (WebCore::IntPoint::operator D2D1_POINT_2U):
+        * platform/graphics/win/IntRectWin.cpp:
+        (WebCore::IntRect::IntRect):
+        (WebCore::IntRect::operator D2D1_RECT_F):
+        (WebCore::IntRect::operator D2D1_RECT_U):
+        * platform/graphics/win/IntSizeWin.cpp:
+        (WebCore::IntSize::IntSize):
+        (WebCore::IntSize::operator D2D1_SIZE_U):
+        (WebCore::IntSize::operator D2D1_SIZE_F):
+        * platform/graphics/win/TransformationMatrixDirect2D.cpp: Added.
+        (WebCore::TransformationMatrix::TransformationMatrix):
+        (WebCore::TransformationMatrix::operator D2D1_MATRIX_3X2_F):
+        (WebCore::AffineTransform::AffineTransform):
+        (WebCore::AffineTransform::operator D2D1_MATRIX_3X2_F):
+
 2016-09-13  Tim Horton  <timothy_horton@apple.com>
 
         Undoing a candidate insertion results in the replaced text being selected
index 01edf15..99bd7b5 100644 (file)
@@ -87,6 +87,9 @@ list(APPEND WebCore_SOURCES
     platform/graphics/opentype/OpenTypeUtilities.cpp
 
     platform/graphics/win/DIBPixelData.cpp
+    platform/graphics/win/FloatPointDirect2D.cpp
+    platform/graphics/win/FloatRectDirect2D.cpp
+    platform/graphics/win/FloatSizeDirect2D.cpp
     platform/graphics/win/FontCacheWin.cpp
     platform/graphics/win/FontPlatformDataWin.cpp
     platform/graphics/win/FontWin.cpp
@@ -99,6 +102,7 @@ list(APPEND WebCore_SOURCES
     platform/graphics/win/IntSizeWin.cpp
     platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp
     platform/graphics/win/SimpleFontDataWin.cpp
+    platform/graphics/win/TransformationMatrixDirect2D.cpp
     platform/graphics/win/TransformationMatrixWin.cpp
     platform/graphics/win/UniscribeController.cpp
 
index 32a4a78..15f871a 100644 (file)
@@ -47,6 +47,10 @@ typedef struct _NSPoint NSPoint;
 #endif
 #endif // PLATFORM(MAC)
 
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
 namespace WebCore {
 
 class AffineTransform;
@@ -57,7 +61,7 @@ class TextStream;
 
 class FloatPoint {
 public:
-    FloatPoint() : m_x(0), m_y(0) { }
+    FloatPoint() { }
     FloatPoint(float x, float y) : m_x(x), m_y(y) { }
     WEBCORE_EXPORT FloatPoint(const IntPoint&);
     explicit FloatPoint(const FloatSize& size) : m_x(size.width()), m_y(size.height()) { }
@@ -107,7 +111,7 @@ public:
         m_y *= sy;
     }
 
-    void normalize();
+    WEBCORE_EXPORT void normalize();
 
     float dot(const FloatPoint& a) const
     {
@@ -148,11 +152,17 @@ public:
     WEBCORE_EXPORT operator NSPoint() const;
 #endif
 
-    FloatPoint matrixTransform(const TransformationMatrix&) const;
-    FloatPoint matrixTransform(const AffineTransform&) const;
+#if PLATFORM(WIN)
+    WEBCORE_EXPORT FloatPoint(const D2D_POINT_2F&);
+    WEBCORE_EXPORT operator D2D_POINT_2F() const;
+#endif
+
+    WEBCORE_EXPORT FloatPoint matrixTransform(const TransformationMatrix&) const;
+    WEBCORE_EXPORT FloatPoint matrixTransform(const AffineTransform&) const;
 
 private:
-    float m_x, m_y;
+    float m_x { 0 };
+    float m_y { 0 };
 };
 
 
index 2936b90..87c6df4 100644 (file)
@@ -45,6 +45,10 @@ typedef struct _NSRect NSRect;
 typedef struct _cairo_rectangle cairo_rectangle_t;
 #endif
 
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
 namespace WebCore {
 
 class IntRect;
@@ -138,7 +142,7 @@ public:
     WEBCORE_EXPORT void unite(const FloatRect&);
     void uniteEvenIfEmpty(const FloatRect&);
     void uniteIfNonZero(const FloatRect&);
-    void extend(const FloatPoint&);
+    WEBCORE_EXPORT void extend(const FloatPoint&);
 
     // Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version
     // is really checking for containment of 1x1 rect, but that doesn't make sense with floats.
@@ -163,9 +167,9 @@ public:
     FloatRect transposedRect() const { return FloatRect(m_location.transposedPoint(), m_size.transposedSize()); }
 
     // Re-initializes this rectangle to fit the sets of passed points.
-    void fitToPoints(const FloatPoint& p0, const FloatPoint& p1);
-    void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2);
-    void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3);
+    WEBCORE_EXPORT void fitToPoints(const FloatPoint& p0, const FloatPoint& p1);
+    WEBCORE_EXPORT void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2);
+    WEBCORE_EXPORT void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3);
 
 #if USE(CG)
     WEBCORE_EXPORT FloatRect(const CGRect&);
@@ -182,6 +186,11 @@ public:
     operator cairo_rectangle_t() const;
 #endif
 
+#if PLATFORM(WIN)
+    WEBCORE_EXPORT FloatRect(const D2D1_RECT_F&);
+    WEBCORE_EXPORT operator D2D1_RECT_F() const;
+#endif
+
     static FloatRect infiniteRect();
     bool isInfinite() const;
 
index b512644..d30e458 100644 (file)
@@ -47,6 +47,10 @@ typedef struct _NSSize NSSize;
 #endif
 #endif // PLATFORM(MAC)
 
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
 namespace WebCore {
 
 class IntSize;
@@ -54,7 +58,7 @@ class TextStream;
 
 class FloatSize {
 public:
-    FloatSize() : m_width(0), m_height(0) { }
+    FloatSize() { }
     FloatSize(float width, float height) : m_width(width), m_height(height) { }
     WEBCORE_EXPORT FloatSize(const IntSize&);
 
@@ -120,13 +124,18 @@ public:
 #endif
 
 #if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
-    WEBCORE_EXPORT explicit FloatSize(const NSSize &); // don't do this implicitly since it's lossy
+    WEBCORE_EXPORT explicit FloatSize(const NSSize&); // don't do this implicitly since it's lossy
     operator NSSize() const;
 #endif
 
+#if PLATFORM(WIN)
+    WEBCORE_EXPORT explicit FloatSize(const D2D1_SIZE_F&); // don't do this implicitly since it's lossy
+    operator D2D1_SIZE_F() const;
+#endif
+
 private:
-    float m_width;
-    float m_height;
+    float m_width { 0 };
+    float m_height { 0 };
 };
 
 inline FloatSize& operator+=(FloatSize& a, const FloatSize& b)
index 4fa9e5b..a86b21c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2006 Apple Inc.  All rights reserved.
+ * Copyright (C) 2004-2016 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #import <Foundation/NSGeometry.h>
 #endif
 
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
 #if USE(CG)
 typedef struct CGPoint CGPoint;
 #endif
@@ -62,8 +66,8 @@ class IntPoint {
 public:
     IntPoint() : m_x(0), m_y(0) { }
     IntPoint(int x, int y) : m_x(x), m_y(y) { }
-    explicit IntPoint(const IntSize& size) : m_x(size.width()), m_y(size.height()) { }
-    explicit IntPoint(const FloatPoint&); // don't do this implicitly since it's lossy
+    WEBCORE_EXPORT explicit IntPoint(const IntSize& size) : m_x(size.width()), m_y(size.height()) { }
+    WEBCORE_EXPORT explicit IntPoint(const FloatPoint&); // don't do this implicitly since it's lossy
 
     static IntPoint zero() { return IntPoint(); }
     bool isZero() const { return !m_x && !m_y; }
@@ -104,7 +108,7 @@ public:
         };
     }
 
-    IntPoint constrainedBetween(const IntPoint& min, const IntPoint& max) const;
+    WEBCORE_EXPORT IntPoint constrainedBetween(const IntPoint& min, const IntPoint& max) const;
 
     int distanceSquaredToPoint(const IntPoint&) const;
 
@@ -135,6 +139,11 @@ public:
     operator POINT() const;
     IntPoint(const POINTS&);
     operator POINTS() const;
+
+    IntPoint(const D2D1_POINT_2U&);
+    explicit IntPoint(const D2D1_POINT_2F&); // Don't do this implicitly, since it's lossy.
+    operator D2D1_POINT_2F() const;
+    operator D2D1_POINT_2U() const;
 #elif PLATFORM(EFL)
     explicit IntPoint(const Evas_Point&);
     operator Evas_Point() const;
index 1e40944..afb22d5 100644 (file)
 #include "IntPoint.h"
 #include "LayoutUnit.h"
 
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
 #if USE(CG)
 typedef struct CGRect CGRect;
 #endif
@@ -170,6 +174,10 @@ public:
 #if PLATFORM(WIN)
     IntRect(const RECT&);
     operator RECT() const;
+    explicit IntRect(const D2D1_RECT_F&);
+    IntRect(const D2D1_RECT_U&);
+    operator D2D1_RECT_F() const;
+    operator D2D1_RECT_U() const;
 #elif PLATFORM(EFL)
     explicit IntRect(const Eina_Rectangle&);
     operator Eina_Rectangle() const;
index 4f41161..4fd3ebe 100644 (file)
 #import <Foundation/NSGeometry.h>
 #endif
 
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
 #if USE(CG)
 typedef struct CGSize CGSize;
 #endif
@@ -123,7 +127,7 @@ public:
             m_height = minimumSize.height();
     }
 
-    IntSize constrainedBetween(const IntSize& min, const IntSize& max) const;
+    WEBCORE_EXPORT IntSize constrainedBetween(const IntSize& min, const IntSize& max) const;
 
     unsigned area() const
     {
@@ -153,6 +157,10 @@ public:
 #if PLATFORM(WIN)
     IntSize(const SIZE&);
     operator SIZE() const;
+    IntSize(const D2D1_SIZE_U&);
+    explicit IntSize(const D2D1_SIZE_F&); // don't do this implicitly since it's lossy;
+    operator D2D1_SIZE_U() const;
+    operator D2D1_SIZE_F() const;
 #endif
 
 private:
index e21549e..263b93c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006 Apple Inc.  All rights reserved.
+ * Copyright (C) 2005-2016 Apple Inc.  All rights reserved.
  *               2010 Dirk Schulze <krit@webkit.org>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,11 @@ typedef struct CGAffineTransform CGAffineTransform;
 #include <cairo.h>
 #endif
 
+#if PLATFORM(WIN)
+typedef struct D2D_MATRIX_3X2_F D2D_MATRIX_3X2_F;
+typedef D2D_MATRIX_3X2_F D2D1_MATRIX_3X2_F;
+#endif
+
 namespace WebCore {
 
 class FloatPoint;
@@ -57,7 +62,11 @@ public:
     WEBCORE_EXPORT AffineTransform(double a, double b, double c, double d, double e, double f);
 
 #if USE(CG)
-    AffineTransform(const CGAffineTransform&);
+    WEBCORE_EXPORT AffineTransform(const CGAffineTransform&);
+#endif
+
+#if PLATFORM(WIN)
+    AffineTransform(const D2D1_MATRIX_3X2_F&);
 #endif
 
     void setMatrix(double a, double b, double c, double d, double e, double f);
@@ -69,16 +78,16 @@ public:
 
     WEBCORE_EXPORT FloatPoint mapPoint(const FloatPoint&) const;
 
-    IntSize mapSize(const IntSize&) const;
+    WEBCORE_EXPORT IntSize mapSize(const IntSize&) const;
 
-    FloatSize mapSize(const FloatSize&) const;
+    WEBCORE_EXPORT FloatSize mapSize(const FloatSize&) const;
 
     // Rounds the resulting mapped rectangle out. This is helpful for bounding
     // box computations but may not be what is wanted in other contexts.
-    IntRect mapRect(const IntRect&) const;
+    WEBCORE_EXPORT IntRect mapRect(const IntRect&) const;
 
     WEBCORE_EXPORT FloatRect mapRect(const FloatRect&) const;
-    FloatQuad mapQuad(const FloatQuad&) const;
+    WEBCORE_EXPORT FloatQuad mapQuad(const FloatQuad&) const;
 
     WEBCORE_EXPORT bool isIdentity() const;
 
@@ -95,21 +104,21 @@ public:
     double f() const { return m_transform[5]; }
     void setF(double f) { m_transform[5] = f; }
 
-    void makeIdentity();
+    WEBCORE_EXPORT void makeIdentity();
 
     WEBCORE_EXPORT AffineTransform& multiply(const AffineTransform& other);
     WEBCORE_EXPORT AffineTransform& scale(double);
     AffineTransform& scale(double sx, double sy); 
-    AffineTransform& scaleNonUniform(double sx, double sy);
-    AffineTransform& scale(const FloatSize&);
-    AffineTransform& rotate(double d);
+    WEBCORE_EXPORT AffineTransform& scaleNonUniform(double sx, double sy);
+    WEBCORE_EXPORT AffineTransform& scale(const FloatSize&);
+    WEBCORE_EXPORT AffineTransform& rotate(double);
     AffineTransform& rotateFromVector(double x, double y);
     WEBCORE_EXPORT AffineTransform& translate(double tx, double ty);
-    AffineTransform& translate(const FloatPoint&);
-    AffineTransform& shear(double sx, double sy);
-    AffineTransform& flipX();
+    WEBCORE_EXPORT AffineTransform& translate(const FloatPoint&);
+    WEBCORE_EXPORT AffineTransform& shear(double sx, double sy);
+    WEBCORE_EXPORT AffineTransform& flipX();
     WEBCORE_EXPORT AffineTransform& flipY();
-    AffineTransform& skew(double angleX, double angleY);
+    WEBCORE_EXPORT AffineTransform& skew(double angleX, double angleY);
     AffineTransform& skewX(double angle);
     AffineTransform& skewY(double angle);
 
@@ -121,9 +130,9 @@ public:
     bool isInvertible() const; // If you call this this, you're probably doing it wrong.
     WEBCORE_EXPORT Optional<AffineTransform> inverse() const;
 
-    void blend(const AffineTransform& from, double progress);
+    WEBCORE_EXPORT void blend(const AffineTransform& from, double progress);
 
-    TransformationMatrix toTransformationMatrix() const;
+    WEBCORE_EXPORT TransformationMatrix toTransformationMatrix() const;
 
     bool isIdentityOrTranslation() const
     {
@@ -167,11 +176,15 @@ public:
     }
 
 #if USE(CG)
-    operator CGAffineTransform() const;
+    WEBCORE_EXPORT operator CGAffineTransform() const;
 #elif USE(CAIRO)
     operator cairo_matrix_t() const;
 #endif
 
+#if PLATFORM(WIN)
+    operator D2D1_MATRIX_3X2_F() const;
+#endif
+
     static AffineTransform translation(double x, double y)
     {
         return AffineTransform(1, 0, 0, 1, x, y);
@@ -192,7 +205,7 @@ private:
     std::array<double, 6> m_transform;
 };
 
-AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);
+WEBCORE_EXPORT AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest);
 
 WEBCORE_EXPORT TextStream& operator<<(TextStream&, const AffineTransform&);
 
index 548453d..1bcbe4d 100644 (file)
@@ -50,6 +50,11 @@ typedef struct tagXFORM XFORM;
 #endif
 #endif
 
+#if PLATFORM(WIN)
+typedef struct D2D_MATRIX_3X2_F D2D_MATRIX_3X2_F;
+typedef D2D_MATRIX_3X2_F D2D1_MATRIX_3X2_F;
+#endif
+
 namespace WebCore {
 
 class AffineTransform;
@@ -78,7 +83,7 @@ public:
 #endif
 
     TransformationMatrix() { makeIdentity(); }
-    TransformationMatrix(const AffineTransform& t);
+    WEBCORE_EXPORT TransformationMatrix(const AffineTransform&);
     TransformationMatrix(const TransformationMatrix& t) { *this = t; }
     TransformationMatrix(double a, double b, double c, double d, double e, double f) { setMatrix(a, b, c, d, e, f); }
     TransformationMatrix(double m11, double m12, double m13, double m14,
@@ -136,7 +141,7 @@ public:
 
     // Maps a 2D point through the transform, returning a 2D point.
     // Note that this ignores the z component, effectively projecting the point into the z=0 plane.
-    FloatPoint mapPoint(const FloatPoint&) const;
+    WEBCORE_EXPORT FloatPoint mapPoint(const FloatPoint&) const;
 
     // Like the version above, except that it rounds the mapped point to the nearest integer value.
     IntPoint mapPoint(const IntPoint& p) const
@@ -155,7 +160,7 @@ public:
 
     // If the matrix has 3D components, the z component of the result is
     // dropped, effectively projecting the quad into the z=0 plane.
-    FloatQuad mapQuad(const FloatQuad&) const;
+    WEBCORE_EXPORT FloatQuad mapQuad(const FloatQuad&) const;
 
     // Maps a point on the z=0 plane into a point on the plane with with the transform applied, by
     // extending a ray perpendicular to the source plane and computing the local x,y position of
@@ -219,16 +224,16 @@ public:
     void setF(double f) { m_matrix[3][1] = f; }
 
     // this = mat * this.
-    TransformationMatrix& multiply(const TransformationMatrix&);
+    WEBCORE_EXPORT TransformationMatrix& multiply(const TransformationMatrix&);
 
     WEBCORE_EXPORT TransformationMatrix& scale(double);
-    TransformationMatrix& scaleNonUniform(double sx, double sy);
+    WEBCORE_EXPORT TransformationMatrix& scaleNonUniform(double sx, double sy);
     TransformationMatrix& scale3d(double sx, double sy, double sz);
 
     // Angle is in degrees.
-    TransformationMatrix& rotate(double d) { return rotate3d(0, 0, d); }
+    WEBCORE_EXPORT TransformationMatrix& rotate(double d) { return rotate3d(0, 0, d); }
     TransformationMatrix& rotateFromVector(double x, double y);
-    TransformationMatrix& rotate3d(double rx, double ry, double rz);
+    WEBCORE_EXPORT TransformationMatrix& rotate3d(double rx, double ry, double rz);
     
     // The vector (x,y,z) is normalized if it's not already. A vector of (0,0,0) uses a vector of (0,0,1).
     TransformationMatrix& rotate3d(double x, double y, double z, double angle);
@@ -240,9 +245,9 @@ public:
     TransformationMatrix& translateRight(double tx, double ty);
     TransformationMatrix& translateRight3d(double tx, double ty, double tz);
     
-    TransformationMatrix& flipX();
-    TransformationMatrix& flipY();
-    TransformationMatrix& skew(double angleX, double angleY);
+    WEBCORE_EXPORT TransformationMatrix& flipX();
+    WEBCORE_EXPORT TransformationMatrix& flipY();
+    WEBCORE_EXPORT TransformationMatrix& skew(double angleX, double angleY);
     TransformationMatrix& skewX(double angle) { return skew(angle, 0); }
     TransformationMatrix& skewY(double angle) { return skew(0, angle); }
 
@@ -250,7 +255,7 @@ public:
     bool hasPerspective() const { return m_matrix[2][3] != 0.0f; }
 
     // Returns a transformation that maps a rect to a rect.
-    static TransformationMatrix rectToRect(const FloatRect&, const FloatRect&);
+    WEBCORE_EXPORT static TransformationMatrix rectToRect(const FloatRect&, const FloatRect&);
 
     bool isInvertible() const; // If you call this this, you're probably doing it wrong.
     WEBCORE_EXPORT Optional<TransformationMatrix> inverse() const;
@@ -295,8 +300,8 @@ public:
     void recompose4(const Decomposed4Type&);
 
     WEBCORE_EXPORT void blend(const TransformationMatrix& from, double progress);
-    void blend2(const TransformationMatrix& from, double progress);
-    void blend4(const TransformationMatrix& from, double progress);
+    WEBCORE_EXPORT void blend2(const TransformationMatrix& from, double progress);
+    WEBCORE_EXPORT void blend4(const TransformationMatrix& from, double progress);
 
     bool isAffine() const
     {
@@ -305,9 +310,9 @@ public:
     }
 
     // Throw away the non-affine parts of the matrix (lossy!).
-    void makeAffine();
+    WEBCORE_EXPORT void makeAffine();
 
-    AffineTransform toAffineTransform() const;
+    WEBCORE_EXPORT AffineTransform toAffineTransform() const;
 
     bool operator==(const TransformationMatrix& m2) const
     {
@@ -346,12 +351,12 @@ public:
     }
 
 #if USE(CA)
-    TransformationMatrix(const CATransform3D&);
+    WEBCORE_EXPORT TransformationMatrix(const CATransform3D&);
     WEBCORE_EXPORT operator CATransform3D() const;
 #endif
 #if USE(CG)
-    TransformationMatrix(const CGAffineTransform&);
-    operator CGAffineTransform() const;
+    WEBCORE_EXPORT TransformationMatrix(const CGAffineTransform&);
+    WEBCORE_EXPORT operator CGAffineTransform() const;
 #elif USE(CAIRO)
     operator cairo_matrix_t() const;
 #endif
@@ -360,6 +365,11 @@ public:
     operator XFORM() const;
 #endif
 
+#if PLATFORM(WIN)
+    TransformationMatrix(const D2D1_MATRIX_3X2_F&);
+    operator D2D1_MATRIX_3X2_F() const;
+#endif
+
     bool isIdentityOrTranslation() const
     {
         return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0
diff --git a/Source/WebCore/platform/graphics/win/FloatPointDirect2D.cpp b/Source/WebCore/platform/graphics/win/FloatPointDirect2D.cpp
new file mode 100644 (file)
index 0000000..65213af
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2004-2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "FloatPoint.h"
+
+#if PLATFORM(WIN)
+
+#include <d2d1.h>
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const D2D_POINT_2F& p)
+    : m_x(p.x)
+    , m_y(p.y)
+{
+}
+
+FloatPoint::operator D2D_POINT_2F() const
+{
+    return D2D1::Point2F(m_x, m_y);
+}
+
+}
+
+#endif // PLATFORM(WIN)
diff --git a/Source/WebCore/platform/graphics/win/FloatRectDirect2D.cpp b/Source/WebCore/platform/graphics/win/FloatRectDirect2D.cpp
new file mode 100644 (file)
index 0000000..498e891
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FloatRect.h"
+
+#if PLATFORM(WIN)
+
+#include "FloatPoint.h"
+#include <d2d1.h>
+
+namespace WebCore {
+
+FloatRect::FloatRect(const D2D1_RECT_F& r)
+    : m_location(FloatPoint(r.left, r.top))
+    , m_size(FloatSize(r.right - r.left, r.bottom - r.top))
+{
+}
+
+FloatRect::operator D2D1_RECT_F() const
+{
+    return D2D1::RectF(x(), y(), maxX(), maxY());
+}
+
+}
+
+#endif // PLATFORM(WIN)
diff --git a/Source/WebCore/platform/graphics/win/FloatSizeDirect2D.cpp b/Source/WebCore/platform/graphics/win/FloatSizeDirect2D.cpp
new file mode 100644 (file)
index 0000000..446e675
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2003-2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "FloatSize.h"
+
+#if PLATFORM(WIN)
+
+#include <d2d1.h>
+
+namespace WebCore {
+
+FloatSize::FloatSize(const D2D1_SIZE_F& s)
+    : m_width(s.width)
+    , m_height(s.height)
+{
+}
+
+FloatSize::operator D2D1_SIZE_F() const
+{
+    return D2D1::SizeF(m_width, m_height);
+}
+
+}
+
+#endif // PLATFORM(WIN)
index ec188a6..8a6f07b 100644 (file)
@@ -25,7 +25,9 @@
 
 #include "config.h"
 #include "IntPoint.h"
+#include "MathExtras.h"
 
+#include <d2d1.h>
 #include <windows.h>
 
 namespace WebCore {
@@ -54,4 +56,26 @@ IntPoint::operator POINTS() const
     return p;
 }
 
+IntPoint::IntPoint(const D2D1_POINT_2F& p)
+    : m_x(clampToInteger(p.x))
+    , m_y(clampToInteger(p.y))
+{
+}
+
+IntPoint::IntPoint(const D2D1_POINT_2U& p)
+    : m_x(p.x)
+    , m_y(p.y)
+{
+}
+
+IntPoint::operator D2D1_POINT_2F() const
+{
+    return D2D1::Point2F(m_x, m_y);
+}
+
+IntPoint::operator D2D1_POINT_2U() const
+{
+    return D2D1::Point2U(m_x, m_y);
+}
+
 }
index 9b2a9a2..7c41f1a 100644 (file)
 #include "config.h"
 #include "IntRect.h"
 
+#include "MathExtras.h"
+#include <d2d1.h>
 #include <windows.h>
 
 namespace WebCore {
 
 IntRect::IntRect(const RECT& r)
-    : m_location(IntPoint(r.left, r.top)), m_size(IntSize(r.right-r.left, r.bottom-r.top))
+    : m_location(IntPoint(r.left, r.top)), m_size(IntSize(r.right - r.left, r.bottom - r.top))
 {
 }
 
@@ -42,4 +44,26 @@ IntRect::operator RECT() const
     return rect;
 }
 
+IntRect::IntRect(const D2D1_RECT_F& r)
+    : m_location(IntPoint(clampToInteger(r.left), clampToInteger(r.top)))
+    , m_size(IntSize(clampToInteger(r.right - r.left), clampToInteger(r.bottom - r.top)))
+{
+}
+
+IntRect::IntRect(const D2D1_RECT_U& r)
+    : m_location(IntPoint(r.left, r.top))
+    , m_size(IntSize(r.right - r.left, r.bottom - r.top))
+{
+}
+
+IntRect::operator D2D1_RECT_F() const
+{
+    return D2D1::RectF(x(), y(), maxX(), maxY());
+}
+
+IntRect::operator D2D1_RECT_U() const
+{
+    return D2D1::RectU(x(), y(), maxX(), maxY());
+}
+
 }
index 7c8e76f..e221cf6 100644 (file)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "IntSize.h"
 
+#include "MathExtras.h"
+#include <d2d1.h>
 #include <windows.h>
 
 namespace WebCore {
@@ -42,4 +44,26 @@ IntSize::operator SIZE() const
     return s;
 }
 
+IntSize::IntSize(const D2D1_SIZE_U& s)
+    : m_width(s.width)
+    , m_height(s.height)
+{
+}
+
+IntSize::IntSize(const D2D1_SIZE_F& s)
+    : m_width(clampToInteger(s.width))
+    , m_height(clampToInteger(s.height))
+{
+}
+
+IntSize::operator D2D1_SIZE_U() const
+{
+    return D2D1::SizeU(m_width, m_height);
+}
+
+IntSize::operator D2D1_SIZE_F() const
+{
+    return D2D1::SizeF(m_width, m_height);
+}
+
 }
diff --git a/Source/WebCore/platform/graphics/win/TransformationMatrixDirect2D.cpp b/Source/WebCore/platform/graphics/win/TransformationMatrixDirect2D.cpp
new file mode 100644 (file)
index 0000000..f81f9ec
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2005-2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "TransformationMatrix.h"
+
+#if PLATFORM(WIN)
+
+#include "AffineTransform.h"
+#include "FloatConversion.h"
+
+#include <d2d1.h>
+
+namespace WebCore {
+
+TransformationMatrix::TransformationMatrix(const D2D1_MATRIX_3X2_F& t)
+{
+    setA(t._11);
+    setB(t._12);
+    setC(t._21);
+    setD(t._22);
+    setE(t._31);
+    setF(t._32);
+}
+
+TransformationMatrix::operator D2D1_MATRIX_3X2_F() const
+{
+    return D2D1::Matrix3x2F(narrowPrecisionToFloat(a()),
+        narrowPrecisionToFloat(b()),
+        narrowPrecisionToFloat(c()),
+        narrowPrecisionToFloat(d()),
+        narrowPrecisionToFloat(e()),
+        narrowPrecisionToFloat(f()));
+}
+
+AffineTransform::AffineTransform(const D2D1_MATRIX_3X2_F& t)
+{
+    setMatrix(t._11, t._12, t._21, t._22, t._31, t._32);
+}
+
+AffineTransform::operator D2D1_MATRIX_3X2_F() const
+{
+    return D2D1::Matrix3x2F(narrowPrecisionToFloat(a()),
+        narrowPrecisionToFloat(b()),
+        narrowPrecisionToFloat(c()),
+        narrowPrecisionToFloat(d()),
+        narrowPrecisionToFloat(e()),
+        narrowPrecisionToFloat(f()));
+}
+
+}
+
+#endif // USE(DIRECT2D)
index 41ffa07..1f828c6 100644 (file)
@@ -1,3 +1,12 @@
+2016-09-12  Brent Fulgham  <bfulgham@apple.com>
+
+        [Win][Direct2D] Provide Direct2D-based geometry and transform cast operations
+        https://bugs.webkit.org/show_bug.cgi?id=161818
+
+        Reviewed by Dean Jackson.
+
+        * PlatformWin.cmake: Link to Direct2D on Windows.
+
 2016-09-06  Dan Bernstein  <mitz@apple.com>
 
         [Xcode] WebKitLegacy.framework is re-signed on incremental build even if nothing’s changed
index 18cb990..ce9a3b8 100644 (file)
@@ -420,6 +420,7 @@ list(APPEND WebKit_LIBRARIES
     PRIVATE Comctl32
     PRIVATE Comsupp
     PRIVATE Crypt32
+    PRIVATE D2d1
     PRIVATE Iphlpapi
     PRIVATE Psapi
     PRIVATE Rpcrt4
index cb599cb..c74d614 100644 (file)
@@ -1,3 +1,24 @@
+2016-09-12  Brent Fulgham  <bfulgham@apple.com>
+
+        [Win][Direct2D] Provide Direct2D-based geometry and transform cast operations
+        https://bugs.webkit.org/show_bug.cgi?id=161818
+
+        Reviewed by Dean Jackson.
+
+        Add several new test suites for the various geometric primitives in WebCore.
+
+        * TestWebKitAPI/PlatformWin.cmake: Add new files for test cases.
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: Ditto.
+        * TestWebKitAPI/Tests/WebCore/AffineTransform.cpp: Added.
+        * TestWebKitAPI/Tests/WebCore/FloatPoint.cpp: Added.
+        * TestWebKitAPI/Tests/WebCore/FloatRect.cpp: Added.
+        * TestWebKitAPI/Tests/WebCore/FloatSize.cpp: Added.
+        * TestWebKitAPI/Tests/WebCore/IntPoint.cpp: Added.
+        * TestWebKitAPI/Tests/WebCore/IntRect.cpp: Added.
+        * TestWebKitAPI/Tests/WebCore/IntSize.cpp: Added.
+        * TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp: Add some new
+        Windows-focused test cases.
+
 2016-09-12  Chris Dumez  <cdumez@apple.com>
 
         Fix post-landing review comments after r205787
index 822d941..d9bc0e3 100644 (file)
@@ -27,6 +27,7 @@ add_definitions(-DWEBCORE_EXPORT=)
 
 set(test_webcore_LIBRARIES
     Crypt32
+    D2d1
     Iphlpapi
     Psapi
     Shlwapi
@@ -40,13 +41,21 @@ set(test_webcore_LIBRARIES
 set(TestWebCoreLib_SOURCES
     ${test_main_SOURCES}
     ${TESTWEBKITAPI_DIR}/TestsController.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/AffineTransform.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/CalculationValue.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/CSSParser.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/FloatRect.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/FloatPoint.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/FloatSize.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/HTMLParserIdioms.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/IntRect.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/IntPoint.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/IntSize.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/LayoutUnit.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/ParsedContentRange.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/SharedBuffer.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/TimeRanges.cpp
+    ${TESTWEBKITAPI_DIR}/Tests/WebCore/TransformationMatrix.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/URL.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/URLParser.cpp
     ${TESTWEBKITAPI_DIR}/Tests/WebCore/win/DIBPixelData.cpp
index a87d4dc..dd46478 100644 (file)
                7673499D1930C5BB00E44DF9 /* StopLoadingDuringDidFailProvisionalLoad_bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7673499A1930182E00E44DF9 /* StopLoadingDuringDidFailProvisionalLoad_bundle.cpp */; };
                76E182DD1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */; };
                76E182DF154767E600F1FADD /* auto-submitting-form.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 76E182DE15475A8300F1FADD /* auto-submitting-form.html */; };
+               7A010BCB1D877C0500EDE72A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A010BCA1D877C0500EDE72A /* CoreGraphics.framework */; };
+               7A010BCD1D877C0D00EDE72A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A010BCC1D877C0D00EDE72A /* QuartzCore.framework */; };
                7A1458FC1AD5C07000E06772 /* mouse-button-listener.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */; };
+               7A909A7D1D877480007E10F8 /* AffineTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A909A6F1D877475007E10F8 /* AffineTransform.cpp */; };
+               7A909A7E1D877480007E10F8 /* FloatPoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A909A701D877475007E10F8 /* FloatPoint.cpp */; };
+               7A909A7F1D877480007E10F8 /* FloatRect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A909A711D877475007E10F8 /* FloatRect.cpp */; };
+               7A909A801D877480007E10F8 /* FloatSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A909A721D877475007E10F8 /* FloatSize.cpp */; };
+               7A909A811D877480007E10F8 /* IntPoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A909A731D877475007E10F8 /* IntPoint.cpp */; };
+               7A909A821D877480007E10F8 /* IntRect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A909A741D877475007E10F8 /* IntRect.cpp */; };
+               7A909A831D877480007E10F8 /* IntSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A909A751D877475007E10F8 /* IntSize.cpp */; };
                7AD3FE8E1D76131200B169A4 /* TransformationMatrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AD3FE8D1D75FB8D00B169A4 /* TransformationMatrix.cpp */; };
                7AE9E5091AE5AE8B00CF874B /* test.pdf in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7AE9E5081AE5AE8B00CF874B /* test.pdf */; };
                7C3965061CDD74F90094DBB8 /* Color.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C3965051CDD74F90094DBB8 /* Color.cpp */; };
                76E182D91547550100F1FADD /* WillSendSubmitEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillSendSubmitEvent.cpp; sourceTree = "<group>"; };
                76E182DC1547569100F1FADD /* WillSendSubmitEvent_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillSendSubmitEvent_Bundle.cpp; sourceTree = "<group>"; };
                76E182DE15475A8300F1FADD /* auto-submitting-form.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "auto-submitting-form.html"; sourceTree = "<group>"; };
+               7A010BCA1D877C0500EDE72A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+               7A010BCC1D877C0D00EDE72A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
                7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "mouse-button-listener.html"; sourceTree = "<group>"; };
                7A38D7E51C752D5F004F157D /* HashCountedSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashCountedSet.cpp; sourceTree = "<group>"; };
                7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MenuTypesForMouseEvents.cpp; sourceTree = "<group>"; };
+               7A909A6F1D877475007E10F8 /* AffineTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AffineTransform.cpp; sourceTree = "<group>"; };
+               7A909A701D877475007E10F8 /* FloatPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatPoint.cpp; sourceTree = "<group>"; };
+               7A909A711D877475007E10F8 /* FloatRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatRect.cpp; sourceTree = "<group>"; };
+               7A909A721D877475007E10F8 /* FloatSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatSize.cpp; sourceTree = "<group>"; };
+               7A909A731D877475007E10F8 /* IntPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntPoint.cpp; sourceTree = "<group>"; };
+               7A909A741D877475007E10F8 /* IntRect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntRect.cpp; sourceTree = "<group>"; };
+               7A909A751D877475007E10F8 /* IntSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntSize.cpp; sourceTree = "<group>"; };
                7A99D9931AD4A29D00373141 /* MenuTypesForMouseEvents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MenuTypesForMouseEvents.mm; sourceTree = "<group>"; };
                7AA021BA1AB09EA70052953F /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; };
                7AA6A1511AAC0B31002B2ED3 /* WorkQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkQueue.cpp; sourceTree = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               7A010BCD1D877C0D00EDE72A /* QuartzCore.framework in Frameworks */,
+                               7A010BCB1D877C0500EDE72A /* CoreGraphics.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                440A1D3614A01000008A66F2 /* WebCore */ = {
                        isa = PBXGroup;
                        children = (
+                               7A909A6F1D877475007E10F8 /* AffineTransform.cpp */,
+                               7A909A701D877475007E10F8 /* FloatPoint.cpp */,
+                               7A909A711D877475007E10F8 /* FloatRect.cpp */,
+                               7A909A721D877475007E10F8 /* FloatSize.cpp */,
+                               7A909A731D877475007E10F8 /* IntPoint.cpp */,
+                               7A909A741D877475007E10F8 /* IntRect.cpp */,
+                               7A909A751D877475007E10F8 /* IntSize.cpp */,
                                CD89D0371C4EDB1300040A04 /* cocoa */,
                                93A720E518F1A0E800A848E1 /* CalculationValue.cpp */,
                                7C3965051CDD74F90094DBB8 /* Color.cpp */,
                7C83E0281D0A5CDF00FEBCF3 /* Frameworks */ = {
                        isa = PBXGroup;
                        children = (
+                               7A010BCC1D877C0D00EDE72A /* QuartzCore.framework */,
+                               7A010BCA1D877C0500EDE72A /* CoreGraphics.framework */,
                                7C83E0331D0A5F2700FEBCF3 /* libicucore.dylib */,
                                7C83E0291D0A5CDF00FEBCF3 /* libWTF.a */,
                        );
                                7CCE7F291A411B1000447C4C /* CustomProtocolsInvalidScheme.mm in Sources */,
                                7CCE7F2A1A411B1000447C4C /* CustomProtocolsSyncXHRTest.mm in Sources */,
                                7CCE7F2B1A411B1000447C4C /* CustomProtocolsTest.mm in Sources */,
+                               7A909A801D877480007E10F8 /* FloatSize.cpp in Sources */,
                                2DC4CF771D2D9DD800ECCC94 /* DataDetection.mm in Sources */,
                                2D1646E21D1862CD00015A1A /* DeferredViewInWindowStateChange.mm in Sources */,
                                7CCE7EB91A411A7E00447C4C /* DeviceScaleFactorInDashboardRegions.mm in Sources */,
                                7CCE7EBE1A411A7E00447C4C /* DynamicDeviceScaleFactor.mm in Sources */,
                                7CCE7EE01A411A9A00447C4C /* EditorCommands.mm in Sources */,
                                7CCE7EBF1A411A7E00447C4C /* ElementAtPointInWebFrame.mm in Sources */,
+                               7A909A831D877480007E10F8 /* IntSize.cpp in Sources */,
                                7CCE7EEF1A411AE600447C4C /* EphemeralSessionPushStateNoHistoryCallback.cpp in Sources */,
                                7CCE7EF01A411AE600447C4C /* EvaluateJavaScript.cpp in Sources */,
                                7CCE7EF11A411AE600447C4C /* FailedLoad.cpp in Sources */,
                                7CCE7EA61A411A0F00447C4C /* PlatformUtilitiesMac.mm in Sources */,
                                7CCE7EA71A411A1300447C4C /* PlatformWebViewMac.mm in Sources */,
                                7CCE7F261A411AF600447C4C /* Preferences.mm in Sources */,
+                               7A909A821D877480007E10F8 /* IntRect.cpp in Sources */,
                                7CCE7F0B1A411AE600447C4C /* PreventEmptyUserAgent.cpp in Sources */,
                                7CCE7F2C1A411B1000447C4C /* PreventImageLoadWithAutoResizing.mm in Sources */,
+                               7A909A7E1D877480007E10F8 /* FloatPoint.cpp in Sources */,
                                7CCE7F0C1A411AE600447C4C /* PrivateBrowsingPushStateNoHistoryCallback.cpp in Sources */,
                                7C83E0C11D0A652F00FEBCF3 /* ProvisionalURLNotChange.mm in Sources */,
                                7CCE7EC81A411A7E00447C4C /* PublicSuffix.mm in Sources */,
                                7CCE7F0D1A411AE600447C4C /* ReloadPageAfterCrash.cpp in Sources */,
                                7C83E0C31D0A653A00FEBCF3 /* RemoteObjectRegistry.mm in Sources */,
                                7CCE7EC91A411A7E00447C4C /* RenderedImageFromDOMNode.mm in Sources */,
+                               7A909A7D1D877480007E10F8 /* AffineTransform.cpp in Sources */,
                                7CCE7ECA1A411A7E00447C4C /* RenderedImageFromDOMRange.mm in Sources */,
                                7C83E0C41D0A654200FEBCF3 /* RequiresUserActionForPlayback.mm in Sources */,
                                7CCE7F0E1A411AE600447C4C /* ResizeReversePaginatedWebView.cpp in Sources */,
                                7CCE7F0F1A411AE600447C4C /* ResizeWindowAfterCrash.cpp in Sources */,
                                7CCE7F101A411AE600447C4C /* ResponsivenessTimerDoesntFireEarly.cpp in Sources */,
                                7CCE7F111A411AE600447C4C /* RestoreSessionStateContainingFormData.cpp in Sources */,
+                               7A909A811D877480007E10F8 /* IntPoint.cpp in Sources */,
                                835CF9671D25FCD6001A65D4 /* RestoreSessionStateWithoutNavigation.cpp in Sources */,
+                               7A909A7F1D877480007E10F8 /* FloatRect.cpp in Sources */,
                                7CCE7F121A411AE600447C4C /* ScrollPinningBehaviors.cpp in Sources */,
                                7CCE7ECB1A411A7E00447C4C /* SetAndUpdateCacheModel.mm in Sources */,
                                7CCE7ECC1A411A7E00447C4C /* SetDocumentURI.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp b/Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp
new file mode 100644 (file)
index 0000000..9bcd1a4
--- /dev/null
@@ -0,0 +1,1024 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/AffineTransform.h>
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatQuad.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/TransformationMatrix.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::AffineTransform& affineTransform)
+{
+    affineTransform.setA(1.1);
+    EXPECT_DOUBLE_EQ(1.1, affineTransform.a());
+    affineTransform.setB(2.2);
+    EXPECT_DOUBLE_EQ(2.2, affineTransform.b());
+    affineTransform.setC(3.3);
+    EXPECT_DOUBLE_EQ(3.3, affineTransform.c());
+    affineTransform.setD(4.4);
+    EXPECT_DOUBLE_EQ(4.4, affineTransform.d());
+    affineTransform.setE(5.5);
+    EXPECT_DOUBLE_EQ(5.5, affineTransform.e());
+    affineTransform.setF(6.6);
+    EXPECT_DOUBLE_EQ(6.6, affineTransform.f());
+}
+
+static void testIdentity(const WebCore::AffineTransform& transform)
+{
+    EXPECT_DOUBLE_EQ(1.0, transform.a());
+    EXPECT_DOUBLE_EQ(0.0, transform.b());
+    EXPECT_DOUBLE_EQ(0.0, transform.c());
+    EXPECT_DOUBLE_EQ(1.0, transform.d());
+    EXPECT_DOUBLE_EQ(0.0, transform.e());
+    EXPECT_DOUBLE_EQ(0.0, transform.f());
+}
+
+TEST(AffineTransform, DefaultConstruction)
+{
+    WebCore::AffineTransform test;
+
+    testIdentity(test);
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+}
+
+static void testValueConstruction(const WebCore::AffineTransform& transform)
+{
+    EXPECT_DOUBLE_EQ(6.0, transform.a());
+    EXPECT_DOUBLE_EQ(5.0, transform.b());
+    EXPECT_DOUBLE_EQ(4.0, transform.c());
+    EXPECT_DOUBLE_EQ(3.0, transform.d());
+    EXPECT_DOUBLE_EQ(2.0, transform.e());
+    EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testDoubled(const WebCore::AffineTransform& transform)
+{
+    EXPECT_DOUBLE_EQ(12.0, transform.a());
+    EXPECT_DOUBLE_EQ(10.0, transform.b());
+    EXPECT_DOUBLE_EQ(8.0, transform.c());
+    EXPECT_DOUBLE_EQ(6.0, transform.d());
+    EXPECT_DOUBLE_EQ(2.0, transform.e());
+    EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testHalved(const WebCore::AffineTransform& transform)
+{
+    EXPECT_DOUBLE_EQ(3.0, transform.a());
+    EXPECT_DOUBLE_EQ(2.5, transform.b());
+    EXPECT_DOUBLE_EQ(2.0, transform.c());
+    EXPECT_DOUBLE_EQ(1.5, transform.d());
+    EXPECT_DOUBLE_EQ(2.0, transform.e());
+    EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+TEST(AffineTransform, ValueConstruction)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+    ASSERT_FALSE(test.preservesAxisAlignment());
+}
+
+#if USE(CG)
+TEST(AffineTransform, CGAffineTransformConstruction)
+{
+    CGAffineTransform cgTransform = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::AffineTransform test(cgTransform);
+
+    testValueConstruction(test);
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+#if PLATFORM(WIN)
+TEST(AffineTransform, D2D1MatrixConstruction)
+{
+    D2D1_MATRIX_3X2_F d2dTransform = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::AffineTransform test(d2dTransform);
+
+    testValueConstruction(test);
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+TEST(AffineTransform, Identity)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    ASSERT_FALSE(test.isIdentity());
+    ASSERT_FALSE(test.isIdentityOrTranslation());
+    ASSERT_FALSE(test.isIdentityOrTranslationOrFlipped());
+    ASSERT_FALSE(test.preservesAxisAlignment());
+
+    test.makeIdentity();
+
+    ASSERT_TRUE(test.isIdentity());
+    ASSERT_TRUE(test.isIdentityOrTranslation());
+    ASSERT_TRUE(test.isIdentityOrTranslationOrFlipped());
+    ASSERT_TRUE(test.preservesAxisAlignment());
+
+    testIdentity(test);
+}
+
+TEST(AffineTransform, MapFloatPoint)
+{
+    WebCore::AffineTransform test;
+    WebCore::FloatPoint point(100.0f, 50.0f);
+
+    auto mappedPoint = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint.x());
+    ASSERT_FLOAT_EQ(50.0f, mappedPoint.y());
+
+    test.setD(2.0);
+
+    auto mappedPoint2 = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint2.x());
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint2.y());
+
+    test.setA(0.5);
+
+    auto mappedPoint3 = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(50.0f, mappedPoint3.x());
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint3.y());
+}
+
+TEST(AffineTransform, MapIntPoint)
+{
+    WebCore::AffineTransform test;
+    WebCore::IntPoint point(100, 50);
+
+    auto mappedPoint = test.mapPoint(point);
+
+    ASSERT_EQ(100, mappedPoint.x());
+    ASSERT_EQ(50, mappedPoint.y());
+
+    test.setD(2.0);
+
+    auto mappedPoint2 = test.mapPoint(point);
+
+    ASSERT_EQ(100, mappedPoint2.x());
+    ASSERT_EQ(100, mappedPoint2.y());
+
+    test.setA(0.5);
+
+    auto mappedPoint3 = test.mapPoint(point);
+
+    ASSERT_EQ(50, mappedPoint3.x());
+    ASSERT_EQ(100, mappedPoint3.y());
+}
+
+TEST(AffineTransform, MapIntSize)
+{
+    WebCore::AffineTransform test;
+    WebCore::IntSize size(200, 300);
+
+    auto mappedSize = test.mapSize(size);
+
+    ASSERT_EQ(200, mappedSize.width());
+    ASSERT_EQ(300, mappedSize.height());
+
+    test.setD(2.0);
+
+    auto mappedSize2 = test.mapSize(size);
+
+    ASSERT_EQ(200, mappedSize2.width());
+    ASSERT_EQ(600, mappedSize2.height());
+
+    test.setA(0.5);
+
+    auto mappedSize3 = test.mapSize(size);
+
+    ASSERT_EQ(100, mappedSize3.width());
+    ASSERT_EQ(600, mappedSize3.height());
+}
+
+TEST(AffineTransform, MapFloatSize)
+{
+    WebCore::AffineTransform test;
+    WebCore::FloatSize size(200.0f, 300.0f);
+
+    auto mappedSize = test.mapSize(size);
+
+    ASSERT_EQ(200.0f, mappedSize.width());
+    ASSERT_EQ(300.0f, mappedSize.height());
+
+    test.setD(2.0);
+
+    auto mappedSize2 = test.mapSize(size);
+
+    ASSERT_EQ(200.0f, mappedSize2.width());
+    ASSERT_EQ(600.0f, mappedSize2.height());
+
+    test.setA(0.5);
+
+    auto mappedSize3 = test.mapSize(size);
+
+    ASSERT_EQ(100.0f, mappedSize3.width());
+    ASSERT_EQ(600.0f, mappedSize3.height());
+}
+
+TEST(AffineTransform, MapIntRect)
+{
+    WebCore::AffineTransform test;
+    WebCore::IntRect rect(10, 20, 200, 300);
+
+    auto mappedRect = test.mapRect(rect);
+
+    ASSERT_EQ(10, mappedRect.x());
+    ASSERT_EQ(20, mappedRect.y());
+    ASSERT_EQ(200, mappedRect.width());
+    ASSERT_EQ(300, mappedRect.height());
+
+    test.setD(2.0);
+
+    auto mappedRect2 = test.mapRect(rect);
+
+    ASSERT_EQ(10, mappedRect2.x());
+    ASSERT_EQ(40, mappedRect2.y());
+    ASSERT_EQ(200, mappedRect2.width());
+    ASSERT_EQ(600, mappedRect2.height());
+
+    test.setA(0.5);
+
+    auto mappedRect3 = test.mapRect(rect);
+
+    ASSERT_EQ(5, mappedRect3.x());
+    ASSERT_EQ(40, mappedRect3.y());
+    ASSERT_EQ(100, mappedRect3.width());
+    ASSERT_EQ(600, mappedRect3.height());
+}
+
+TEST(AffineTransform, MapFloatRect)
+{
+    WebCore::AffineTransform test;
+    WebCore::FloatRect rect(10.f, 20.0f, 200.0f, 300.0f);
+
+    auto mappedRect = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(10.0f, mappedRect.x());
+    ASSERT_FLOAT_EQ(20.0f, mappedRect.y());
+    ASSERT_FLOAT_EQ(200.0f, mappedRect.width());
+    ASSERT_FLOAT_EQ(300.0f, mappedRect.height());
+
+    test.setD(2.0);
+
+    auto mappedRect2 = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(10.0f, mappedRect2.x());
+    ASSERT_FLOAT_EQ(40.0f, mappedRect2.y());
+    ASSERT_FLOAT_EQ(200.0f, mappedRect2.width());
+    ASSERT_FLOAT_EQ(600.0f, mappedRect2.height());
+
+    test.setA(0.5);
+
+    auto mappedRect3 = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(5.0f, mappedRect3.x());
+    ASSERT_FLOAT_EQ(40.0f, mappedRect3.y());
+    ASSERT_FLOAT_EQ(100.0f, mappedRect3.width());
+    ASSERT_FLOAT_EQ(600.0f, mappedRect3.height());
+}
+
+TEST(AffineTransform, MapFloatQuad)
+{
+    WebCore::FloatRect rect(100.0f, 100.0f, 100.0f, 50.0f);
+    WebCore::FloatQuad quad(rect);
+
+    ASSERT_FLOAT_EQ(100.0f, quad.p1().x());
+    ASSERT_FLOAT_EQ(100.0f, quad.p1().y());
+    ASSERT_FLOAT_EQ(200.0f, quad.p2().x());
+    ASSERT_FLOAT_EQ(100.0f, quad.p2().y());
+    ASSERT_FLOAT_EQ(200.0f, quad.p3().x());
+    ASSERT_FLOAT_EQ(150.0f, quad.p3().y());
+    ASSERT_FLOAT_EQ(100.0f, quad.p4().x());
+    ASSERT_FLOAT_EQ(150.0f, quad.p4().y());
+
+    WebCore::AffineTransform test;
+    auto mappedQuad = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().x());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad.p2().x());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p2().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad.p3().x());
+    ASSERT_FLOAT_EQ(150.0f, mappedQuad.p3().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p4().x());
+    ASSERT_FLOAT_EQ(150.0f, mappedQuad.p4().y());
+
+    test.setD(2.0);
+
+    auto mappedQuad2 = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p1().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p1().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p3().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p3().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p4().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p4().y());
+
+    test.setA(0.5);
+
+    auto mappedQuad3 = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p1().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p1().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p2().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p2().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p3().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p3().y());
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p4().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p4().y());
+}
+
+TEST(AffineTransform, Multiply)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::AffineTransform identity;
+
+    testValueConstruction(test);
+
+    test.multiply(identity);
+
+    testValueConstruction(test);
+
+    WebCore::AffineTransform doubler(2.0, 0.0, 0.0, 2.0, 0.0, 0.0);
+
+    test.multiply(doubler);
+
+    testDoubled(test);
+
+    WebCore::AffineTransform halver(0.5, 0.0, 0.0, 0.5, 0.0, 0.0);
+
+    test.multiply(halver);
+
+    testValueConstruction(test);
+
+    test.multiply(halver);
+
+    testHalved(test);
+}
+
+TEST(AffineTransform, Scale)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.scale(1.0);
+
+    testValueConstruction(test);
+
+    test.scale(2.0);
+
+    testDoubled(test);
+
+    test.scale(0.5);
+
+    testValueConstruction(test);
+
+    test.scale(0.5);
+
+    testHalved(test);
+}
+
+TEST(AffineTransform, ScaleUniformNonUniform)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(1.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(2.0, 2.0);
+
+    testDoubled(test);
+
+    test.scaleNonUniform(0.5, 0.5);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(0.5, 0.5);
+
+    testHalved(test);
+}
+
+TEST(AffineTransform, ScaleNonUniform)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(1.0, 2.0);
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(8.0, test.c());
+    EXPECT_DOUBLE_EQ(6.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.scaleNonUniform(1.0, 0.5);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(2.0, 1.0);
+
+    EXPECT_DOUBLE_EQ(12.0, test.a());
+    EXPECT_DOUBLE_EQ(10.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.scaleNonUniform(0.5, 1.0);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(0.5, 2.0);
+
+    EXPECT_DOUBLE_EQ(3.0, test.a());
+    EXPECT_DOUBLE_EQ(2.5, test.b());
+    EXPECT_DOUBLE_EQ(8.0, test.c());
+    EXPECT_DOUBLE_EQ(6.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+}
+
+TEST(AffineTransform, ScaleFloatSize)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    WebCore::FloatSize first(1.0f, 2.0f);
+
+    test.scale(first);
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(8.0, test.c());
+    EXPECT_DOUBLE_EQ(6.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    WebCore::FloatSize second(1.0f, 0.5f);
+
+    test.scale(second);
+
+    testValueConstruction(test);
+
+    WebCore::FloatSize third(2.0f, 1.0f);
+
+    test.scale(third);
+
+    EXPECT_DOUBLE_EQ(12.0, test.a());
+    EXPECT_DOUBLE_EQ(10.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    WebCore::FloatSize fourth(0.5f, 1.0f);
+
+    test.scale(fourth);
+
+    testValueConstruction(test);
+
+    WebCore::FloatSize fifth(0.5f, 2.0f);
+
+    test.scale(fifth);
+
+    EXPECT_DOUBLE_EQ(3.0, test.a());
+    EXPECT_DOUBLE_EQ(2.5, test.b());
+    EXPECT_DOUBLE_EQ(8.0, test.c());
+    EXPECT_DOUBLE_EQ(6.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+}
+
+TEST(AffineTransform, Rotate)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    test.rotate(360.0);
+
+    testValueConstruction(test);
+
+    test.rotate(180.0);
+
+    static double epsilon = 0.0001;
+
+    EXPECT_NEAR(-6.0, test.a(), epsilon);
+    EXPECT_NEAR(-5.0, test.b(), epsilon);
+    EXPECT_NEAR(-4.0, test.c(), epsilon);
+    EXPECT_NEAR(-3.0, test.d(), epsilon);
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.rotate(-180.0);
+
+    testValueConstruction(test);
+
+    test.rotate(90.0);
+
+    EXPECT_NEAR(4.0, test.a(), epsilon);
+    EXPECT_NEAR(3.0, test.b(), epsilon);
+    EXPECT_NEAR(-6.0, test.c(), epsilon);
+    EXPECT_NEAR(-5.0, test.d(), epsilon);
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.rotate(-90.0);
+
+    testValueConstruction(test);
+}
+
+TEST(AffineTransform, TranslateXY)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    test.translate(0.0, 0.0);
+
+    testValueConstruction(test);
+
+    test.translate(5.0, 0.0);
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(32.0, test.e());
+    EXPECT_DOUBLE_EQ(26.0, test.f());
+
+    test.translate(0.0, -1.2);
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(27.2, test.e());
+    EXPECT_DOUBLE_EQ(22.4, test.f());
+}
+
+TEST(AffineTransform, TranslateFloatPoint)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    WebCore::FloatPoint none;
+    test.translate(none);
+
+    testValueConstruction(test);
+
+    WebCore::FloatPoint first(5.0f, 0.0f);
+
+    test.translate(first);
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(32.0, test.e());
+    EXPECT_DOUBLE_EQ(26.0, test.f());
+
+    WebCore::FloatPoint second(0.0f, -1.2f);
+
+    test.translate(second);
+
+    static double epsilon = 0.0001;
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_NEAR(27.2, test.e(), epsilon);
+    EXPECT_NEAR(22.4, test.f(), epsilon);
+
+    WebCore::AffineTransform test2;
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.translate(second);
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, Shear)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    test.shear(0.0, 0.0);
+
+    testValueConstruction(test);
+
+    test.shear(2.0, 2.0);
+
+    EXPECT_DOUBLE_EQ(14.0, test.a());
+    EXPECT_DOUBLE_EQ(11.0, test.b());
+    EXPECT_DOUBLE_EQ(16.0, test.c());
+    EXPECT_DOUBLE_EQ(13.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.shear(-1.0, 2.0);
+
+    EXPECT_DOUBLE_EQ(46.0, test.a());
+    EXPECT_DOUBLE_EQ(37.0, test.b());
+    EXPECT_DOUBLE_EQ(2.0, test.c());
+    EXPECT_DOUBLE_EQ(2.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+}
+
+TEST(AffineTransform, FlipX)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.flipX();
+
+    EXPECT_DOUBLE_EQ(-6.0, test.a());
+    EXPECT_DOUBLE_EQ(-5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipX();
+
+    testValueConstruction(test);
+
+    WebCore::AffineTransform test2;
+
+    testIdentity(test2);
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipX();
+
+    EXPECT_DOUBLE_EQ(-1.0, test2.a());
+    EXPECT_DOUBLE_EQ(0.0, test2.b());
+    EXPECT_DOUBLE_EQ(0.0, test2.c());
+    EXPECT_DOUBLE_EQ(1.0, test2.d());
+    EXPECT_DOUBLE_EQ(0.0, test2.e());
+    EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+    // 'Flipped' just means in the Y direction
+    ASSERT_FALSE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipX();
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, FlipY)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.flipY();
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(-4.0, test.c());
+    EXPECT_DOUBLE_EQ(-3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipY();
+
+    testValueConstruction(test);
+
+    WebCore::AffineTransform test2;
+
+    testIdentity(test2);
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipY();
+
+    EXPECT_DOUBLE_EQ(1.0, test2.a());
+    EXPECT_DOUBLE_EQ(0.0, test2.b());
+    EXPECT_DOUBLE_EQ(0.0, test2.c());
+    EXPECT_DOUBLE_EQ(-1.0, test2.d());
+    EXPECT_DOUBLE_EQ(0.0, test2.e());
+    EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipY();
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, FlipXandFlipY)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.flipX();
+
+    EXPECT_DOUBLE_EQ(-6.0, test.a());
+    EXPECT_DOUBLE_EQ(-5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipY();
+
+    EXPECT_DOUBLE_EQ(-6.0, test.a());
+    EXPECT_DOUBLE_EQ(-5.0, test.b());
+    EXPECT_DOUBLE_EQ(-4.0, test.c());
+    EXPECT_DOUBLE_EQ(-3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipX();
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(-4.0, test.c());
+    EXPECT_DOUBLE_EQ(-3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipY();
+
+    testValueConstruction(test);
+
+    WebCore::AffineTransform test2;
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipX();
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+    ASSERT_FALSE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipY();
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+    // False here because X is also flipped.
+    ASSERT_FALSE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipX();
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+    test2.flipY();
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+    ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, Skew)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.skew(360.0, 360.0);
+
+    testValueConstruction(test);
+
+    test.skew(0.0, 0.0);
+
+    testValueConstruction(test);
+
+    test.skew(180.0, 180.0);
+
+    static double epsilon = 0.0001;
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_NEAR(4.0, test.c(), epsilon);
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.skew(-180.0, -180.0);
+
+    testValueConstruction(test);
+}
+
+TEST(AffineTransform, XandYScale)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    EXPECT_NEAR(7.8102, test.xScale(), 0.0001);
+    EXPECT_NEAR(5.0, test.yScale(), 0.0001);
+}
+
+TEST(AffineTransform, Equality)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::AffineTransform test2;
+
+    ASSERT_FALSE(test == test2);
+    ASSERT_TRUE(test != test2);
+
+    test.makeIdentity();
+
+    ASSERT_TRUE(test == test2);
+    ASSERT_FALSE(test != test2);
+}
+
+TEST(AffineTransform, Inverse)
+{
+    WebCore::AffineTransform test;
+
+    auto inverse = test.inverse();
+
+    ASSERT(inverse);
+
+    EXPECT_DOUBLE_EQ(1.0, inverse->a());
+    EXPECT_DOUBLE_EQ(0.0, inverse->b());
+    EXPECT_DOUBLE_EQ(0.0, inverse->c());
+    EXPECT_DOUBLE_EQ(1.0, inverse->d());
+    EXPECT_DOUBLE_EQ(0.0, inverse->e());
+    EXPECT_DOUBLE_EQ(0.0, inverse->f());
+
+    auto test2 = test * inverse.value();
+
+    testIdentity(test2);
+}
+
+TEST(AffineTransform, Blend)
+{
+    WebCore::AffineTransform test;
+
+    WebCore::AffineTransform test2;
+    test2.scale(2.0);
+
+    test.blend(test2, 50);
+
+    EXPECT_DOUBLE_EQ(-48.0, test.a());
+    EXPECT_DOUBLE_EQ(0.0, test.b());
+    EXPECT_DOUBLE_EQ(0.0, test.c());
+    EXPECT_DOUBLE_EQ(-48.0, test.d());
+    EXPECT_DOUBLE_EQ(0.0, test.e());
+    EXPECT_DOUBLE_EQ(0.0, test.f());
+}
+
+TEST(AffineTransform, Translation)
+{
+    auto test = WebCore::AffineTransform::translation(-5.0, -7.0);
+    EXPECT_DOUBLE_EQ(1.0, test.a());
+    EXPECT_DOUBLE_EQ(0.0, test.b());
+    EXPECT_DOUBLE_EQ(0.0, test.c());
+    EXPECT_DOUBLE_EQ(1.0, test.d());
+    EXPECT_DOUBLE_EQ(-5.0, test.e());
+    EXPECT_DOUBLE_EQ(-7.0, test.f());
+}
+
+TEST(AffineTransform, ToTransformationMatrix)
+{
+    WebCore::AffineTransform transform;
+    WebCore::TransformationMatrix matrix = transform.toTransformationMatrix();
+
+    EXPECT_DOUBLE_EQ(1.0, matrix.m11());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m12());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m13());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m14());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m21());
+    EXPECT_DOUBLE_EQ(1.0, matrix.m22());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m23());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m24());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m31());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m32());
+    EXPECT_DOUBLE_EQ(1.0, matrix.m33());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m34());
+}
+
+TEST(AffineTransform, MakeMapBetweenRects)
+{
+    WebCore::AffineTransform transform;
+
+    WebCore::FloatRect fromRect(10.0f, 10.0f, 100.0f, 100.0f);
+    WebCore::FloatRect toRect(70.0f, 70.0f, 200.0f, 50.0f);
+
+    auto mapBetween = WebCore::makeMapBetweenRects(fromRect, toRect);
+
+    EXPECT_DOUBLE_EQ(2.0, mapBetween.a());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.b());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.c());
+    EXPECT_DOUBLE_EQ(0.5, mapBetween.d());
+    EXPECT_DOUBLE_EQ(60.0, mapBetween.e());
+    EXPECT_DOUBLE_EQ(60.0, mapBetween.f());
+}
+
+#if USE(CG)
+TEST(AffineTransform, CoreGraphicsCasting)
+{
+    WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    CGAffineTransform test2 = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    ASSERT_TRUE(CGAffineTransformEqualToTransform(test, test2));
+
+    WebCore::AffineTransform test3;
+
+    ASSERT_FALSE(CGAffineTransformEqualToTransform(test, test3));
+}
+#endif
+
+#if PLATFORM(WIN)
+TEST(AffineTransform, Direct2DCasting)
+{
+    WebCore::AffineTransform transform(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    D2D1_MATRIX_3X2_F test = transform;
+    D2D1_MATRIX_3X2_F test2 = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    static const double epsilon = 0.0000001;
+
+    EXPECT_NEAR(test._11, test2._11, epsilon);
+    EXPECT_NEAR(test._12, test2._12, epsilon);
+    EXPECT_NEAR(test._21, test2._21, epsilon);
+    EXPECT_NEAR(test._22, test2._22, epsilon);
+    EXPECT_NEAR(test._31, test2._31, epsilon);
+    EXPECT_NEAR(test._32, test2._32, epsilon);
+}
+#endif
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp
new file mode 100644 (file)
index 0000000..0d9ebf3
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/AffineTransform.h>
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/TransformationMatrix.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::FloatPoint point)
+{
+    point.setX(1.1f);
+    EXPECT_FLOAT_EQ(1.1f, point.x());
+    point.setY(2.2f);
+    EXPECT_FLOAT_EQ(2.2f, point.y());
+
+    point.set(9.9f, 8.8f);
+    EXPECT_FLOAT_EQ(9.9f, point.x());
+    EXPECT_FLOAT_EQ(8.8f, point.y());
+}
+
+TEST(FloatPoint, DefaultConstruction)
+{
+    WebCore::FloatPoint test;
+
+    EXPECT_FLOAT_EQ(0, test.x());
+    EXPECT_FLOAT_EQ(0, test.y());
+
+    testGetAndSet(test);
+}
+
+TEST(FloatPoint, ValueConstruction)
+{
+    WebCore::FloatPoint test(9.9f, 8.8f);
+
+    EXPECT_FLOAT_EQ(9.9f, test.x());
+    EXPECT_FLOAT_EQ(8.8f, test.y());
+
+    testGetAndSet(test);
+}
+
+TEST(FloatPoint, ZeroConstruction)
+{
+    WebCore::FloatPoint test = WebCore::FloatPoint::zero();
+
+    EXPECT_FLOAT_EQ(0, test.x());
+    EXPECT_FLOAT_EQ(0, test.y());
+}
+
+TEST(FloatPoint, IntPointConstruction)
+{
+    WebCore::IntPoint testInput(2003, 1997);
+    WebCore::FloatPoint test = WebCore::FloatPoint(testInput);
+
+    EXPECT_FLOAT_EQ(2003.0f, test.x());
+    EXPECT_FLOAT_EQ(1997.0f, test.y());
+}
+
+TEST(FloatPoint, FloatSizeConstruction)
+{
+    WebCore::FloatSize testInput(500.7f, 300.2f);
+    WebCore::FloatPoint test = WebCore::FloatPoint(testInput);
+
+    EXPECT_FLOAT_EQ(500.7, test.x());
+    EXPECT_FLOAT_EQ(300.2, test.y());
+}
+
+TEST(FloatPoint, MoveByFloat)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    test.move(20.2f, 30.3f);
+
+    EXPECT_FLOAT_EQ(120.2f, test.x());
+    EXPECT_FLOAT_EQ(230.3f, test.y());
+
+    test.move(-81.3f, 10.0f);
+
+    EXPECT_FLOAT_EQ(38.9f, test.x());
+    EXPECT_FLOAT_EQ(240.3f, test.y());
+
+    test.move(11.1f, -33.2f);
+
+    EXPECT_FLOAT_EQ(50.0f, test.x());
+    EXPECT_FLOAT_EQ(207.1f, test.y());
+
+    test.move(-5.6f, -9.8f);
+
+    EXPECT_FLOAT_EQ(44.4f, test.x());
+    EXPECT_FLOAT_EQ(197.3f, test.y());
+}
+
+TEST(FloatPoint, MoveByIntSize)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    WebCore::IntSize first(20, 30);
+
+    test.move(first);
+
+    EXPECT_FLOAT_EQ(120.0f, test.x());
+    EXPECT_FLOAT_EQ(230.0f, test.y());
+
+    WebCore::IntSize second(-81, 10);
+
+    test.move(second);
+
+    EXPECT_FLOAT_EQ(39.0f, test.x());
+    EXPECT_FLOAT_EQ(240.0f, test.y());
+
+    WebCore::IntSize third(11, -33);
+
+    test.move(third);
+
+    EXPECT_FLOAT_EQ(50.0f, test.x());
+    EXPECT_FLOAT_EQ(207.0f, test.y());
+
+    WebCore::IntSize fourth(-6, -10);
+
+    test.move(fourth);
+
+    EXPECT_FLOAT_EQ(44.0f, test.x());
+    EXPECT_FLOAT_EQ(197.0f, test.y());
+}
+
+TEST(FloatPoint, MoveByFloatSize)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    WebCore::FloatSize first(20.2f, 30.3f);
+
+    test.move(first);
+
+    EXPECT_FLOAT_EQ(120.2f, test.x());
+    EXPECT_FLOAT_EQ(230.3f, test.y());
+
+    WebCore::FloatSize second(-81.3f, 10.0f);
+
+    test.move(second);
+
+    EXPECT_FLOAT_EQ(38.9f, test.x());
+    EXPECT_FLOAT_EQ(240.3f, test.y());
+
+    WebCore::FloatSize third(11.1f, -33.2f);
+
+    test.move(third);
+
+    EXPECT_FLOAT_EQ(50.0f, test.x());
+    EXPECT_FLOAT_EQ(207.1f, test.y());
+
+    WebCore::FloatSize fourth(-5.6f, -9.8f);
+
+    test.move(fourth);
+
+    EXPECT_FLOAT_EQ(44.4f, test.x());
+    EXPECT_FLOAT_EQ(197.3f, test.y());
+}
+
+TEST(FloatPoint, MoveByIntPoint)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    WebCore::IntPoint first(20, 30);
+
+    test.moveBy(first);
+
+    EXPECT_FLOAT_EQ(120.0f, test.x());
+    EXPECT_FLOAT_EQ(230.0f, test.y());
+
+    WebCore::IntPoint second(-81, 10);
+
+    test.moveBy(second);
+
+    EXPECT_FLOAT_EQ(39.0f, test.x());
+    EXPECT_FLOAT_EQ(240.0f, test.y());
+
+    WebCore::IntPoint third(11, -33);
+
+    test.moveBy(third);
+
+    EXPECT_FLOAT_EQ(50.0f, test.x());
+    EXPECT_FLOAT_EQ(207.0f, test.y());
+
+    WebCore::IntPoint fourth(-6, -10);
+
+    test.moveBy(fourth);
+
+    EXPECT_FLOAT_EQ(44.0f, test.x());
+    EXPECT_FLOAT_EQ(197.0f, test.y());
+}
+
+TEST(FloatPoint, MoveByFloatPoint)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    WebCore::FloatPoint first(20.2f, 30.3f);
+
+    test.moveBy(first);
+
+    EXPECT_FLOAT_EQ(120.2f, test.x());
+    EXPECT_FLOAT_EQ(230.3f, test.y());
+
+    WebCore::FloatPoint second(-81.3f, 10.0f);
+
+    test.moveBy(second);
+
+    EXPECT_FLOAT_EQ(38.9f, test.x());
+    EXPECT_FLOAT_EQ(240.3f, test.y());
+
+    WebCore::FloatPoint third(11.1f, -33.2f);
+
+    test.moveBy(third);
+
+    EXPECT_FLOAT_EQ(50.0f, test.x());
+    EXPECT_FLOAT_EQ(207.1f, test.y());
+
+    WebCore::FloatPoint fourth(-5.6f, -9.8f);
+
+    test.moveBy(fourth);
+
+    EXPECT_FLOAT_EQ(44.4f, test.x());
+    EXPECT_FLOAT_EQ(197.3f, test.y());
+}
+
+TEST(FloatPoint, Scale)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    test.scale(2.0f, 2.0f);
+
+    EXPECT_FLOAT_EQ(200.0f, test.x());
+    EXPECT_FLOAT_EQ(400.0f, test.y());
+
+    test.scale(0.5f, 0.5f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    test.scale(1.0f, 0.5f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(100.0f, test.y());
+}
+
+TEST(FloatPoint, Normalize)
+{
+    WebCore::FloatPoint a(30.0f, 40.0f);
+
+    a.normalize();
+
+    EXPECT_FLOAT_EQ(0.6, a.x());
+    EXPECT_FLOAT_EQ(0.8, a.y());
+}
+
+TEST(FloatPoint, Dot)
+{
+    WebCore::FloatPoint a(100.0f, 200.0f);
+    WebCore::FloatPoint b(2.0f, 4.0f);
+    WebCore::FloatPoint c(1.0f, 0.5f);
+
+    EXPECT_NEAR(1000.0f, a.dot(b), 0.0001f);
+    EXPECT_NEAR(200.0f, a.dot(c), 0.0001f);
+}
+
+TEST(FloatPoint, LengthSquared)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    EXPECT_FLOAT_EQ(50000.0f, test.lengthSquared());
+}
+
+TEST(FloatPoint, ConstrainedBetween)
+{
+    WebCore::FloatPoint left(10.0f, 20.0f);
+    WebCore::FloatPoint right(100.0f, 200.0f);
+
+    WebCore::FloatPoint test1(50.0f, 80.0f);
+    WebCore::FloatPoint test2(8.0f, 80.0f);
+    WebCore::FloatPoint test3(50.0f, 220.0f);
+
+    auto constrained1 = test1.constrainedBetween(left, right);
+    EXPECT_FLOAT_EQ(50.0f, constrained1.x());
+    EXPECT_FLOAT_EQ(80.0f, constrained1.y());
+
+    auto constrained2 = test2.constrainedBetween(left, right);
+    EXPECT_FLOAT_EQ(10.0f, constrained2.x());
+    EXPECT_FLOAT_EQ(80.0f, constrained2.y());
+
+    auto constrained3 = test3.constrainedBetween(left, right);
+    EXPECT_FLOAT_EQ(50.0f, constrained3.x());
+    EXPECT_FLOAT_EQ(200.0f, constrained3.y());
+}
+
+TEST(FloatPoint, ShrunkTo)
+{
+    WebCore::FloatPoint big(100.0f, 200.0f);
+    WebCore::FloatPoint smaller(10.0f, 80.0f);
+
+    auto shrunkTo = big.shrunkTo(smaller);
+
+    EXPECT_FLOAT_EQ(10.0f, shrunkTo.x());
+    EXPECT_FLOAT_EQ(80.0f, shrunkTo.y());
+
+    WebCore::FloatPoint bigish(8.0f, 200.0f);
+
+    auto shrunkTo2 = bigish.shrunkTo(smaller);
+
+    EXPECT_FLOAT_EQ(8.0f, shrunkTo2.x());
+    EXPECT_FLOAT_EQ(80.0f, shrunkTo2.y());
+}
+
+TEST(FloatPoint, ExpandedTo)
+{
+    WebCore::FloatPoint big(100.0f, 200.0f);
+    WebCore::FloatPoint smaller(10.0f, 80.0f);
+
+    auto expandedTo = smaller.expandedTo(big);
+
+    EXPECT_FLOAT_EQ(100.0f, expandedTo.x());
+    EXPECT_FLOAT_EQ(200.0f, expandedTo.y());
+
+    WebCore::FloatPoint bigish(8.0f, 300.0f);
+
+    auto expandedTo2 = bigish.expandedTo(big);
+
+    EXPECT_FLOAT_EQ(100.0f, expandedTo2.x());
+    EXPECT_FLOAT_EQ(300.0f, expandedTo2.y());
+}
+
+TEST(FloatPoint, Transpose)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    EXPECT_FLOAT_EQ(100.0f, test.x());
+    EXPECT_FLOAT_EQ(200.0f, test.y());
+
+    auto transposed = test.transposedPoint();
+
+    EXPECT_FLOAT_EQ(200.0f, transposed.x());
+    EXPECT_FLOAT_EQ(100.0f, transposed.y());
+}
+
+TEST(FloatPoint, Transforms)
+{
+    WebCore::FloatPoint test(100.0f, 200.0f);
+
+    WebCore::AffineTransform affine;
+
+    auto transformed1 = test.matrixTransform(affine);
+
+    EXPECT_FLOAT_EQ(100.0f, transformed1.x());
+    EXPECT_FLOAT_EQ(200.0f, transformed1.y());
+
+    WebCore::AffineTransform affine2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0);
+
+    auto transformed2 = test.matrixTransform(affine2);
+
+    EXPECT_FLOAT_EQ(200.0f, transformed2.x());
+    EXPECT_FLOAT_EQ(400.0f, transformed2.y());
+
+    WebCore::TransformationMatrix matrix;
+
+    auto transformed3 = test.matrixTransform(matrix);
+
+    EXPECT_FLOAT_EQ(100.0f, transformed3.x());
+    EXPECT_FLOAT_EQ(200.0f, transformed3.y());
+
+    auto transformed4 = test.matrixTransform(affine2.toTransformationMatrix());
+
+    EXPECT_FLOAT_EQ(200.0f, transformed4.x());
+    EXPECT_FLOAT_EQ(400.0f, transformed4.y());
+}
+
+TEST(FloatPoint, Math)
+{
+    WebCore::FloatPoint a(100.0f, 200.0f);
+    WebCore::FloatPoint b(100.0f, 200.0f);
+
+    a += b;
+
+    EXPECT_FLOAT_EQ(200.0f, a.x());
+    EXPECT_FLOAT_EQ(400.0f, a.y());
+
+    WebCore::FloatSize c(50.0f, 50.0f);
+
+    a += c;
+
+    EXPECT_FLOAT_EQ(250.0f, a.x());
+    EXPECT_FLOAT_EQ(450.0f, a.y());
+
+    WebCore::FloatSize d(10.0f, 200.0f);
+
+    a -= d;
+
+    EXPECT_FLOAT_EQ(240.0f, a.x());
+    EXPECT_FLOAT_EQ(250.0f, a.y());
+
+    WebCore::FloatSize e(100.0f, 200.0f);
+
+    auto f = b + e;
+
+    EXPECT_FLOAT_EQ(200.0f, f.x());
+    EXPECT_FLOAT_EQ(400.0f, f.y());
+
+    WebCore::FloatPoint g(10.0f, 20.0f);
+
+    auto h = b + g;
+
+    EXPECT_FLOAT_EQ(110.0f, h.x());
+    EXPECT_FLOAT_EQ(220.0f, h.y());
+
+    WebCore::FloatSize i = b - g;
+
+    EXPECT_FLOAT_EQ(90.0f, i.width());
+    EXPECT_FLOAT_EQ(180.0f, i.height());
+
+    WebCore::FloatPoint j = b - e;
+
+    EXPECT_FLOAT_EQ(0.0f, j.x());
+    EXPECT_FLOAT_EQ(0.0f, j.y());
+
+    WebCore::FloatPoint negated = -b;
+
+    EXPECT_FLOAT_EQ(-100.0f, negated.x());
+    EXPECT_FLOAT_EQ(-200.0f, negated.y());
+
+    float value = b * g;
+
+    EXPECT_FLOAT_EQ(5000.0f, value);
+}
+
+TEST(FloatPoint, Equality)
+{
+    WebCore::FloatPoint a(100.0f, 200.0f);
+    WebCore::FloatPoint b(100.0f, 200.0f);
+    WebCore::FloatPoint c(10.0f, 20.0f);
+
+    ASSERT_TRUE(a == b);
+    ASSERT_FALSE(a == c);
+    ASSERT_FALSE(a != b);
+    ASSERT_TRUE(a != c);
+
+    ASSERT_TRUE(WebCore::areEssentiallyEqual(a, b));
+    ASSERT_FALSE(WebCore::areEssentiallyEqual(a, c));
+}
+
+TEST(FloatPoint, Floors)
+{
+    WebCore::FloatPoint a(100.6f, 199.9f);
+
+    WebCore::IntSize flooredSize = WebCore::flooredIntSize(a);
+    EXPECT_FLOAT_EQ(100, flooredSize.width());
+    EXPECT_FLOAT_EQ(199, flooredSize.height());
+
+    WebCore::IntPoint flooredPoint = WebCore::flooredIntPoint(a);
+    EXPECT_FLOAT_EQ(100, flooredPoint.x());
+    EXPECT_FLOAT_EQ(199, flooredPoint.y());
+
+    WebCore::FloatPoint flooredPoint1x = WebCore::floorPointToDevicePixels(a, 1.0);
+    EXPECT_FLOAT_EQ(100.0f, flooredPoint1x.x());
+    EXPECT_FLOAT_EQ(199.0f, flooredPoint1x.y());
+
+    WebCore::FloatPoint flooredPoint2x = WebCore::floorPointToDevicePixels(a, 2.0);
+    EXPECT_FLOAT_EQ(100.5f, flooredPoint2x.x());
+    EXPECT_FLOAT_EQ(199.5f, flooredPoint2x.y());
+}
+
+TEST(FloatPoint, Rounding)
+{
+    WebCore::FloatPoint a(100.4f, 199.9f);
+
+    WebCore::IntPoint roundedPoint = WebCore::roundedIntPoint(a);
+    EXPECT_FLOAT_EQ(100, roundedPoint.x());
+    EXPECT_FLOAT_EQ(200, roundedPoint.y());
+}
+
+TEST(FloatPoint, Ceiling)
+{
+    WebCore::FloatPoint a(100.4f, 199.9f);
+
+    WebCore::IntPoint ceilingPoint = WebCore::ceiledIntPoint(a);
+    EXPECT_FLOAT_EQ(101, ceilingPoint.x());
+    EXPECT_FLOAT_EQ(200, ceilingPoint.y());
+
+    WebCore::FloatPoint ceilingPoint1x = WebCore::ceilPointToDevicePixels(a, 1.0);
+    EXPECT_FLOAT_EQ(101.0f, ceilingPoint1x.x());
+    EXPECT_FLOAT_EQ(200.0f, ceilingPoint1x.y());
+
+    WebCore::FloatPoint ceilingPoint2x = WebCore::ceilPointToDevicePixels(a, 2.0);
+    EXPECT_FLOAT_EQ(100.5f, ceilingPoint2x.x());
+    EXPECT_FLOAT_EQ(200.0f, ceilingPoint2x.y());
+}
+
+TEST(FloatPoint, Casting)
+{
+    WebCore::FloatPoint a(100.4f, 199.9f);
+
+    WebCore::FloatSize floatSize = WebCore::toFloatSize(a);
+    EXPECT_FLOAT_EQ(100.4f, floatSize.width());
+    EXPECT_FLOAT_EQ(199.9f, floatSize.height());
+
+    WebCore::FloatSize b(99.6f, 299.1f);
+
+    WebCore::FloatPoint floatPoint = WebCore::toFloatPoint(b);
+    EXPECT_FLOAT_EQ(99.6f, floatPoint.x());
+    EXPECT_FLOAT_EQ(299.1f, floatPoint.y());
+
+#if USE(CG)
+    CGPoint cgPoint = a;
+
+    EXPECT_FLOAT_EQ(100.4f, cgPoint.x);
+    EXPECT_FLOAT_EQ(199.9f, cgPoint.y);
+
+    CGPoint cgPoint2 = CGPointMake(-22.3f, 14.2f);
+
+    WebCore::FloatPoint testCG(cgPoint2);
+
+    EXPECT_FLOAT_EQ(-22.3f, testCG.x());
+    EXPECT_FLOAT_EQ(14.2f, testCG.y());
+#endif
+
+#if PLATFORM(WIN)
+    D2D_POINT_2F d2dPoint = a;
+
+    EXPECT_FLOAT_EQ(100.4f, d2dPoint.x);
+    EXPECT_FLOAT_EQ(199.9f, d2dPoint.y);
+
+    D2D_POINT_2F d2dPoint2 = D2D1::Point2F(-22.3f, 14.2f);
+
+    WebCore::FloatPoint testD2D(d2dPoint2);
+
+    EXPECT_FLOAT_EQ(-22.3f, testD2D.x());
+    EXPECT_FLOAT_EQ(14.2f, testD2D.y());
+#endif
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp
new file mode 100644 (file)
index 0000000..63c072f
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntRect.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::FloatRect rect)
+{
+    rect.setX(1.1f);
+    EXPECT_FLOAT_EQ(1.1f, rect.x());
+    rect.setY(2.2f);
+    EXPECT_FLOAT_EQ(2.2f, rect.y());
+    rect.setWidth(203.2f);
+    EXPECT_FLOAT_EQ(203.2f, rect.width());
+    rect.setHeight(72.9f);
+    EXPECT_FLOAT_EQ(72.9f, rect.height());
+}
+
+static void testEmptyRect(const WebCore::FloatRect& rect)
+{
+    EXPECT_FLOAT_EQ(0, rect.x());
+    EXPECT_FLOAT_EQ(0, rect.y());
+    EXPECT_FLOAT_EQ(0, rect.width());
+    EXPECT_FLOAT_EQ(0, rect.height());
+    EXPECT_FLOAT_EQ(0, rect.maxX());
+    EXPECT_FLOAT_EQ(0, rect.maxY());
+    EXPECT_TRUE(rect.isEmpty());
+    EXPECT_TRUE(rect.isZero());
+    EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, DefaultConstruction)
+{
+    WebCore::FloatRect test;
+
+    testEmptyRect(test);
+
+    testGetAndSet(test);
+
+    auto location = test.location();
+    EXPECT_FLOAT_EQ(0, location.x());
+    EXPECT_FLOAT_EQ(0, location.y());
+
+    auto size = test.size();
+    EXPECT_FLOAT_EQ(0, size.width());
+    EXPECT_FLOAT_EQ(0, size.height());
+}
+
+TEST(FloatRect, ValueConstruction)
+{
+    WebCore::FloatRect test(10.0f, 20.0f, 100.0f, 50.0f);
+
+    EXPECT_FLOAT_EQ(10.0f, test.x());
+    EXPECT_FLOAT_EQ(20.0f, test.y());
+    EXPECT_FLOAT_EQ(100.0f, test.width());
+    EXPECT_FLOAT_EQ(50.0f, test.height());
+    EXPECT_FLOAT_EQ(110.0f, test.maxX());
+    EXPECT_FLOAT_EQ(70.0f, test.maxY());
+    EXPECT_FALSE(test.isEmpty());
+    EXPECT_FALSE(test.isZero());
+    EXPECT_FALSE(test.isInfinite());
+
+    auto location = test.location();
+    EXPECT_FLOAT_EQ(10.0f, location.x());
+    EXPECT_FLOAT_EQ(20.0f, location.y());
+
+    auto size = test.size();
+    EXPECT_FLOAT_EQ(100.0f, size.width());
+    EXPECT_FLOAT_EQ(50.0f, size.height());
+}
+
+TEST(FloatRect, PointSizeConstruction)
+{
+    WebCore::FloatPoint location(20.0f, 30.0f);
+    WebCore::FloatSize size(100.0f, 50.0f);
+
+    WebCore::FloatRect test(location, size);
+
+    EXPECT_FLOAT_EQ(20.0f, test.x());
+    EXPECT_FLOAT_EQ(30.0f, test.y());
+    EXPECT_FLOAT_EQ(100.0f, test.width());
+    EXPECT_FLOAT_EQ(50.0f, test.height());
+    EXPECT_FLOAT_EQ(120.0f, test.maxX());
+    EXPECT_FLOAT_EQ(80.0f, test.maxY());
+    EXPECT_FALSE(test.isEmpty());
+    EXPECT_FALSE(test.isZero());
+    EXPECT_FALSE(test.isInfinite());
+
+    auto location2 = test.location();
+    EXPECT_FLOAT_EQ(20.0f, location2.x());
+    EXPECT_FLOAT_EQ(30.0f, location2.y());
+
+    auto size2 = test.size();
+    EXPECT_FLOAT_EQ(100.0f, size2.width());
+    EXPECT_FLOAT_EQ(50.0f, size2.height());
+}
+
+TEST(FloatRect, TwoPointConstruction)
+{
+    WebCore::FloatPoint point1(20.0f, 30.0f);
+    WebCore::FloatPoint point2(150.0f, 250.0f);
+
+    WebCore::FloatRect test(point1, point2);
+
+    EXPECT_FLOAT_EQ(20.0f, test.x());
+    EXPECT_FLOAT_EQ(30.0f, test.y());
+    EXPECT_FLOAT_EQ(130.0f, test.width());
+    EXPECT_FLOAT_EQ(220.0f, test.height());
+    EXPECT_FLOAT_EQ(150.0f, test.maxX());
+    EXPECT_FLOAT_EQ(250.0f, test.maxY());
+    EXPECT_FALSE(test.isEmpty());
+    EXPECT_FALSE(test.isZero());
+    EXPECT_FALSE(test.isInfinite());
+
+    auto location = test.location();
+    EXPECT_FLOAT_EQ(20.0f, location.x());
+    EXPECT_FLOAT_EQ(30.0f, location.y());
+
+    auto size = test.size();
+    EXPECT_FLOAT_EQ(130.0f, size.width());
+    EXPECT_FLOAT_EQ(220.0f, size.height());
+}
+
+TEST(FloatRect, IntRectConstruction)
+{
+    WebCore::IntRect rect(20, 30, 150, 300);
+
+    WebCore::FloatRect test(rect);
+
+    EXPECT_FLOAT_EQ(20.0f, test.x());
+    EXPECT_FLOAT_EQ(30.0f, test.y());
+    EXPECT_FLOAT_EQ(150.0f, test.width());
+    EXPECT_FLOAT_EQ(300.0f, test.height());
+    EXPECT_FLOAT_EQ(170.0f, test.maxX());
+    EXPECT_FLOAT_EQ(330.0f, test.maxY());
+    EXPECT_FALSE(test.isEmpty());
+    EXPECT_FALSE(test.isZero());
+    EXPECT_FALSE(test.isInfinite());
+
+    auto location = test.location();
+    EXPECT_FLOAT_EQ(20.0f, location.x());
+    EXPECT_FLOAT_EQ(30.0f, location.y());
+
+    auto size = test.size();
+    EXPECT_FLOAT_EQ(150.0f, size.width());
+    EXPECT_FLOAT_EQ(300.0f, size.height());
+}
+
+TEST(FloatRect, SetLocationAndSize)
+{
+    WebCore::FloatRect rect;
+
+    testEmptyRect(rect);
+
+    WebCore::FloatPoint location(10.0f, 20.0f);
+
+    rect.setLocation(location);
+
+    EXPECT_FLOAT_EQ(10.0f, rect.x());
+    EXPECT_FLOAT_EQ(20.0f, rect.y());
+    EXPECT_FLOAT_EQ(0.0f, rect.width());
+    EXPECT_FLOAT_EQ(0.0f, rect.height());
+    EXPECT_FLOAT_EQ(10.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(20.0f, rect.maxY());
+    EXPECT_TRUE(rect.isEmpty());
+    EXPECT_TRUE(rect.isZero());
+    EXPECT_FALSE(rect.isInfinite());
+
+    WebCore::FloatSize size(100.0f, 200.0f);
+
+    rect.setSize(size);
+
+    EXPECT_FLOAT_EQ(10.0f, rect.x());
+    EXPECT_FLOAT_EQ(20.0f, rect.y());
+    EXPECT_FLOAT_EQ(100.0f, rect.width());
+    EXPECT_FLOAT_EQ(200.0f, rect.height());
+    EXPECT_FLOAT_EQ(110.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(220.0f, rect.maxY());
+    EXPECT_FALSE(rect.isEmpty());
+    EXPECT_FALSE(rect.isZero());
+    EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, Center)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    auto center = rect.center();
+
+    EXPECT_FLOAT_EQ(70.0f, center.x());
+    EXPECT_FLOAT_EQ(130.0f, center.y());
+}
+
+TEST(FloatRect, Move)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    WebCore::FloatSize delta(10.0f, 20.0f);
+
+    rect.move(delta);
+
+    EXPECT_FLOAT_EQ(30.0f, rect.x());
+    EXPECT_FLOAT_EQ(50.0f, rect.y());
+
+    WebCore::FloatPoint deltaPoint(-20.0f, -40.0f);
+
+    rect.moveBy(deltaPoint);
+
+    EXPECT_FLOAT_EQ(10.0f, rect.x());
+    EXPECT_FLOAT_EQ(10.0f, rect.y());
+
+    rect.move(-10.0f, 22.0f);
+
+    EXPECT_FLOAT_EQ(0.0f, rect.x());
+    EXPECT_FLOAT_EQ(32.0f, rect.y());
+}
+
+TEST(FloatRect, Expand)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    WebCore::FloatSize size(100.0f, 100.0f);
+
+    rect.expand(size);
+
+    EXPECT_FLOAT_EQ(200.0f, rect.width());
+    EXPECT_FLOAT_EQ(300.0f, rect.height());
+
+    rect.expand(55.0f, 22.0f);
+
+    EXPECT_FLOAT_EQ(255.0f, rect.width());
+    EXPECT_FLOAT_EQ(322.0f, rect.height());
+
+    WebCore::FloatSize size2(-10.0f, -20.0f);
+
+    rect.expand(size2);
+
+    EXPECT_FLOAT_EQ(245.0f, rect.width());
+    EXPECT_FLOAT_EQ(302.0f, rect.height());
+
+    rect.expand(-5.0f, -2.0f);
+
+    EXPECT_FLOAT_EQ(240.0f, rect.width());
+    EXPECT_FLOAT_EQ(300.0f, rect.height());
+
+    EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, Contract)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    WebCore::FloatSize size(50.0f, 100.0f);
+
+    rect.contract(size);
+
+    EXPECT_FLOAT_EQ(50.0f, rect.width());
+    EXPECT_FLOAT_EQ(100.0f, rect.height());
+
+    rect.contract(25.0f, 22.0f);
+
+    EXPECT_FLOAT_EQ(25.0f, rect.width());
+    EXPECT_FLOAT_EQ(78.0f, rect.height());
+
+    WebCore::FloatSize size2(-10.0f, -20.0f);
+
+    rect.contract(size2);
+
+    EXPECT_FLOAT_EQ(35.0f, rect.width());
+    EXPECT_FLOAT_EQ(98.0f, rect.height());
+
+    rect.contract(-5.0f, -2.0f);
+
+    EXPECT_FLOAT_EQ(40.0f, rect.width());
+    EXPECT_FLOAT_EQ(100.0f, rect.height());
+
+    EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, ShiftXEdge)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    rect.shiftXEdgeTo(77.0f);
+
+    EXPECT_FLOAT_EQ(77.0f, rect.x());
+    EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(30.0f, rect.y());
+    EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+    EXPECT_FLOAT_EQ(43.0f, rect.width());
+    EXPECT_FLOAT_EQ(200.0f, rect.height());
+
+    rect.shiftMaxXEdgeTo(200.0f);
+
+    EXPECT_FLOAT_EQ(77.0f, rect.x());
+    EXPECT_FLOAT_EQ(200.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(30.0f, rect.y());
+    EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+    EXPECT_FLOAT_EQ(123.0f, rect.width());
+    EXPECT_FLOAT_EQ(200.0f, rect.height());
+}
+
+TEST(FloatRect, ShiftYEdge)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    rect.shiftYEdgeTo(59.0f);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(59.0f, rect.y());
+    EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+    EXPECT_FLOAT_EQ(100.0f, rect.width());
+    EXPECT_FLOAT_EQ(171.0f, rect.height());
+
+    rect.shiftMaxYEdgeTo(270.0f);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(59.0f, rect.y());
+    EXPECT_FLOAT_EQ(270.0f, rect.maxY());
+    EXPECT_FLOAT_EQ(100.0f, rect.width());
+    EXPECT_FLOAT_EQ(211.0f, rect.height());
+}
+
+TEST(FloatRect, Inflate)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    rect.inflateX(5.0f);
+
+    EXPECT_FLOAT_EQ(15.0f, rect.x());
+    EXPECT_FLOAT_EQ(125.0f, rect.maxX());
+
+    rect.inflateY(4.0f);
+
+    EXPECT_FLOAT_EQ(26.0f, rect.y());
+    EXPECT_FLOAT_EQ(234.0f, rect.maxY());
+
+    rect.inflate(10.0f);
+
+    EXPECT_FLOAT_EQ(5.0f, rect.x());
+    EXPECT_FLOAT_EQ(135.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(16.0f, rect.y());
+    EXPECT_FLOAT_EQ(244.0f, rect.maxY());
+
+    EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, Corners)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    WebCore::FloatPoint topLeft = rect.minXMinYCorner();
+    EXPECT_FLOAT_EQ(20.0f, topLeft.x());
+    EXPECT_FLOAT_EQ(30.0f, topLeft.y());
+
+    WebCore::FloatPoint topRight = rect.maxXMinYCorner();
+    EXPECT_FLOAT_EQ(120.0f, topRight.x());
+    EXPECT_FLOAT_EQ(30.0f, topRight.y());
+
+    WebCore::FloatPoint bottomLeft = rect.minXMaxYCorner();
+    EXPECT_FLOAT_EQ(20.0f, bottomLeft.x());
+    EXPECT_FLOAT_EQ(230.0f, bottomLeft.y());
+
+    WebCore::FloatPoint bottomRight = rect.maxXMaxYCorner();
+    EXPECT_FLOAT_EQ(120.0f, bottomRight.x());
+    EXPECT_FLOAT_EQ(230.0f, bottomRight.y());
+}
+
+TEST(FloatRect, Contains)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    WebCore::FloatRect contained(30.0f, 40.0f, 50.0f, 100.0f);
+
+    ASSERT_TRUE(rect.contains(contained));
+
+    WebCore::FloatRect outside(120.0f, 230.0f, 50.0f, 100.0f);
+
+    ASSERT_FALSE(rect.contains(outside));
+
+    WebCore::FloatRect intersects(10.0f, 20.0f, 90.0f, 180.0f);
+
+    ASSERT_FALSE(rect.contains(intersects));
+
+    WebCore::FloatPoint pointInside(60.0f, 70.0f);
+
+    ASSERT_TRUE(rect.contains(pointInside));
+    ASSERT_TRUE(rect.contains(pointInside, WebCore::FloatRect::InsideButNotOnStroke));
+
+    WebCore::FloatPoint pointOutside(160.0f, 270.0f);
+
+    ASSERT_FALSE(rect.contains(pointOutside));
+    ASSERT_FALSE(rect.contains(pointOutside, WebCore::FloatRect::InsideButNotOnStroke));
+
+    WebCore::FloatPoint pointOnLine(20.0f, 30.0f);
+
+    ASSERT_TRUE(rect.contains(pointOnLine));
+    ASSERT_FALSE(rect.contains(pointOutside, WebCore::FloatRect::InsideButNotOnStroke));
+
+    ASSERT_TRUE(rect.contains(60.0f, 70.0f));
+    ASSERT_FALSE(rect.contains(160.0f, 270.0f));
+}
+
+TEST(FloatRect, Intersects)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    WebCore::FloatRect contained(30.0f, 40.0f, 50.0f, 100.0f);
+
+    ASSERT_TRUE(rect.intersects(contained));
+
+    WebCore::FloatRect outside(120.0f, 230.0f, 50.0f, 100.0f);
+
+    ASSERT_FALSE(rect.intersects(outside));
+
+    WebCore::FloatRect intersects(10.0f, 20.0f, 90.0f, 180.0f);
+
+    ASSERT_TRUE(rect.intersects(intersects));
+}
+
+static void testIntersectResult(const WebCore::FloatRect& rect)
+{
+    EXPECT_FLOAT_EQ(70.0f, rect.x());
+    EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(80.0f, rect.y());
+    EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+}
+
+TEST(FloatRect, Intersect)
+{
+    WebCore::FloatRect rectA(20.0f, 30.0f, 100.0f, 200.0f);
+    WebCore::FloatRect rectB(70.0f, 80.0f, 100.0f, 200.0f);
+
+    rectA.intersect(rectB);
+
+    testIntersectResult(rectA);
+
+    WebCore::FloatRect rectC(20.0f, 30.0f, 100.0f, 200.0f);
+
+    auto intersected = WebCore::intersection(rectC, rectB);
+
+    testIntersectResult(intersected);
+}
+
+static void testUnitedRects(const WebCore::FloatRect& united)
+{
+    EXPECT_FLOAT_EQ(20.0f, united.x());
+    EXPECT_FLOAT_EQ(170.0f, united.maxX());
+    EXPECT_FLOAT_EQ(30.0f, united.y());
+    EXPECT_FLOAT_EQ(280.0f, united.maxY());
+}
+
+TEST(FloatRect, Unite)
+{
+    WebCore::FloatRect rectA(20.0f, 30.0f, 100.0f, 200.0f);
+    WebCore::FloatRect rectB(70.0f, 80.0f, 100.0f, 200.0f);
+
+    rectA.unite(rectB);
+
+    testUnitedRects(rectA);
+
+    WebCore::FloatRect rectC(20.0f, 30.0f, 100.0f, 200.0f);
+
+    auto united = WebCore::unionRect(rectC, rectB);
+
+    testUnitedRects(united);
+}
+
+TEST(FloatRect, Extend)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+    WebCore::FloatPoint point(170.0f, 280.0f);
+
+    rect.extend(point);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(170.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(30.0f, rect.y());
+    EXPECT_FLOAT_EQ(280.0f, rect.maxY());
+}
+
+TEST(FloatRect, Overlaps)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    ASSERT_FALSE(rect.overlapsXRange(0.0f, 10.0f));
+    ASSERT_TRUE(rect.overlapsXRange(10.0f, 30.0f));
+    ASSERT_TRUE(rect.overlapsXRange(40.0f, 70.0f));
+    ASSERT_TRUE(rect.overlapsXRange(110.0f, 130.0f));
+    ASSERT_FALSE(rect.overlapsXRange(140.0f, 600.0f));
+
+    ASSERT_FALSE(rect.overlapsYRange(0.0f, 10.0f));
+    ASSERT_TRUE(rect.overlapsYRange(10.0f, 40.0f));
+    ASSERT_TRUE(rect.overlapsYRange(40.0f, 70.0f));
+    ASSERT_TRUE(rect.overlapsYRange(220.0f, 250.0f));
+    ASSERT_FALSE(rect.overlapsYRange(250.0f, 600.0f));
+}
+
+TEST(FloatRect, Scale)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    rect.scale(2.0f);
+
+    EXPECT_FLOAT_EQ(40.0f, rect.x());
+    EXPECT_FLOAT_EQ(240.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(60.0f, rect.y());
+    EXPECT_FLOAT_EQ(460.0f, rect.maxY());
+
+    rect.scale(0.5f, 2.0f);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(120.0f, rect.y());
+    EXPECT_FLOAT_EQ(920.0f, rect.maxY());
+
+    rect.scale(1.0f, 0.25f);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(30.0f, rect.y());
+    EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+}
+
+TEST(FloatRect, Transpose)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+    auto transposed = rect.transposedRect();
+
+    EXPECT_FLOAT_EQ(30.0f, transposed.x());
+    EXPECT_FLOAT_EQ(230.0f, transposed.maxX());
+    EXPECT_FLOAT_EQ(20.0f, transposed.y());
+    EXPECT_FLOAT_EQ(120.0f, transposed.maxY());
+}
+
+TEST(FloatRect, FitToPoints)
+{
+    WebCore::FloatRect rect(10.0f, 20.0f, 30.0f, 40.0f);
+
+    WebCore::FloatPoint p0(20.0f, 30.0f);
+    WebCore::FloatPoint p1(70.0f, 130.0f);
+    WebCore::FloatPoint p2(50.0f, 20.0f);
+    WebCore::FloatPoint p3(90.0f, 190.0f);
+
+    rect.fitToPoints(p0, p1);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(70.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(30.0f, rect.y());
+    EXPECT_FLOAT_EQ(130.0f, rect.maxY());
+
+    rect.fitToPoints(p0, p1, p2);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(70.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(20.0f, rect.y());
+    EXPECT_FLOAT_EQ(130.0f, rect.maxY());
+
+    rect.fitToPoints(p0, p1, p2, p3);
+
+    EXPECT_FLOAT_EQ(20.0f, rect.x());
+    EXPECT_FLOAT_EQ(90.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(20.0f, rect.y());
+    EXPECT_FLOAT_EQ(190.0f, rect.maxY());
+}
+
+static void checkCastRect(const WebCore::FloatRect& rect)
+{
+    EXPECT_FLOAT_EQ(10.0f, rect.x());
+    EXPECT_FLOAT_EQ(40.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(20.0f, rect.y());
+    EXPECT_FLOAT_EQ(60.0f, rect.maxY());
+    EXPECT_FLOAT_EQ(30.0f, rect.width());
+    EXPECT_FLOAT_EQ(40.0f, rect.height());
+}
+
+TEST(FloatRect, Casting)
+{
+    WebCore::FloatRect rect(10.0f, 20.0f, 30.0f, 40.0f);
+
+#if USE(CG)
+    CGRect cgRect = rect;
+
+    EXPECT_FLOAT_EQ(10.0f, cgRect.origin.x);
+    EXPECT_FLOAT_EQ(20.0f, cgRect.origin.y);
+    EXPECT_FLOAT_EQ(30.0f, cgRect.size.width);
+    EXPECT_FLOAT_EQ(40.0f, cgRect.size.height);
+
+    WebCore::FloatRect rectFromCGRect(cgRect);
+
+    checkCastRect(rectFromCGRect);
+#endif
+
+#if PLATFORM(WIN)
+    D2D1_RECT_F d2dRect = rect;
+
+    EXPECT_FLOAT_EQ(10.0f, d2dRect.left);
+    EXPECT_FLOAT_EQ(20.0f, d2dRect.top);
+    EXPECT_FLOAT_EQ(40.0f, d2dRect.right);
+    EXPECT_FLOAT_EQ(60.0f, d2dRect.bottom);
+
+    WebCore::FloatRect rectFromD2DRect(d2dRect);
+
+    checkCastRect(rectFromD2DRect);
+#endif
+}
+
+static void checkAdditionResult1(const WebCore::FloatRect& rect)
+{
+    EXPECT_FLOAT_EQ(10.0f, rect.x());
+    EXPECT_FLOAT_EQ(130.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(20.0f, rect.y());
+    EXPECT_FLOAT_EQ(220.0f, rect.maxY());
+    EXPECT_FLOAT_EQ(120.0f, rect.width());
+    EXPECT_FLOAT_EQ(200.0f, rect.height());
+}
+
+static void checkAdditionResult2(const WebCore::FloatRect& rect)
+{
+    EXPECT_FLOAT_EQ(10.0f, rect.x());
+    EXPECT_FLOAT_EQ(250.0f, rect.maxX());
+    EXPECT_FLOAT_EQ(20.0f, rect.y());
+    EXPECT_FLOAT_EQ(240.0f, rect.maxY());
+    EXPECT_FLOAT_EQ(240.0f, rect.width());
+    EXPECT_FLOAT_EQ(220.0f, rect.height());
+}
+
+TEST(FloatRect, Addition)
+{
+    WebCore::FloatRect rect(10.0f, 20.0f, 100.0f, 100.0f);
+    WebCore::FloatRect rightSide(0.0f, 0.0f, 20.0f, 100.0f);
+    WebCore::FloatRect bottom(0.0f, 0.0f, 120.0f, 20.0f);
+
+    auto combined = rect + rightSide;
+
+    checkAdditionResult1(combined);
+
+    auto combined2 = combined + bottom;
+
+    checkAdditionResult2(combined2);
+
+    rect += rightSide;
+    rect += bottom;
+
+    checkAdditionResult2(rect);
+}
+
+TEST(FloatRect, Equality)
+{
+    WebCore::FloatRect rect(10.0f, 20.0f, 100.0f, 100.0f);
+    WebCore::FloatRect rect2(10.0f, 20.0f, 100.0f, 100.0f);
+    WebCore::FloatRect rightSide(110.0f, 20.0f, 20.0f, 100.0f);
+
+    ASSERT_TRUE(rect == rect2);
+    ASSERT_FALSE(rect != rect2);
+    ASSERT_TRUE(rect != rightSide);
+    ASSERT_FALSE(rect == rightSide);
+}
+
+TEST(FloatRect, InfiniteRect)
+{
+    WebCore::FloatRect infinite = WebCore::FloatRect::infiniteRect();
+
+    EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max() / 2, infinite.x());
+    EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max() / 2, infinite.y());
+    EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), infinite.width());
+    EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), infinite.height());
+
+    // FIXME: We have an unusual representation for our infinite rect.
+    // WebCore::Float::infiniteRect is (negative infinity)/2 for the upper left corner,
+    // while CoreGraphics and D2D use (negative infinity).
+
+#if USE(CG)
+    CGRect cgInfiniteRect = CGRectInfinite;
+
+    EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), cgInfiniteRect.origin.x);
+    EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), cgInfiniteRect.origin.y);
+    EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), cgInfiniteRect.origin.x + cgInfiniteRect.size.width);
+    EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), cgInfiniteRect.origin.y + cgInfiniteRect.size.height);
+    // ASSERT_TRUE(infinite == cgInfiniteRect);
+#endif
+
+#if PLATFORM(WIN)
+    D2D1_RECT_F d2dInfiniteRect = D2D1::InfiniteRect();
+
+    EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), d2dInfiniteRect.left);
+    EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), d2dInfiniteRect.top);
+    EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), d2dInfiniteRect.right);
+    EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), d2dInfiniteRect.bottom);
+    // ASSERT_TRUE(infinite == d2dInfiniteRect);
+#endif
+}
+
+TEST(FloatRect, EnclosingAndRounding)
+{
+    WebCore::FloatRect rect(10.0f, 20.0f, 1024.3f, 768.3f);
+
+    auto enclosed = WebCore::encloseRectToDevicePixels(rect, 1.0f);
+
+    EXPECT_FLOAT_EQ(10.0f, enclosed.x());
+    EXPECT_FLOAT_EQ(20.0f, enclosed.y());
+    EXPECT_FLOAT_EQ(1035.0f, enclosed.maxX());
+    EXPECT_FLOAT_EQ(789.0f, enclosed.maxY());
+
+    auto enclosed2 = WebCore::encloseRectToDevicePixels(rect, 2.0f);
+
+    EXPECT_FLOAT_EQ(10.0f, enclosed2.x());
+    EXPECT_FLOAT_EQ(20.0f, enclosed2.y());
+    EXPECT_FLOAT_EQ(1034.5f, enclosed2.maxX());
+    EXPECT_FLOAT_EQ(788.5f, enclosed2.maxY());
+}
+
+TEST(FloatRect, EnclosingIntRect)
+{
+    WebCore::FloatRect rect(10.0f, 20.0f, 1024.3f, 768.6f);
+
+    auto enclosed = WebCore::enclosingIntRect(rect);
+
+    EXPECT_FLOAT_EQ(10, enclosed.x());
+    EXPECT_FLOAT_EQ(20, enclosed.y());
+    EXPECT_FLOAT_EQ(1035, enclosed.maxX());
+    EXPECT_FLOAT_EQ(789, enclosed.maxY());
+}
+
+TEST(FloatRect, RoundedIntRect)
+{
+    WebCore::FloatRect rect(10.0f, 20.0f, 1024.3f, 768.6f);
+
+    auto enclosed = WebCore::roundedIntRect(rect);
+
+    EXPECT_FLOAT_EQ(10, enclosed.x());
+    EXPECT_FLOAT_EQ(20, enclosed.y());
+    EXPECT_FLOAT_EQ(1034, enclosed.maxX());
+    EXPECT_FLOAT_EQ(789, enclosed.maxY());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp
new file mode 100644 (file)
index 0000000..756e76f
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::FloatSize size)
+{
+    size.setWidth(101.1f);
+    EXPECT_FLOAT_EQ(101.1f, size.width());
+    size.setHeight(218.2f);
+    EXPECT_FLOAT_EQ(218.2f, size.height());
+}
+
+TEST(FloatSize, DefaultConstruction)
+{
+    WebCore::FloatSize test;
+
+    EXPECT_FLOAT_EQ(0, test.width());
+    EXPECT_FLOAT_EQ(0, test.height());
+
+    ASSERT_TRUE(test.isEmpty());
+    ASSERT_TRUE(test.isZero());
+
+    testGetAndSet(test);
+}
+
+TEST(FloatSize, ValueConstruction)
+{
+    WebCore::FloatSize test(1024.0f, 768.0f);
+
+    EXPECT_FLOAT_EQ(1024.0f, test.width());
+    EXPECT_FLOAT_EQ(768.0f, test.height());
+
+    ASSERT_FALSE(test.isEmpty());
+    ASSERT_FALSE(test.isZero());
+
+    static const float epsilon = 0.0001f;
+    EXPECT_NEAR(1.3333f, test.aspectRatio(), epsilon);
+
+    testGetAndSet(test);
+}
+
+TEST(FloatSize, IntSizeConstruction)
+{
+    WebCore::IntSize size(1024, 768);
+    WebCore::FloatSize test(size);
+
+    EXPECT_FLOAT_EQ(1024.0f, test.width());
+    EXPECT_FLOAT_EQ(768.0f, test.height());
+
+    ASSERT_FALSE(test.isEmpty());
+    ASSERT_FALSE(test.isZero());
+
+    static const double epsilon = 0.0001;
+    EXPECT_NEAR(1.3333f, test.aspectRatio(), epsilon);
+
+    testGetAndSet(test);
+}
+
+TEST(FloatSize, Scale)
+{
+    WebCore::FloatSize test(1024.0f, 768.0f);
+
+    test.scale(2.0f);
+
+    EXPECT_FLOAT_EQ(2048.0f, test.width());
+    EXPECT_FLOAT_EQ(1536.0f, test.height());
+
+    test.scale(0.5f);
+
+    EXPECT_FLOAT_EQ(1024.0f, test.width());
+    EXPECT_FLOAT_EQ(768.0f, test.height());
+
+    test.scale(2.0f, 0.5f);
+
+    EXPECT_FLOAT_EQ(2048.0f, test.width());
+    EXPECT_FLOAT_EQ(384.0f, test.height());
+}
+
+TEST(FloatSize, Expand)
+{
+    WebCore::FloatSize test(1024.0f, 768.0f);
+
+    EXPECT_FLOAT_EQ(1024.0f, test.width());
+    EXPECT_FLOAT_EQ(768.0f, test.height());
+
+    test.expand(100.0f, 50.0f);
+
+    EXPECT_FLOAT_EQ(1124.0f, test.width());
+    EXPECT_FLOAT_EQ(818.0f, test.height());
+
+    WebCore::FloatSize other(2048.0f, 700.0f);
+
+    auto expanded = test.expandedTo(other);
+
+    EXPECT_FLOAT_EQ(2048.0f, expanded.width());
+    EXPECT_FLOAT_EQ(818.0f, expanded.height());
+}
+
+TEST(FloatSize, Shrink)
+{
+    WebCore::FloatSize test(1024.0f, 768.0f);
+    WebCore::FloatSize other(1000.0f, 700.0f);
+
+    auto shrunken = test.shrunkTo(other);
+
+    EXPECT_FLOAT_EQ(1000.0f, shrunken.width());
+    EXPECT_FLOAT_EQ(700.0f, shrunken.height());
+
+    WebCore::FloatSize other2(2000.0f, 700.0f);
+
+    auto shrunken2 = test.shrunkTo(other2);
+
+    EXPECT_FLOAT_EQ(1024.0f, shrunken2.width());
+    EXPECT_FLOAT_EQ(700.0f, shrunken2.height());
+}
+
+TEST(FloatSize, DiagonalLengthAndArea)
+{
+    WebCore::FloatSize test(1024.0f, 768.0f);
+
+    EXPECT_FLOAT_EQ(1280.0f, test.diagonalLength());
+    EXPECT_FLOAT_EQ(1638400.0f, test.diagonalLengthSquared());
+    EXPECT_FLOAT_EQ(786432.0f, test.area());
+}
+
+TEST(FloatSize, TransposedSize)
+{
+    WebCore::FloatSize test(1024.0f, 768.0f);
+
+    auto transposedSize = test.transposedSize();
+
+    EXPECT_FLOAT_EQ(768.0f, transposedSize.width());
+    EXPECT_FLOAT_EQ(1024.0f, transposedSize.height());
+}
+
+TEST(FloatSize, Casting)
+{
+    WebCore::FloatSize test(1024.0f, 768.0f);
+
+#if USE(CG)
+    CGSize cgSize = test;
+
+    EXPECT_FLOAT_EQ(1024.0f, cgSize.width);
+    EXPECT_FLOAT_EQ(768.0f, cgSize.height);
+
+    CGSize cgSize2 = CGSizeMake(-22.3f, 14.2f);
+
+    WebCore::FloatSize testCG(cgSize2);
+
+    EXPECT_FLOAT_EQ(-22.3f, testCG.width());
+    EXPECT_FLOAT_EQ(14.2f, testCG.height());
+#endif
+
+#if PLATFORM(WIN)
+    D2D1_SIZE_F d2dSize = test;
+
+    EXPECT_FLOAT_EQ(1024.0f, d2dSize.width);
+    EXPECT_FLOAT_EQ(768.0f, d2dSize.height);
+
+    D2D1_SIZE_F d2dSize2 = D2D1::SizeF(-22.3f, 14.2f);
+
+    WebCore::FloatSize testD2D(d2dSize2);
+
+    EXPECT_FLOAT_EQ(-22.3f, testD2D.width());
+    EXPECT_FLOAT_EQ(14.2f, testD2D.height());
+#endif
+}
+
+TEST(FloatSize, AddSubtract)
+{
+    WebCore::FloatSize a(512.0f, 384.0f);
+    WebCore::FloatSize b(100.0f, 100.0f);
+
+    WebCore::FloatSize c = a + b;
+
+    EXPECT_FLOAT_EQ(612.0f, c.width());
+    EXPECT_FLOAT_EQ(484.0f, c.height());
+
+    a += b;
+
+    EXPECT_FLOAT_EQ(612.0f, a.width());
+    EXPECT_FLOAT_EQ(484.0f, a.height());
+
+    WebCore::FloatSize a2(512.0f, 384.0f);
+
+    WebCore::FloatSize d = a2 - b;
+
+    EXPECT_FLOAT_EQ(412.0f, d.width());
+    EXPECT_FLOAT_EQ(284.0f, d.height());
+
+    a2 -= b;
+
+    EXPECT_FLOAT_EQ(412.0f, a2.width());
+    EXPECT_FLOAT_EQ(284.0f, a2.height());
+}
+
+TEST(FloatSize, Negation)
+{
+    WebCore::FloatSize a(512.0f, 384.0f);
+
+    WebCore::FloatSize negated = -a;
+
+    EXPECT_FLOAT_EQ(-512.0f, negated.width());
+    EXPECT_FLOAT_EQ(-384.0f, negated.height());
+}
+
+TEST(FloatSize, Multiply)
+{
+    WebCore::FloatSize a(512.0f, 384.0f);
+
+    WebCore::FloatSize multiplied = a * 2.0f;
+
+    EXPECT_FLOAT_EQ(1024.0f, multiplied.width());
+    EXPECT_FLOAT_EQ(768.0f, multiplied.height());
+
+    WebCore::FloatSize multiplied2 = 3.0f * a;
+
+    EXPECT_FLOAT_EQ(1536.0f, multiplied2.width());
+    EXPECT_FLOAT_EQ(1152.0f, multiplied2.height());
+
+    WebCore::FloatSize b(1024.0f, 768.0f);
+
+    WebCore::FloatSize multiplied3 = a * b;
+
+    EXPECT_FLOAT_EQ(524288.0f, multiplied3.width());
+    EXPECT_FLOAT_EQ(294912.0f, multiplied3.height());
+}
+
+TEST(FloatSize, Divide)
+{
+    WebCore::FloatSize a(1024.0f, 768.0f);
+
+    WebCore::FloatSize divided = a / 2.0f;
+
+    EXPECT_FLOAT_EQ(512.0f, divided.width());
+    EXPECT_FLOAT_EQ(384.0f, divided.height());
+
+    WebCore::FloatSize b(512.0f, 256.0f);
+
+    WebCore::FloatSize divided2 = 1024.0f / b;
+
+    EXPECT_FLOAT_EQ(2.0f, divided2.width());
+    EXPECT_FLOAT_EQ(4.0f, divided2.height());
+}
+
+TEST(FloatSize, Equality)
+{
+    WebCore::FloatSize a(1024.0f, 768.0f);
+    WebCore::FloatSize b(1024.0f, 768.0f);
+    WebCore::FloatSize c(768.0f, 534.0F);
+
+    ASSERT_TRUE(a == b);
+    ASSERT_FALSE(a != b);
+    ASSERT_FALSE(a == c);
+    ASSERT_TRUE(a != c);
+
+    ASSERT_TRUE(WebCore::areEssentiallyEqual(a, b));
+    ASSERT_FALSE(WebCore::areEssentiallyEqual(a, c));
+}
+
+TEST(FloatSize, Floors)
+{
+    WebCore::FloatSize a(1024.4f, 768.8f);
+
+    WebCore::IntSize floorSize = WebCore::flooredIntSize(a);
+
+    EXPECT_EQ(1024, floorSize.width());
+    EXPECT_EQ(768, floorSize.height());
+
+    WebCore::IntPoint floorPoint = WebCore::flooredIntPoint(a);
+
+    EXPECT_EQ(1024, floorPoint.x());
+    EXPECT_EQ(768, floorPoint.y());
+}
+
+TEST(FloatSize, Rounded)
+{
+    WebCore::FloatSize a(1024.4f, 768.8f);
+
+    WebCore::IntSize roundedSize = WebCore::roundedIntSize(a);
+
+    EXPECT_EQ(1024, roundedSize.width());
+    EXPECT_EQ(769, roundedSize.height());
+
+    WebCore::IntSize expandedSize = WebCore::expandedIntSize(a);
+
+    EXPECT_EQ(1025, expandedSize.width());
+    EXPECT_EQ(769, expandedSize.height());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp b/Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp
new file mode 100644 (file)
index 0000000..aa332e5
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatPoint.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::IntPoint point)
+{
+    point.setX(1);
+    EXPECT_EQ(1, point.x());
+    point.setY(2);
+    EXPECT_EQ(2, point.y());
+}
+
+TEST(IntPoint, DefaultConstruction)
+{
+    WebCore::IntPoint test;
+
+    EXPECT_EQ(0, test.x());
+    EXPECT_EQ(0, test.y());
+    ASSERT_TRUE(test.isZero());
+
+    testGetAndSet(test);
+}
+
+TEST(IntPoint, ValueConstruction)
+{
+    WebCore::IntPoint test(10, 9);
+
+    EXPECT_EQ(10, test.x());
+    EXPECT_EQ(9, test.y());
+
+    testGetAndSet(test);
+}
+
+TEST(IntPoint, ZeroConstruction)
+{
+    WebCore::IntPoint test = WebCore::IntPoint::zero();
+
+    EXPECT_EQ(0, test.x());
+    EXPECT_EQ(0, test.y());
+    ASSERT_TRUE(test.isZero());
+}
+
+TEST(IntPoint, IntSizeConstruction)
+{
+    WebCore::IntSize testInput(2003, 1997);
+    WebCore::IntPoint test(testInput);
+
+    EXPECT_EQ(2003, test.x());
+    EXPECT_EQ(1997, test.y());
+    ASSERT_FALSE(test.isZero());
+}
+
+TEST(IntPoint, FloatPointConstruction)
+{
+    WebCore::FloatPoint testInput(2003.2f, 1997.3f);
+    WebCore::IntPoint test(testInput);
+
+    EXPECT_EQ(2003, test.x());
+    EXPECT_EQ(1997, test.y());
+    ASSERT_FALSE(test.isZero());
+}
+
+TEST(IntPoint, Move)
+{
+    WebCore::IntPoint test(10, 20);
+    WebCore::IntSize size(30, 50);
+
+    test.move(size);
+
+    EXPECT_EQ(40, test.x());
+    EXPECT_EQ(70, test.y());
+
+    test.move(-2, 8);
+
+    EXPECT_EQ(38, test.x());
+    EXPECT_EQ(78, test.y());
+
+    WebCore::IntPoint offset(100, 100);
+
+    test.moveBy(offset);
+
+    EXPECT_EQ(138, test.x());
+    EXPECT_EQ(178, test.y());
+}
+
+TEST(IntPoint, Scale)
+{
+    WebCore::IntPoint test(10, 20);
+
+    test.scale(2.0);
+
+    EXPECT_EQ(20, test.x());
+    EXPECT_EQ(40, test.y());
+
+    test.scale(3.0, 1.5);
+
+    EXPECT_EQ(60, test.x());
+    EXPECT_EQ(60, test.y());
+}
+
+TEST(IntPoint, Expand)
+{
+    WebCore::IntPoint a(10, 20);
+    WebCore::IntPoint b(20, 40);
+
+    auto c = a.expandedTo(b);
+
+    EXPECT_EQ(20, c.x());
+    EXPECT_EQ(40, c.y());
+}
+
+TEST(IntPoint, Shrink)
+{
+    WebCore::IntPoint a(10, 20);
+    WebCore::IntPoint b(20, 40);
+
+    auto c = b.shrunkTo(a);
+
+    EXPECT_EQ(10, c.x());
+    EXPECT_EQ(20, c.y());
+}
+
+TEST(IntPoint, Transpose)
+{
+    WebCore::IntPoint a(10, 20);
+
+    auto b = a.transposedPoint();
+
+    EXPECT_EQ(20, b.x());
+    EXPECT_EQ(10, b.y());
+}
+
+TEST(IntPoint, Cast)
+{
+    WebCore::IntPoint a(10, 20);
+
+    WebCore::IntSize as = WebCore::toIntSize(a);
+    EXPECT_EQ(10, as.width());
+    EXPECT_EQ(20, as.height());
+
+#if USE(CG)
+    CGPoint cgPoint = a;
+
+    ASSERT_FLOAT_EQ(10.0f, cgPoint.x);
+    ASSERT_FLOAT_EQ(20.0f, cgPoint.y);
+
+    WebCore::IntPoint fromCGPoint(cgPoint);
+    EXPECT_EQ(10, fromCGPoint.x());
+    EXPECT_EQ(20, fromCGPoint.y());
+    ASSERT_TRUE(a == fromCGPoint);
+#endif
+
+#if PLATFORM(WIN)
+    POINT gdiPoint = a;
+
+    ASSERT_FLOAT_EQ(10.0f, gdiPoint.x);
+    ASSERT_FLOAT_EQ(20.0f, gdiPoint.y);
+
+    WebCore::IntPoint fromGDIPoint(gdiPoint);
+    EXPECT_EQ(10, fromGDIPoint.x());
+    EXPECT_EQ(20, fromGDIPoint.y());
+    ASSERT_TRUE(a == fromGDIPoint);
+
+    D2D1_POINT_2F d2dPointF = a;
+
+    ASSERT_FLOAT_EQ(10.0f, d2dPointF.x);
+    ASSERT_FLOAT_EQ(20.0f, d2dPointF.y);
+
+    WebCore::IntPoint fromD2DPointF(d2dPointF);
+    EXPECT_EQ(10, fromD2DPointF.x());
+    EXPECT_EQ(20, fromD2DPointF.y());
+    ASSERT_TRUE(a == fromD2DPointF);
+
+    D2D1_POINT_2U d2dPointU = a;
+
+    ASSERT_FLOAT_EQ(10.0f, d2dPointU.x);
+    ASSERT_FLOAT_EQ(20.0f, d2dPointU.y);
+
+    WebCore::IntPoint fromD2DPointU(d2dPointU);
+    EXPECT_EQ(10, fromD2DPointU.x());
+    EXPECT_EQ(20, fromD2DPointU.y());
+    ASSERT_TRUE(a == fromD2DPointU);
+#endif
+}
+
+TEST(IntPoint, Addition)
+{
+    WebCore::IntPoint a(10, 20);
+    WebCore::IntPoint b(50, 60);
+    WebCore::IntSize bs(50, 60);
+
+    auto c = a + b;
+
+    EXPECT_EQ(60, c.x());
+    EXPECT_EQ(80, c.y());
+
+    a += bs;
+
+    EXPECT_EQ(60, a.x());
+    EXPECT_EQ(80, a.y());
+}
+
+TEST(IntPoint, Subtraction)
+{
+    WebCore::IntPoint a(100, 80);
+    WebCore::IntPoint b(50, 60);
+    WebCore::IntSize bs(50, 60);
+
+    WebCore::IntSize c = a - b;
+
+    EXPECT_EQ(50, c.width());
+    EXPECT_EQ(20, c.height());
+
+    WebCore::IntPoint d = a - bs;
+
+    EXPECT_EQ(50, d.x());
+    EXPECT_EQ(20, d.y());
+
+    a -= bs;
+
+    EXPECT_EQ(50, a.x());
+    EXPECT_EQ(20, a.y());
+}
+
+TEST(IntPoint, Negation)
+{
+    WebCore::IntPoint a(100, 80);
+    auto b = -a;
+
+    EXPECT_EQ(-100, b.x());
+    EXPECT_EQ(-80, b.y());
+}
+
+TEST(IntPoint, Equality)
+{
+    WebCore::IntPoint a(100, 80);
+    WebCore::IntPoint b(70, 50);
+    WebCore::IntPoint c(100, 80);
+
+    ASSERT_TRUE(a == c);
+    ASSERT_FALSE(a == b);
+    ASSERT_FALSE(a != c);
+    ASSERT_TRUE(a != b);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp b/Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp
new file mode 100644 (file)
index 0000000..a290432
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatRect.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::IntRect rect)
+{
+    rect.setX(1);
+    EXPECT_EQ(1, rect.x());
+    rect.setY(2);
+    EXPECT_EQ(2, rect.y());
+    rect.setWidth(203);
+    EXPECT_EQ(203, rect.width());
+    rect.setHeight(73);
+    EXPECT_EQ(73, rect.height());
+}
+
+static void testEmptyRect(const WebCore::IntRect& rect)
+{
+    EXPECT_EQ(0, rect.x());
+    EXPECT_EQ(0, rect.y());
+    EXPECT_EQ(0, rect.width());
+    EXPECT_EQ(0, rect.height());
+    EXPECT_EQ(0, rect.maxX());
+    EXPECT_EQ(0, rect.maxY());
+    EXPECT_TRUE(rect.isEmpty());
+}
+
+TEST(IntRect, DefaultConstruction)
+{
+    WebCore::IntRect test;
+
+    testEmptyRect(test);
+
+    testGetAndSet(test);
+
+    auto location = test.location();
+    EXPECT_EQ(0, location.x());
+    EXPECT_EQ(0, location.y());
+
+    auto size = test.size();
+    EXPECT_EQ(0, size.width());
+    EXPECT_EQ(0, size.height());
+}
+
+TEST(IntRect, ValueConstruction)
+{
+    WebCore::IntRect test(10, 20, 100, 50);
+
+    EXPECT_EQ(10, test.x());
+    EXPECT_EQ(20, test.y());
+    EXPECT_EQ(100, test.width());
+    EXPECT_EQ(50, test.height());
+    EXPECT_EQ(110, test.maxX());
+    EXPECT_EQ(70, test.maxY());
+    EXPECT_FALSE(test.isEmpty());
+
+    auto location = test.location();
+    EXPECT_EQ(10, location.x());
+    EXPECT_EQ(20, location.y());
+
+    auto size = test.size();
+    EXPECT_EQ(100, size.width());
+    EXPECT_EQ(50, size.height());
+}
+
+TEST(IntRect, PointSizeConstruction)
+{
+    WebCore::IntPoint location(20, 30);
+    WebCore::IntSize size(100, 50);
+
+    WebCore::IntRect test(location, size);
+
+    EXPECT_EQ(20, test.x());
+    EXPECT_EQ(30, test.y());
+    EXPECT_EQ(100, test.width());
+    EXPECT_EQ(50, test.height());
+    EXPECT_EQ(120, test.maxX());
+    EXPECT_EQ(80, test.maxY());
+    EXPECT_FALSE(test.isEmpty());
+
+    auto location2 = test.location();
+    EXPECT_EQ(20, location2.x());
+    EXPECT_EQ(30, location2.y());
+
+    auto size2 = test.size();
+    EXPECT_EQ(100, size2.width());
+    EXPECT_EQ(50, size2.height());
+}
+
+TEST(IntRect, FloatRectConstruction)
+{
+    WebCore::FloatRect rect(20.0f, 30.0f, 150.0f, 300.0f);
+
+    WebCore::IntRect test(rect);
+
+    EXPECT_EQ(20, test.x());
+    EXPECT_EQ(30, test.y());
+    EXPECT_EQ(150, test.width());
+    EXPECT_EQ(300, test.height());
+    EXPECT_EQ(170, test.maxX());
+    EXPECT_EQ(330, test.maxY());
+    EXPECT_FALSE(test.isEmpty());
+
+    auto location = test.location();
+    EXPECT_EQ(20, location.x());
+    EXPECT_EQ(30, location.y());
+
+    auto size = test.size();
+    EXPECT_EQ(150, size.width());
+    EXPECT_EQ(300, size.height());
+}
+
+TEST(IntRect, SetLocationAndSize)
+{
+    WebCore::IntRect rect;
+
+    testEmptyRect(rect);
+
+    WebCore::IntPoint location(10, 20);
+
+    rect.setLocation(location);
+
+    EXPECT_EQ(10, rect.x());
+    EXPECT_EQ(20, rect.y());
+    EXPECT_EQ(0, rect.width());
+    EXPECT_EQ(0, rect.height());
+    EXPECT_EQ(10, rect.maxX());
+    EXPECT_EQ(20, rect.maxY());
+    EXPECT_TRUE(rect.isEmpty());
+
+    WebCore::IntSize size(100, 200);
+
+    rect.setSize(size);
+
+    EXPECT_EQ(10, rect.x());
+    EXPECT_EQ(20, rect.y());
+    EXPECT_EQ(100, rect.width());
+    EXPECT_EQ(200, rect.height());
+    EXPECT_EQ(110, rect.maxX());
+    EXPECT_EQ(220, rect.maxY());
+    EXPECT_FALSE(rect.isEmpty());
+}
+
+TEST(IntRect, Center)
+{
+    WebCore::IntRect rect(20, 40, 100, 200);
+
+    auto center = rect.center();
+
+    EXPECT_EQ(70, center.x());
+    EXPECT_EQ(140, center.y());
+}
+
+TEST(IntRect, Move)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    WebCore::IntSize delta(10, 20);
+
+    rect.move(delta);
+
+    EXPECT_EQ(30, rect.x());
+    EXPECT_EQ(50, rect.y());
+
+    WebCore::IntPoint deltaPoint(-20, -40);
+
+    rect.moveBy(deltaPoint);
+
+    EXPECT_EQ(10, rect.x());
+    EXPECT_EQ(10, rect.y());
+
+    rect.move(-10, 22);
+
+    EXPECT_EQ(0, rect.x());
+    EXPECT_EQ(32, rect.y());
+}
+
+TEST(IntRect, Expand)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    WebCore::IntSize size(100, 100);
+
+    rect.expand(size);
+
+    EXPECT_EQ(200, rect.width());
+    EXPECT_EQ(300, rect.height());
+
+    rect.expand(55, 22);
+
+    EXPECT_EQ(255, rect.width());
+    EXPECT_EQ(322, rect.height());
+
+    WebCore::IntSize size2(-10, -20);
+
+    rect.expand(size2);
+
+    EXPECT_EQ(245, rect.width());
+    EXPECT_EQ(302, rect.height());
+
+    rect.expand(-5, -2);
+
+    EXPECT_EQ(240, rect.width());
+    EXPECT_EQ(300, rect.height());
+}
+
+TEST(IntRect, Contract)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    WebCore::IntSize size(50, 100);
+
+    rect.contract(size);
+
+    EXPECT_EQ(50, rect.width());
+    EXPECT_EQ(100, rect.height());
+
+    rect.contract(25, 22);
+
+    EXPECT_EQ(25, rect.width());
+    EXPECT_EQ(78, rect.height());
+
+    WebCore::IntSize size2(-10, -20);
+
+    rect.contract(size2);
+
+    EXPECT_EQ(35, rect.width());
+    EXPECT_EQ(98, rect.height());
+
+    rect.contract(-5, -2);
+
+    EXPECT_EQ(40, rect.width());
+    EXPECT_EQ(100, rect.height());
+}
+
+TEST(IntRect, ShiftXEdge)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    rect.shiftXEdgeTo(77);
+
+    EXPECT_EQ(77, rect.x());
+    EXPECT_EQ(120, rect.maxX());
+    EXPECT_EQ(30, rect.y());
+    EXPECT_EQ(230, rect.maxY());
+    EXPECT_EQ(43, rect.width());
+    EXPECT_EQ(200, rect.height());
+
+    rect.shiftMaxXEdgeTo(200);
+
+    EXPECT_EQ(77, rect.x());
+    EXPECT_EQ(200, rect.maxX());
+    EXPECT_EQ(30, rect.y());
+    EXPECT_EQ(230, rect.maxY());
+    EXPECT_EQ(123, rect.width());
+    EXPECT_EQ(200, rect.height());
+}
+
+TEST(IntRect, ShiftYEdge)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    rect.shiftYEdgeTo(59.0f);
+
+    EXPECT_EQ(20, rect.x());
+    EXPECT_EQ(120, rect.maxX());
+    EXPECT_EQ(59, rect.y());
+    EXPECT_EQ(230, rect.maxY());
+    EXPECT_EQ(100, rect.width());
+    EXPECT_EQ(171, rect.height());
+
+    rect.shiftMaxYEdgeTo(270.0f);
+
+    EXPECT_EQ(20, rect.x());
+    EXPECT_EQ(120, rect.maxX());
+    EXPECT_EQ(59, rect.y());
+    EXPECT_EQ(270, rect.maxY());
+    EXPECT_EQ(100, rect.width());
+    EXPECT_EQ(211, rect.height());
+}
+
+TEST(IntRect, Inflate)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    rect.inflateX(5);
+
+    EXPECT_EQ(15, rect.x());
+    EXPECT_EQ(125, rect.maxX());
+
+    rect.inflateY(4);
+
+    EXPECT_EQ(26, rect.y());
+    EXPECT_EQ(234, rect.maxY());
+
+    rect.inflate(10);
+
+    EXPECT_EQ(5, rect.x());
+    EXPECT_EQ(135, rect.maxX());
+    EXPECT_EQ(16, rect.y());
+    EXPECT_EQ(244, rect.maxY());
+}
+
+TEST(IntRect, Corners)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    WebCore::FloatPoint topLeft = rect.minXMinYCorner();
+    EXPECT_EQ(20, topLeft.x());
+    EXPECT_EQ(30, topLeft.y());
+
+    WebCore::FloatPoint topRight = rect.maxXMinYCorner();
+    EXPECT_EQ(120, topRight.x());
+    EXPECT_EQ(30, topRight.y());
+
+    WebCore::FloatPoint bottomLeft = rect.minXMaxYCorner();
+    EXPECT_EQ(20, bottomLeft.x());
+    EXPECT_EQ(230, bottomLeft.y());
+
+    WebCore::FloatPoint bottomRight = rect.maxXMaxYCorner();
+    EXPECT_EQ(120, bottomRight.x());
+    EXPECT_EQ(230, bottomRight.y());
+}
+
+TEST(IntRect, Contains)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    WebCore::IntRect contained(30, 40, 50, 100);
+
+    ASSERT_TRUE(rect.contains(contained));
+
+    WebCore::IntRect outside(120, 230, 50, 100);
+
+    ASSERT_FALSE(rect.contains(outside));
+
+    WebCore::IntRect intersects(10, 20, 90, 180);
+
+    ASSERT_FALSE(rect.contains(intersects));
+
+    WebCore::IntPoint pointInside(60, 70);
+
+    ASSERT_TRUE(rect.contains(pointInside));
+
+    WebCore::IntPoint pointOutside(160, 270);
+
+    ASSERT_FALSE(rect.contains(pointOutside));
+
+    WebCore::IntPoint pointOnLine(20, 30);
+
+    ASSERT_TRUE(rect.contains(pointOnLine));
+
+    ASSERT_TRUE(rect.contains(60, 70));
+    ASSERT_FALSE(rect.contains(160, 270));
+}
+
+TEST(IntRect, Intersects)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    WebCore::IntRect contained(30, 40, 50, 100);
+
+    ASSERT_TRUE(rect.intersects(contained));
+
+    WebCore::IntRect outside(120, 230, 50, 100);
+
+    ASSERT_FALSE(rect.intersects(outside));
+
+    WebCore::IntRect intersects(10, 20, 90, 180);
+
+    ASSERT_TRUE(rect.intersects(intersects));
+}
+
+static void testIntersectResult(const WebCore::IntRect& rect)
+{
+    EXPECT_EQ(70, rect.x());
+    EXPECT_EQ(120, rect.maxX());
+    EXPECT_EQ(80, rect.y());
+    EXPECT_EQ(230, rect.maxY());
+}
+
+TEST(IntRect, Intersect)
+{
+    WebCore::IntRect rectA(20, 30, 100, 200);
+    WebCore::IntRect rectB(70, 80, 100, 200);
+
+    rectA.intersect(rectB);
+
+    testIntersectResult(rectA);
+
+    WebCore::IntRect rectC(20, 30, 100, 200);
+
+    auto intersected = WebCore::intersection(rectC, rectB);
+
+    testIntersectResult(intersected);
+}
+
+static void testUnitedRects(const WebCore::IntRect& united)
+{
+    EXPECT_EQ(20, united.x());
+    EXPECT_EQ(170, united.maxX());
+    EXPECT_EQ(30, united.y());
+    EXPECT_EQ(280, united.maxY());
+}
+
+TEST(IntRect, Unite)
+{
+    WebCore::IntRect rectA(20, 30, 100, 200);
+    WebCore::IntRect rectB(70, 80, 100, 200);
+
+    rectA.unite(rectB);
+
+    testUnitedRects(rectA);
+
+    WebCore::IntRect rectC(20, 30, 100, 200);
+
+    auto united = WebCore::unionRect(rectC, rectB);
+
+    testUnitedRects(united);
+}
+
+TEST(IntRect, Scale)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    rect.scale(2.0f);
+
+    EXPECT_EQ(40, rect.x());
+    EXPECT_EQ(240, rect.maxX());
+    EXPECT_EQ(60, rect.y());
+    EXPECT_EQ(460, rect.maxY());
+}
+
+TEST(IntRect, Transpose)
+{
+    WebCore::IntRect rect(20, 30, 100, 200);
+
+    auto transposed = rect.transposedRect();
+
+    EXPECT_EQ(30, transposed.x());
+    EXPECT_EQ(230, transposed.maxX());
+    EXPECT_EQ(20, transposed.y());
+    EXPECT_EQ(120, transposed.maxY());
+}
+
+static void checkCastRect(const WebCore::IntRect& rect)
+{
+    EXPECT_EQ(10, rect.x());
+    EXPECT_EQ(40, rect.maxX());
+    EXPECT_EQ(20, rect.y());
+    EXPECT_EQ(60, rect.maxY());
+    EXPECT_EQ(30, rect.width());
+    EXPECT_EQ(40, rect.height());
+}
+
+TEST(IntRect, Casting)
+{
+    WebCore::IntRect rect(10, 20, 30, 40);
+
+#if USE(CG)
+    CGRect cgRect = CGRectMake(10.0, 20.0, 30.0, 40.0);
+
+    WebCore::IntRect rectFromCGRect(cgRect);
+
+    checkCastRect(rectFromCGRect);
+#endif
+
+#if PLATFORM(WIN)
+    RECT gdiRect = rect;
+
+    EXPECT_EQ(10, gdiRect.left);
+    EXPECT_EQ(20, gdiRect.top);
+    EXPECT_EQ(40, gdiRect.right);
+    EXPECT_EQ(60, gdiRect.bottom);
+
+    WebCore::IntRect rectFromGDIRect(gdiRect);
+
+    checkCastRect(rectFromGDIRect);
+
+    D2D1_RECT_U d2dRectU = rect;
+
+    EXPECT_EQ(10, d2dRectU.left);
+    EXPECT_EQ(20, d2dRectU.top);
+    EXPECT_EQ(40, d2dRectU.right);
+    EXPECT_EQ(60, d2dRectU.bottom);
+
+    WebCore::IntRect rectFromD2DRectU(d2dRectU);
+
+    checkCastRect(rectFromD2DRectU);
+
+    D2D1_RECT_F d2dRectF = rect;
+
+    EXPECT_FLOAT_EQ(10.0f, d2dRectF.left);
+    EXPECT_FLOAT_EQ(20.0f, d2dRectF.top);
+    EXPECT_FLOAT_EQ(40.0f, d2dRectF.right);
+    EXPECT_FLOAT_EQ(60.0f, d2dRectF.bottom);
+
+    WebCore::IntRect rectFromD2DRectF(d2dRectF);
+
+    checkCastRect(rectFromD2DRectF);
+#endif
+}
+
+static void checkSubtractionResult1(const WebCore::IntRect& rect)
+{
+    EXPECT_EQ(-10, rect.x());
+    EXPECT_EQ(90, rect.maxX());
+    EXPECT_EQ(-10, rect.y());
+    EXPECT_EQ(90, rect.maxY());
+    EXPECT_EQ(100, rect.width());
+    EXPECT_EQ(100, rect.height());
+}
+
+static void checkSubtractionResult2(const WebCore::IntRect& rect)
+{
+    EXPECT_EQ(-40, rect.x());
+    EXPECT_EQ(60, rect.maxX());
+    EXPECT_EQ(-50, rect.y());
+    EXPECT_EQ(50, rect.maxY());
+    EXPECT_EQ(100, rect.width());
+    EXPECT_EQ(100, rect.height());
+}
+
+TEST(IntRect, Subtraction)
+{
+    WebCore::IntRect rect(10, 20, 100, 100);
+    WebCore::IntPoint rightSide(20, 30);
+
+    rect -= rightSide;
+
+    checkSubtractionResult1(rect);
+
+    auto rect2 = rect - WebCore::IntPoint(30, 40);
+    checkSubtractionResult2(rect2);
+}
+
+TEST(IntRect, Equality)
+{
+    WebCore::IntRect rect(10, 20, 100, 100);
+    WebCore::IntRect rect2(10, 20, 100, 100);
+    WebCore::IntRect rightSide(110, 20, 20, 100);
+
+    ASSERT_TRUE(rect == rect2);
+    ASSERT_FALSE(rect != rect2);
+    ASSERT_TRUE(rect != rightSide);
+    ASSERT_FALSE(rect == rightSide);
+}
+
+static void checkEnclosingIntRect(const WebCore::IntRect& rect)
+{
+    EXPECT_EQ(10, rect.x());
+    EXPECT_EQ(41, rect.maxX());
+    EXPECT_EQ(21, rect.y());
+    EXPECT_EQ(62, rect.maxY());
+    EXPECT_EQ(31, rect.width());
+    EXPECT_EQ(41, rect.height());
+}
+
+TEST(IntRect, EnclosingIntRect)
+{
+#if USE(CG)
+    CGRect cgRect = CGRectMake(10.5, 21.3, 30.1, 40.0);
+
+    WebCore::IntRect enclosingCG = WebCore::enclosingIntRect(cgRect);
+
+    checkEnclosingIntRect(enclosingCG);
+#endif
+}
+
+TEST(IntRect, AreaAndDistances)
+{
+    WebCore::IntRect rect(10, 20, 100, 100);
+
+    EXPECT_EQ(10000U, rect.area());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp b/Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp
new file mode 100644 (file)
index 0000000..f08e885
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::IntSize rect)
+{
+    rect.setWidth(203);
+    EXPECT_EQ(203, rect.width());
+    rect.setHeight(73);
+    EXPECT_EQ(73, rect.height());
+}
+
+static void testEmptySize(const WebCore::IntSize& rect)
+{
+    EXPECT_EQ(0, rect.width());
+    EXPECT_EQ(0, rect.height());
+    EXPECT_TRUE(rect.isEmpty());
+    EXPECT_TRUE(rect.isZero());
+}
+
+TEST(IntSize, DefaultConstruction)
+{
+    WebCore::IntSize test;
+
+    testEmptySize(test);
+
+    testGetAndSet(test);
+}
+
+TEST(IntSize, ValueConstruction)
+{
+    WebCore::IntSize test(100, 200);
+
+    EXPECT_EQ(100, test.width());
+    EXPECT_EQ(200, test.height());
+    EXPECT_FALSE(test.isEmpty());
+    EXPECT_FALSE(test.isZero());
+
+    static const float epsilon = 0.0001f;
+    EXPECT_NEAR(0.5f, test.aspectRatio(), epsilon);
+}
+
+TEST(IntSize, FloatSizeConstruction)
+{
+    WebCore::FloatSize size(1024.2, 767.8);
+    WebCore::IntSize test(size);
+
+    EXPECT_EQ(1024, test.width());
+    EXPECT_EQ(767, test.height());
+
+    ASSERT_FALSE(test.isEmpty());
+    ASSERT_FALSE(test.isZero());
+
+    static const double epsilon = 0.001;
+    EXPECT_NEAR(1.335f, test.aspectRatio(), epsilon);
+
+    testGetAndSet(test);
+}
+
+TEST(IntSize, DiagonalLengthAndArea)
+{
+    WebCore::IntSize test(1024, 768);
+
+    EXPECT_EQ(1638400, test.diagonalLengthSquared());
+    EXPECT_EQ(786432U, test.area());
+}
+
+TEST(IntSize, Scale)
+{
+    WebCore::IntSize test(1024, 768);
+
+    test.scale(2.0f);
+
+    EXPECT_EQ(2048, test.width());
+    EXPECT_EQ(1536, test.height());
+
+    test.scale(0.5f);
+
+    EXPECT_EQ(1024, test.width());
+    EXPECT_EQ(768, test.height());
+
+    test.scale(2.0f, 0.5f);
+
+    EXPECT_EQ(2048, test.width());
+    EXPECT_EQ(384, test.height());
+}
+
+TEST(IntSize, Expand)
+{
+    WebCore::IntSize test(1024, 768);
+
+    EXPECT_EQ(1024, test.width());
+    EXPECT_EQ(768, test.height());
+
+    test.expand(100, 50);
+
+    EXPECT_EQ(1124, test.width());
+    EXPECT_EQ(818, test.height());
+
+    WebCore::IntSize other(2048, 700);
+
+    auto expanded = test.expandedTo(other);
+
+    EXPECT_EQ(2048, expanded.width());
+    EXPECT_EQ(818, expanded.height());
+}
+
+TEST(IntSize, Shrink)
+{
+    WebCore::IntSize test(1024, 768);
+    WebCore::IntSize other(1000, 700);
+
+    auto shrunken = test.shrunkTo(other);
+
+    EXPECT_EQ(1000, shrunken.width());
+    EXPECT_EQ(700, shrunken.height());
+
+    WebCore::IntSize other2(2000.0f, 700.0f);
+
+    auto shrunken2 = test.shrunkTo(other2);
+
+    EXPECT_EQ(1024, shrunken2.width());
+    EXPECT_EQ(700, shrunken2.height());
+}
+
+TEST(IntSize, TransposedSize)
+{
+    WebCore::IntSize test(1024, 768);
+
+    auto transposedSize = test.transposedSize();
+
+    EXPECT_EQ(768, transposedSize.width());
+    EXPECT_EQ(1024, transposedSize.height());
+}
+
+TEST(IntSize, Casting)
+{
+    WebCore::IntSize test(1024, 768);
+
+#if USE(CG)
+    CGSize cgSize = test;
+
+    EXPECT_FLOAT_EQ(1024.0f, cgSize.width);
+    EXPECT_FLOAT_EQ(768.0f, cgSize.height);
+
+    CGSize cgSize2 = CGSizeMake(-22.3f, 14.6f);
+
+    WebCore::IntSize testCG(cgSize2);
+
+    EXPECT_EQ(-22, testCG.width());
+    EXPECT_EQ(14, testCG.height());
+#endif
+
+#if PLATFORM(WIN)
+    D2D1_SIZE_U d2dSizeU = test;
+    EXPECT_EQ(1024, d2dSizeU.width);
+    EXPECT_EQ(768, d2dSizeU.height);
+
+    D2D1_SIZE_F d2dSizeF = test;
+    EXPECT_FLOAT_EQ(1024.0f, d2dSizeF.width);
+    EXPECT_FLOAT_EQ(768.0f, d2dSizeF.height);
+
+    D2D1_SIZE_F d2dSizeF2 = D2D1::SizeF(-22.3f, 14.6f);
+
+    WebCore::IntSize testD2D(d2dSizeF2);
+
+    EXPECT_EQ(-22, testD2D.width());
+    EXPECT_EQ(14, testD2D.height());
+
+    D2D1_SIZE_F d2dSizeU2 = D2D1::SizeF(-23, 16);
+
+    WebCore::IntSize testD2D2(d2dSizeU2);
+
+    EXPECT_EQ(-23, testD2D2.width());
+    EXPECT_EQ(16, testD2D2.height());
+#endif
+}
+
+TEST(IntSize, AddSubtract)
+{
+    WebCore::IntSize a(512, 384);
+    WebCore::IntSize b(100, 100);
+
+    WebCore::IntSize c = a + b;
+
+    EXPECT_EQ(612, c.width());
+    EXPECT_EQ(484, c.height());
+
+    a += b;
+
+    EXPECT_EQ(612, a.width());
+    EXPECT_EQ(484, a.height());
+
+    WebCore::IntSize a2(512, 384);
+
+    WebCore::IntSize d = a2 - b;
+
+    EXPECT_EQ(412, d.width());
+    EXPECT_EQ(284, d.height());
+
+    a2 -= b;
+
+    EXPECT_EQ(412, a2.width());
+    EXPECT_EQ(284, a2.height());
+}
+
+TEST(IntSize, Negation)
+{
+    WebCore::IntSize a(512, 384);
+
+    WebCore::IntSize negated = -a;
+
+    EXPECT_EQ(-512, negated.width());
+    EXPECT_EQ(-384, negated.height());
+}
+
+TEST(IntSize, Equality)
+{
+    WebCore::IntSize a(1024, 768);
+    WebCore::IntSize b(1024, 768);
+    WebCore::IntSize c(768, 534);
+
+    ASSERT_TRUE(a == b);
+    ASSERT_FALSE(a != b);
+    ASSERT_FALSE(a == c);
+    ASSERT_TRUE(a != c);
+}
+
+TEST(IntSize, Contract)
+{
+    WebCore::IntSize a(1024, 768);
+
+    a.contract(100, 50);
+
+    EXPECT_EQ(924, a.width());
+    EXPECT_EQ(718, a.height());
+}
+
+TEST(IntSize, Clamp)
+{
+    WebCore::IntSize a(1024, 768);
+
+    a.clampNegativeToZero();
+
+    EXPECT_EQ(1024, a.width());
+    EXPECT_EQ(768, a.height());
+
+    WebCore::IntSize b(-1024, -768);
+
+    b.clampNegativeToZero();
+
+    EXPECT_EQ(0, b.width());
+    EXPECT_EQ(0, b.height());
+
+    WebCore::IntSize minimumSize(1024, 1000);
+
+    a.clampToMinimumSize(minimumSize);
+
+    EXPECT_EQ(1024, a.width());
+    EXPECT_EQ(1000, a.height());
+}
+
+TEST(IntSize, ConstrainedBetween)
+{
+    WebCore::IntSize minimumSize(384, 256);
+    WebCore::IntSize maximumSize(2048, 1536);
+
+    WebCore::IntSize a(1024, 768);
+
+    auto constrained1 = a.constrainedBetween(minimumSize, maximumSize);
+
+    EXPECT_EQ(1024, constrained1.width());
+    EXPECT_EQ(768, constrained1.height());
+
+    WebCore::IntSize b(200, 100);
+
+    auto constrained2 = b.constrainedBetween(minimumSize, maximumSize);
+
+    EXPECT_EQ(384, constrained2.width());
+    EXPECT_EQ(256, constrained2.height());
+
+    WebCore::IntSize c(5000, 2000);
+
+    auto constrained3 = c.constrainedBetween(minimumSize, maximumSize);
+
+    EXPECT_EQ(2048, constrained3.width());
+    EXPECT_EQ(1536, constrained3.height());
+}
+
+/*
+
+IntSize constrainedBetween(const IntSize& min, const IntSize& max) const;
+
+*/
+
+}
index 67c85e0..9315b75 100644 (file)
 /*
  * Copyright (c) 2013, Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "config.h"
+
+#include <WebCore/AffineTransform.h>
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatQuad.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntRect.h>
 #include <WebCore/TransformationMatrix.h>
 
-using namespace WebCore;
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if USE(CA)
+#include <QuartzCore/QuartzCore.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
 
 namespace TestWebKitAPI {
 
-TEST(TransformationMatrix, NonInvertableBlend)
+static void testIdentity(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(1.0, transform.m11());
+    EXPECT_DOUBLE_EQ(0.0, transform.m12());
+    EXPECT_DOUBLE_EQ(0.0, transform.m13());
+    EXPECT_DOUBLE_EQ(0.0, transform.m14());
+    EXPECT_DOUBLE_EQ(0.0, transform.m21());
+    EXPECT_DOUBLE_EQ(1.0, transform.m22());
+    EXPECT_DOUBLE_EQ(0.0, transform.m23());
+    EXPECT_DOUBLE_EQ(0.0, transform.m24());
+    EXPECT_DOUBLE_EQ(0.0, transform.m31());
+    EXPECT_DOUBLE_EQ(0.0, transform.m32());
+    EXPECT_DOUBLE_EQ(1.0, transform.m33());
+    EXPECT_DOUBLE_EQ(0.0, transform.m34());
+    EXPECT_DOUBLE_EQ(0.0, transform.m41());
+    EXPECT_DOUBLE_EQ(0.0, transform.m42());
+    EXPECT_DOUBLE_EQ(0.0, transform.m43());
+    EXPECT_DOUBLE_EQ(1.0, transform.m44());
+}
+
+static void testGetAndSet(WebCore::TransformationMatrix& transform)
+{
+    transform.setA(1.1);
+    EXPECT_DOUBLE_EQ(1.1, transform.a());
+    transform.setB(2.2);
+    EXPECT_DOUBLE_EQ(2.2, transform.b());
+    transform.setC(3.3);
+    EXPECT_DOUBLE_EQ(3.3, transform.c());
+    transform.setD(4.4);
+    EXPECT_DOUBLE_EQ(4.4, transform.d());
+    transform.setE(5.5);
+    EXPECT_DOUBLE_EQ(5.5, transform.e());
+    transform.setF(6.6);
+    EXPECT_DOUBLE_EQ(6.6, transform.f());
+
+    transform.setM11(1.1);
+    EXPECT_DOUBLE_EQ(1.1, transform.m11());
+    transform.setM12(2.2);
+    EXPECT_DOUBLE_EQ(2.2, transform.m12());
+    transform.setM13(3.3);
+    EXPECT_DOUBLE_EQ(3.3, transform.m13());
+    transform.setM14(4.4);
+    EXPECT_DOUBLE_EQ(4.4, transform.m14());
+    transform.setM21(5.5);
+    EXPECT_DOUBLE_EQ(5.5, transform.m21());
+    transform.setM22(6.6);
+    EXPECT_DOUBLE_EQ(6.6, transform.m22());
+    transform.setM23(7.7);
+    EXPECT_DOUBLE_EQ(7.7, transform.m23());
+    transform.setM24(8.8);
+    EXPECT_DOUBLE_EQ(8.8, transform.m24());
+    transform.setM31(9.9);
+    EXPECT_DOUBLE_EQ(9.9, transform.m31());
+    transform.setM32(10.10);
+    EXPECT_DOUBLE_EQ(10.10, transform.m32());
+    transform.setM33(11.11);
+    EXPECT_DOUBLE_EQ(11.11, transform.m33());
+    transform.setM34(12.12);
+    EXPECT_DOUBLE_EQ(12.12, transform.m34());
+    transform.setM41(13.13);
+    EXPECT_DOUBLE_EQ(13.13, transform.m41());
+    transform.setM42(14.14);
+    EXPECT_DOUBLE_EQ(14.14, transform.m42());
+    transform.setM43(15.15);
+    EXPECT_DOUBLE_EQ(15.15, transform.m43());
+    transform.setM44(16.16);
+    EXPECT_DOUBLE_EQ(16.16, transform.m44());
+}
+
+TEST(TransformationMatrix, DefaultConstruction)
+{
+    WebCore::TransformationMatrix test;
+
+    testIdentity(test);
+
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+}
+
+static void testAffineLikeConstruction(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(6.0, transform.a());
+    EXPECT_DOUBLE_EQ(5.0, transform.b());
+    EXPECT_DOUBLE_EQ(4.0, transform.c());
+    EXPECT_DOUBLE_EQ(3.0, transform.d());
+    EXPECT_DOUBLE_EQ(2.0, transform.e());
+    EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testValueConstruction(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(16.0, transform.m11());
+    EXPECT_DOUBLE_EQ(15.0, transform.m12());
+    EXPECT_DOUBLE_EQ(14.0, transform.m13());
+    EXPECT_DOUBLE_EQ(13.0, transform.m14());
+    EXPECT_DOUBLE_EQ(12.0, transform.m21());
+    EXPECT_DOUBLE_EQ(11.0, transform.m22());
+    EXPECT_DOUBLE_EQ(10.0, transform.m23());
+    EXPECT_DOUBLE_EQ(9.0, transform.m24());
+    EXPECT_DOUBLE_EQ(8.0, transform.m31());
+    EXPECT_DOUBLE_EQ(7.0, transform.m32());
+    EXPECT_DOUBLE_EQ(6.0, transform.m33());
+    EXPECT_DOUBLE_EQ(5.0, transform.m34());
+    EXPECT_DOUBLE_EQ(4.0, transform.m41());
+    EXPECT_DOUBLE_EQ(3.0, transform.m42());
+    EXPECT_DOUBLE_EQ(2.0, transform.m43());
+    EXPECT_DOUBLE_EQ(1.0, transform.m44());
+    ASSERT_FALSE(transform.isAffine());
+}
+
+TEST(TransformationMatrix, ValueConstruction)
+{
+    WebCore::TransformationMatrix test1(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testAffineLikeConstruction(test1);
+
+    ASSERT_FALSE(test1.isIdentity());
+    ASSERT_TRUE(test1.isAffine());
+
+    WebCore::TransformationMatrix test2(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test2);
+
+    testGetAndSet(test2);
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isAffine());
+
+    test2.makeIdentity();
+
+    testIdentity(test2);
+
+    ASSERT_TRUE(test2.isIdentity());
+}
+
+#if USE(CG)
+TEST(TransformationMatrix, CGAffineTransformConstruction)
+{
+    CGAffineTransform cgTransform = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix test(cgTransform);
+
+    testAffineLikeConstruction(test);
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+#if PLATFORM(WIN)
+TEST(TransformationMatrix, D2D1MatrixConstruction)
+{
+    D2D1_MATRIX_3X2_F d2dTransform = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix test(d2dTransform);
+
+    testAffineLikeConstruction(test);
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+TEST(TransformationMatrix, AffineTransformConstruction)
+{
+    WebCore::AffineTransform affineTransform(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix test(affineTransform);
+
+    testAffineLikeConstruction(test);
+    testGetAndSet(test);
+
+    ASSERT_FALSE(test.isIdentity());
+}
+
+TEST(TransformationMatrix, TransformMatrixConstruction)
 {
-    TransformationMatrix from;
-    TransformationMatrix to(2.7133590938, 0.0, 0.0, 0.0, 0.0, 2.4645137761, 0.0, 0.0, 0.0, 0.0, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05);
-    TransformationMatrix result;
+    WebCore::TransformationMatrix matrix(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix test(matrix);
+
+    testValueConstruction(test);
+}
+
+TEST(TransformationMatrix, Assignment)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix matrix(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testAffineLikeConstruction(test);
+
+    test = matrix;
+
+    testValueConstruction(test);
+}
+
+TEST(TransformationMatrix, Identity)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    ASSERT_FALSE(test.isIdentity());
+    ASSERT_FALSE(test.isIdentityOrTranslation());
+
+    test.makeIdentity();
+
+    ASSERT_TRUE(test.isIdentity());
+    ASSERT_TRUE(test.isIdentityOrTranslation());
+
+    testIdentity(test);
+}
+
+static void testAffineVersion(WebCore::TransformationMatrix affineTransformMatrix)
+{
+    ASSERT_FALSE(affineTransformMatrix.isIdentity());
+    ASSERT_FALSE(affineTransformMatrix.isIdentityOrTranslation());
+    ASSERT_TRUE(affineTransformMatrix.isAffine());
+
+    EXPECT_DOUBLE_EQ(16.0, affineTransformMatrix.m11());
+    EXPECT_DOUBLE_EQ(15.0, affineTransformMatrix.m12());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m13());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m14());
+    EXPECT_DOUBLE_EQ(12.0, affineTransformMatrix.m21());
+    EXPECT_DOUBLE_EQ(11.0, affineTransformMatrix.m22());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m23());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m24());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m31());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m32());
+    EXPECT_DOUBLE_EQ(1.0, affineTransformMatrix.m33());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m34());
+    EXPECT_DOUBLE_EQ(4.0, affineTransformMatrix.m41());
+    EXPECT_DOUBLE_EQ(3.0, affineTransformMatrix.m42());
+    EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m43());
+    EXPECT_DOUBLE_EQ(1.0, affineTransformMatrix.m44());
+}
+
+TEST(TransformationMatrix, AffineVersion)
+{
+    WebCore::TransformationMatrix test(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    ASSERT_FALSE(test.isIdentity());
+    ASSERT_FALSE(test.isIdentityOrTranslation());
+    ASSERT_FALSE(test.isAffine());
+
+    auto affineCopy = test.toAffineTransform();
+
+    testAffineVersion(affineCopy);
+
+    test.makeAffine();
+
+    testAffineVersion(test);
+}
+
+TEST(TransformationMatrix, MapFloatPoint)
+{
+    WebCore::TransformationMatrix test;
+    WebCore::FloatPoint point(100.0f, 50.0f);
+
+    auto mappedPoint = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint.x());
+    ASSERT_FLOAT_EQ(50.0f, mappedPoint.y());
+
+    test.setD(2.0);
+
+    auto mappedPoint2 = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint2.x());
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint2.y());
+
+    test.setA(0.5);
+
+    auto mappedPoint3 = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(50.0f, mappedPoint3.x());
+    ASSERT_FLOAT_EQ(100.0f, mappedPoint3.y());
+
+    test.setM22(0.5);
+
+    auto mappedPoint4 = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(50.0f, mappedPoint4.x());
+    ASSERT_FLOAT_EQ(25.0f, mappedPoint4.y());
+
+    test.setM11(2.0);
+
+    auto mappedPoint5 = test.mapPoint(point);
+
+    ASSERT_FLOAT_EQ(200.0f, mappedPoint5.x());
+    ASSERT_FLOAT_EQ(25.0f, mappedPoint5.y());
+}
+
+TEST(TransformationMatrix, MapIntPoint)
+{
+    WebCore::TransformationMatrix test;
+    WebCore::IntPoint point(100, 50);
+
+    auto mappedPoint = test.mapPoint(point);
+
+    ASSERT_EQ(100, mappedPoint.x());
+    ASSERT_EQ(50, mappedPoint.y());
+
+    test.setD(2.0);
+
+    auto mappedPoint2 = test.mapPoint(point);
+
+    ASSERT_EQ(100, mappedPoint2.x());
+    ASSERT_EQ(100, mappedPoint2.y());
+
+    test.setA(0.5);
+
+    auto mappedPoint3 = test.mapPoint(point);
+
+    ASSERT_EQ(50, mappedPoint3.x());
+    ASSERT_EQ(100, mappedPoint3.y());
+
+    test.setM22(0.5);
+
+    auto mappedPoint4 = test.mapPoint(point);
+
+    ASSERT_EQ(50, mappedPoint4.x());
+    ASSERT_EQ(25, mappedPoint4.y());
+
+    test.setM11(2.0);
+
+    auto mappedPoint5 = test.mapPoint(point);
+
+    ASSERT_EQ(200, mappedPoint5.x());
+    ASSERT_EQ(25, mappedPoint5.y());
+}
+
+TEST(TransformationMatrix, MapIntRect)
+{
+    WebCore::TransformationMatrix test;
+    WebCore::IntRect rect(10, 20, 200, 300);
+
+    auto mappedRect = test.mapRect(rect);
+
+    ASSERT_EQ(10, mappedRect.x());
+    ASSERT_EQ(20, mappedRect.y());
+    ASSERT_EQ(200, mappedRect.width());
+    ASSERT_EQ(300, mappedRect.height());
+
+    test.setD(2.0);
+
+    auto mappedRect2 = test.mapRect(rect);
+
+    ASSERT_EQ(10, mappedRect2.x());
+    ASSERT_EQ(40, mappedRect2.y());
+    ASSERT_EQ(200, mappedRect2.width());
+    ASSERT_EQ(600, mappedRect2.height());
+
+    test.setA(0.5);
+
+    auto mappedRect3 = test.mapRect(rect);
+
+    ASSERT_EQ(5, mappedRect3.x());
+    ASSERT_EQ(40, mappedRect3.y());
+    ASSERT_EQ(100, mappedRect3.width());
+    ASSERT_EQ(600, mappedRect3.height());
+
+    test.setM22(0.5);
+
+    auto mappedRect4 = test.mapRect(rect);
+
+    ASSERT_EQ(5, mappedRect4.x());
+    ASSERT_EQ(10, mappedRect4.y());
+    ASSERT_EQ(100, mappedRect4.width());
+    ASSERT_EQ(150, mappedRect4.height());
+
+    test.setM11(2.0);
+
+    auto mappedRect5 = test.mapRect(rect);
+
+    ASSERT_EQ(20, mappedRect5.x());
+    ASSERT_EQ(10, mappedRect5.y());
+    ASSERT_EQ(100, mappedRect4.width());
+    ASSERT_EQ(150, mappedRect4.height());
+}
+
+TEST(TransformationMatrix, MapFloatRect)
+{
+    WebCore::TransformationMatrix test;
+    WebCore::FloatRect rect(10.f, 20.0f, 200.0f, 300.0f);
+
+    auto mappedRect = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(10.0f, mappedRect.x());
+    ASSERT_FLOAT_EQ(20.0f, mappedRect.y());
+    ASSERT_FLOAT_EQ(200.0f, mappedRect.width());
+    ASSERT_FLOAT_EQ(300.0f, mappedRect.height());
+
+    test.setD(2.0);
+
+    auto mappedRect2 = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(10.0f, mappedRect2.x());
+    ASSERT_FLOAT_EQ(40.0f, mappedRect2.y());
+    ASSERT_FLOAT_EQ(200.0f, mappedRect2.width());
+    ASSERT_FLOAT_EQ(600.0f, mappedRect2.height());
+
+    test.setA(0.5);
+
+    auto mappedRect3 = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(5.0f, mappedRect3.x());
+    ASSERT_FLOAT_EQ(40.0f, mappedRect3.y());
+    ASSERT_FLOAT_EQ(100.0f, mappedRect3.width());
+    ASSERT_FLOAT_EQ(600.0f, mappedRect3.height());
+
+    test.setM22(0.5);
+
+    auto mappedRect4 = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(5.0f, mappedRect4.x());
+    ASSERT_FLOAT_EQ(10.0f, mappedRect4.y());
+    ASSERT_FLOAT_EQ(100.0f, mappedRect4.width());
+    ASSERT_FLOAT_EQ(150.0f, mappedRect4.height());
+
+    test.setM11(2.0);
+
+    auto mappedRect5 = test.mapRect(rect);
+
+    ASSERT_FLOAT_EQ(20.0f, mappedRect5.x());
+    ASSERT_FLOAT_EQ(10.0f, mappedRect5.y());
+    ASSERT_FLOAT_EQ(100.0f, mappedRect4.width());
+    ASSERT_FLOAT_EQ(150.0f, mappedRect4.height());
+}
+
+TEST(TransformationMatrix, MapFloatQuad)
+{
+    WebCore::FloatRect rect(100.0f, 100.0f, 100.0f, 50.0f);
+    WebCore::FloatQuad quad(rect);
+
+    ASSERT_FLOAT_EQ(100.0f, quad.p1().x());
+    ASSERT_FLOAT_EQ(100.0f, quad.p1().y());
+    ASSERT_FLOAT_EQ(200.0f, quad.p2().x());
+    ASSERT_FLOAT_EQ(100.0f, quad.p2().y());
+    ASSERT_FLOAT_EQ(200.0f, quad.p3().x());
+    ASSERT_FLOAT_EQ(150.0f, quad.p3().y());
+    ASSERT_FLOAT_EQ(100.0f, quad.p4().x());
+    ASSERT_FLOAT_EQ(150.0f, quad.p4().y());
+
+    WebCore::TransformationMatrix test;
+    auto mappedQuad = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().x());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad.p2().x());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p2().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad.p3().x());
+    ASSERT_FLOAT_EQ(150.0f, mappedQuad.p3().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad.p4().x());
+    ASSERT_FLOAT_EQ(150.0f, mappedQuad.p4().y());
+
+    test.setD(2.0);
+
+    auto mappedQuad2 = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p1().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p1().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p3().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p3().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p4().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p4().y());
+
+    test.setA(0.5);
+
+    auto mappedQuad3 = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p1().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p1().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p2().x());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p2().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p3().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p3().y());
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p4().x());
+    ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p4().y());
+
+    test.setM22(0.5);
+
+    auto mappedQuad4 = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p1().x());
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p1().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad4.p2().x());
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p2().y());
+    ASSERT_FLOAT_EQ(100.0f, mappedQuad4.p3().x());
+    ASSERT_FLOAT_EQ(75.0f, mappedQuad4.p3().y());
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p4().x());
+    ASSERT_FLOAT_EQ(75.0f, mappedQuad4.p4().y());
+
+    test.setM11(2.0);
+
+    auto mappedQuad5 = test.mapQuad(quad);
+
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad5.p1().x());
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad5.p1().y());
+    ASSERT_FLOAT_EQ(400.0f, mappedQuad5.p2().x());
+    ASSERT_FLOAT_EQ(50.0f, mappedQuad5.p2().y());
+    ASSERT_FLOAT_EQ(400.0f, mappedQuad5.p3().x());
+    ASSERT_FLOAT_EQ(75.0f, mappedQuad5.p3().y());
+    ASSERT_FLOAT_EQ(200.0f, mappedQuad5.p4().x());
+    ASSERT_FLOAT_EQ(75.0f, mappedQuad5.p4().y());
+}
+
+static void testDoubled(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(12.0, transform.a());
+    EXPECT_DOUBLE_EQ(10.0, transform.b());
+    EXPECT_DOUBLE_EQ(8.0, transform.c());
+    EXPECT_DOUBLE_EQ(6.0, transform.d());
+    EXPECT_DOUBLE_EQ(2.0, transform.e());
+    EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testHalved(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(3.0, transform.a());
+    EXPECT_DOUBLE_EQ(2.5, transform.b());
+    EXPECT_DOUBLE_EQ(2.0, transform.c());
+    EXPECT_DOUBLE_EQ(1.5, transform.d());
+    EXPECT_DOUBLE_EQ(2.0, transform.e());
+    EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testDoubled2(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(32.0, transform.m11());
+    EXPECT_DOUBLE_EQ(30.0, transform.m12());
+    EXPECT_DOUBLE_EQ(28.0, transform.m13());
+    EXPECT_DOUBLE_EQ(26.0, transform.m14());
+    EXPECT_DOUBLE_EQ(24.0, transform.m21());
+    EXPECT_DOUBLE_EQ(22.0, transform.m22());
+    EXPECT_DOUBLE_EQ(20.0, transform.m23());
+    EXPECT_DOUBLE_EQ(18.0, transform.m24());
+    EXPECT_DOUBLE_EQ(16.0, transform.m31());
+    EXPECT_DOUBLE_EQ(14.0, transform.m32());
+    EXPECT_DOUBLE_EQ(12.0, transform.m33());
+    EXPECT_DOUBLE_EQ(10.0, transform.m34());
+    EXPECT_DOUBLE_EQ(8.0, transform.m41());
+    EXPECT_DOUBLE_EQ(6.0, transform.m42());
+    EXPECT_DOUBLE_EQ(4.0, transform.m43());
+    EXPECT_DOUBLE_EQ(2.0, transform.m44());
+}
+
+static void testHalved2(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(8.0, transform.m11());
+    EXPECT_DOUBLE_EQ(7.5, transform.m12());
+    EXPECT_DOUBLE_EQ(7.0, transform.m13());
+    EXPECT_DOUBLE_EQ(6.5, transform.m14());
+    EXPECT_DOUBLE_EQ(6.0, transform.m21());
+    EXPECT_DOUBLE_EQ(5.5, transform.m22());
+    EXPECT_DOUBLE_EQ(5.0, transform.m23());
+    EXPECT_DOUBLE_EQ(4.5, transform.m24());
+    EXPECT_DOUBLE_EQ(4.0, transform.m31());
+    EXPECT_DOUBLE_EQ(3.5, transform.m32());
+    EXPECT_DOUBLE_EQ(3.0, transform.m33());
+    EXPECT_DOUBLE_EQ(2.5, transform.m34());
+    EXPECT_DOUBLE_EQ(2.0, transform.m41());
+    EXPECT_DOUBLE_EQ(1.5, transform.m42());
+    EXPECT_DOUBLE_EQ(1.0, transform.m43());
+    EXPECT_DOUBLE_EQ(0.5, transform.m44());
+}
+
+TEST(TransformationMatrix, Multiply)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix identity;
+
+    testAffineLikeConstruction(test);
+
+    test.multiply(identity);
+
+    testAffineLikeConstruction(test);
+
+    WebCore::TransformationMatrix doubler(2.0, 0.0, 0.0, 2.0, 0.0, 0.0);
+
+    test.multiply(doubler);
+
+    testDoubled(test);
+
+    WebCore::TransformationMatrix halver(0.5, 0.0, 0.0, 0.5, 0.0, 0.0);
+
+    test.multiply(halver);
+
+    testAffineLikeConstruction(test);
+
+    test.multiply(halver);
+
+    testHalved(test);
+
+    WebCore::TransformationMatrix test2(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test2);
+
+    test2.multiply(identity);
+
+    testValueConstruction(test2);
+
+    WebCore::TransformationMatrix doubler2(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0,
+        0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0);
+
+    test2.multiply(doubler2);
+
+    testDoubled2(test2);
+
+    WebCore::TransformationMatrix halver2(0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0,
+        0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5);
+
+    test2.multiply(halver2);
+
+    testValueConstruction(test2);
+
+    test2.multiply(halver2);
+
+    testHalved2(test2);
+
+    WebCore::TransformationMatrix test3(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    test3 *= identity;
 
+    testAffineLikeConstruction(test3);
+
+    test3 *= doubler;
+
+    testDoubled(test3);
+
+    const WebCore::TransformationMatrix test4(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    auto result1 = test4 * identity;
+
+    testValueConstruction(result1);
+
+    auto result2 = test4 * doubler2;
+
+    testDoubled2(result2);
+}
+
+static void testScaledByTwo(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(32.0, transform.m11());
+    EXPECT_DOUBLE_EQ(30.0, transform.m12());
+    EXPECT_DOUBLE_EQ(28.0, transform.m13());
+    EXPECT_DOUBLE_EQ(26.0, transform.m14());
+    EXPECT_DOUBLE_EQ(24.0, transform.m21());
+    EXPECT_DOUBLE_EQ(22.0, transform.m22());
+    EXPECT_DOUBLE_EQ(20.0, transform.m23());
+    EXPECT_DOUBLE_EQ(18.0, transform.m24());
+    EXPECT_DOUBLE_EQ(8.0, transform.m31());
+    EXPECT_DOUBLE_EQ(7.0, transform.m32());
+    EXPECT_DOUBLE_EQ(6.0, transform.m33());
+    EXPECT_DOUBLE_EQ(5.0, transform.m34());
+    EXPECT_DOUBLE_EQ(4.0, transform.m41());
+    EXPECT_DOUBLE_EQ(3.0, transform.m42());
+    EXPECT_DOUBLE_EQ(2.0, transform.m43());
+    EXPECT_DOUBLE_EQ(1.0, transform.m44());
+}
+
+static void testScaledByHalf(const WebCore::TransformationMatrix& transform)
+{
+    EXPECT_DOUBLE_EQ(8.0, transform.m11());
+    EXPECT_DOUBLE_EQ(7.5, transform.m12());
+    EXPECT_DOUBLE_EQ(7.0, transform.m13());
+    EXPECT_DOUBLE_EQ(6.5, transform.m14());
+    EXPECT_DOUBLE_EQ(6.0, transform.m21());
+    EXPECT_DOUBLE_EQ(5.5, transform.m22());
+    EXPECT_DOUBLE_EQ(5.0, transform.m23());
+    EXPECT_DOUBLE_EQ(4.5, transform.m24());
+    EXPECT_DOUBLE_EQ(8.0, transform.m31());
+    EXPECT_DOUBLE_EQ(7.0, transform.m32());
+    EXPECT_DOUBLE_EQ(6.0, transform.m33());
+    EXPECT_DOUBLE_EQ(5.0, transform.m34());
+    EXPECT_DOUBLE_EQ(4.0, transform.m41());
+    EXPECT_DOUBLE_EQ(3.0, transform.m42());
+    EXPECT_DOUBLE_EQ(2.0, transform.m43());
+    EXPECT_DOUBLE_EQ(1.0, transform.m44());
+}
+
+
+TEST(TransformationMatrix, Scale)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testAffineLikeConstruction(test);
+
+    test.scale(1.0);
+
+    testAffineLikeConstruction(test);
+
+    test.scale(2.0);
+
+    testDoubled(test);
+
+    test.scale(0.5);
+
+    testAffineLikeConstruction(test);
+
+    test.scale(0.5);
+
+    testHalved(test);
+
+    WebCore::TransformationMatrix test2(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test2);
+
+    test2.scale(2.0);
+
+    testScaledByTwo(test2);
+
+    test2.scale(0.5);
+
+    testValueConstruction(test2);
+
+    test2.scale(0.5);
+
+    testScaledByHalf(test2);
+}
+
+TEST(TransformationMatrix, ScaleUniformNonUniform)
+{
+    WebCore::TransformationMatrix test(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(1.0, 1.0);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(2.0, 2.0);
+
+    testScaledByTwo(test);
+
+    test.scaleNonUniform(0.5, 0.5);
+
+    testValueConstruction(test);
+
+    test.scaleNonUniform(0.5, 0.5);
+
+    testScaledByHalf(test);
+}
+
+TEST(TransformationMatrix, Rotate)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    test.rotate(360.0);
+
+    testAffineLikeConstruction(test);
+
+    test.rotate(180.0);
+
+    static double epsilon = 0.0001;
+
+    EXPECT_NEAR(-6.0, test.a(), epsilon);
+    EXPECT_NEAR(-5.0, test.b(), epsilon);
+    EXPECT_NEAR(-4.0, test.c(), epsilon);
+    EXPECT_NEAR(-3.0, test.d(), epsilon);
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.rotate(-180.0);
+
+    testAffineLikeConstruction(test);
+
+    test.rotate(90.0);
+
+    EXPECT_NEAR(4.0, test.a(), epsilon);
+    EXPECT_NEAR(3.0, test.b(), epsilon);
+    EXPECT_NEAR(-6.0, test.c(), epsilon);
+    EXPECT_NEAR(-5.0, test.d(), epsilon);
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.rotate(-90.0);
+
+    testAffineLikeConstruction(test);
+}
+
+TEST(TransformationMatrix, TranslateXY)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    test.translate(0.0, 0.0);
+
+    testAffineLikeConstruction(test);
+
+    test.translate(5.0, 0.0);
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(32.0, test.e());
+    EXPECT_DOUBLE_EQ(26.0, test.f());
+
+    test.translate(0.0, -1.2);
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(27.2, test.e());
+    EXPECT_DOUBLE_EQ(22.4, test.f());
+}
+
+TEST(TransformationMatrix, FlipX)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testAffineLikeConstruction(test);
+
+    test.flipX();
+
+    EXPECT_DOUBLE_EQ(-6.0, test.a());
+    EXPECT_DOUBLE_EQ(-5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipX();
+
+    testAffineLikeConstruction(test);
+
+    WebCore::TransformationMatrix test2;
+
+    testIdentity(test2);
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+
+    test2.flipX();
+
+    EXPECT_DOUBLE_EQ(-1.0, test2.a());
+    EXPECT_DOUBLE_EQ(0.0, test2.b());
+    EXPECT_DOUBLE_EQ(0.0, test2.c());
+    EXPECT_DOUBLE_EQ(1.0, test2.d());
+    EXPECT_DOUBLE_EQ(0.0, test2.e());
+    EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+    test2.flipX();
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+}
+
+TEST(TransformationMatrix, FlipY)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testAffineLikeConstruction(test);
+
+    test.flipY();
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(-4.0, test.c());
+    EXPECT_DOUBLE_EQ(-3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipY();
+
+    testAffineLikeConstruction(test);
+
+    WebCore::TransformationMatrix test2;
+
+    testIdentity(test2);
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+
+    test2.flipY();
+
+    EXPECT_DOUBLE_EQ(1.0, test2.a());
+    EXPECT_DOUBLE_EQ(0.0, test2.b());
+    EXPECT_DOUBLE_EQ(0.0, test2.c());
+    EXPECT_DOUBLE_EQ(-1.0, test2.d());
+    EXPECT_DOUBLE_EQ(0.0, test2.e());
+    EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+    test2.flipY();
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+}
+
+TEST(TransformationMatrix, FlipXandFlipY)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testAffineLikeConstruction(test);
+
+    test.flipX();
+
+    EXPECT_DOUBLE_EQ(-6.0, test.a());
+    EXPECT_DOUBLE_EQ(-5.0, test.b());
+    EXPECT_DOUBLE_EQ(4.0, test.c());
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipY();
+
+    EXPECT_DOUBLE_EQ(-6.0, test.a());
+    EXPECT_DOUBLE_EQ(-5.0, test.b());
+    EXPECT_DOUBLE_EQ(-4.0, test.c());
+    EXPECT_DOUBLE_EQ(-3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipX();
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_DOUBLE_EQ(-4.0, test.c());
+    EXPECT_DOUBLE_EQ(-3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.flipY();
+
+    testAffineLikeConstruction(test);
+
+    WebCore::TransformationMatrix test2;
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+
+    test2.flipX();
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+    test2.flipY();
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+    test2.flipX();
+
+    ASSERT_FALSE(test2.isIdentity());
+    ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+    test2.flipY();
+
+    ASSERT_TRUE(test2.isIdentity());
+    ASSERT_TRUE(test2.isIdentityOrTranslation());
+}
+
+TEST(TransformationMatrix, Skew)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+    testAffineLikeConstruction(test);
+
+    test.skew(360.0, 360.0);
+
+    testAffineLikeConstruction(test);
+
+    test.skew(0.0, 0.0);
+
+    testAffineLikeConstruction(test);
+
+    test.skew(180.0, 180.0);
+
+    static double epsilon = 0.0001;
+
+    EXPECT_DOUBLE_EQ(6.0, test.a());
+    EXPECT_DOUBLE_EQ(5.0, test.b());
+    EXPECT_NEAR(4.0, test.c(), epsilon);
+    EXPECT_DOUBLE_EQ(3.0, test.d());
+    EXPECT_DOUBLE_EQ(2.0, test.e());
+    EXPECT_DOUBLE_EQ(1.0, test.f());
+
+    test.skew(-180.0, -180.0);
+
+    testAffineLikeConstruction(test);
+}
+
+TEST(TransformationMatrix, Inverse)
+{
+    WebCore::TransformationMatrix test;
+
+    auto inverse = test.inverse();
+
+    ASSERT(inverse);
+
+    EXPECT_DOUBLE_EQ(1.0, inverse->a());
+    EXPECT_DOUBLE_EQ(0.0, inverse->b());
+    EXPECT_DOUBLE_EQ(0.0, inverse->c());
+    EXPECT_DOUBLE_EQ(1.0, inverse->d());
+    EXPECT_DOUBLE_EQ(0.0, inverse->e());
+    EXPECT_DOUBLE_EQ(0.0, inverse->f());
+
+    auto test2 = test * inverse.value();
+
+    testIdentity(test2);
+}
+
+TEST(TransformationMatrix, NonInvertableBlend)
+{
+    WebCore::TransformationMatrix from;
+    WebCore::TransformationMatrix to(2.7133590938, 0.0, 0.0, 0.0, 0.0, 2.4645137761, 0.0, 0.0, 0.0, 0.0, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05);
+    WebCore::TransformationMatrix result;
+    
     result = to;
     result.blend(from, 0.25);
     EXPECT_TRUE(result == from);
-
+    
     result = to;
     result.blend(from, 0.75);
     EXPECT_TRUE(result == to);
 }
 
+TEST(TransformationMatrix, Blend)
+{
+    WebCore::TransformationMatrix transform;
+
+    WebCore::TransformationMatrix scaled;
+    scaled.scale(2.0);
+
+    transform.blend(scaled, 50);
+
+    static const double epsilon = 0.0001;
+    EXPECT_NEAR(-48.0, transform.m11(), epsilon);
+    EXPECT_NEAR(0.0, transform.m12(), epsilon);
+    EXPECT_NEAR(0.0, transform.m13(), epsilon);
+    EXPECT_NEAR(0.0, transform.m14(), epsilon);
+    EXPECT_NEAR(0.0, transform.m21(), epsilon);
+    EXPECT_NEAR(-48.0, transform.m22(), epsilon);
+    EXPECT_NEAR(0.0, transform.m23(), epsilon);
+    EXPECT_NEAR(0.0, transform.m24(), epsilon);
+    EXPECT_NEAR(0.0, transform.m31(), epsilon);
+    EXPECT_NEAR(0.0, transform.m32(), epsilon);
+    EXPECT_NEAR(1.0, transform.m33(), epsilon);
+    EXPECT_NEAR(0.0, transform.m34(), epsilon);
+    EXPECT_NEAR(0.0, transform.m41(), epsilon);
+    EXPECT_NEAR(0.0, transform.m42(), epsilon);
+    EXPECT_NEAR(0.0, transform.m43(), epsilon);
+    EXPECT_NEAR(1.0, transform.m44(), epsilon);
+}
+
+TEST(TransformationMatrix, Blend2)
+{
+    WebCore::TransformationMatrix transform;
+
+    WebCore::TransformationMatrix scaled;
+    scaled.scale(2.0);
+
+    transform.blend2(scaled, 20);
+
+    static const double epsilon = 0.0001;
+    EXPECT_NEAR(-18.0, transform.m11(), epsilon);
+    EXPECT_NEAR(0.0, transform.m12(), epsilon);
+    EXPECT_NEAR(0.0, transform.m13(), epsilon);
+    EXPECT_NEAR(0.0, transform.m14(), epsilon);
+    EXPECT_NEAR(0.0, transform.m21(), epsilon);
+    EXPECT_NEAR(-18.0, transform.m22(), epsilon);
+    EXPECT_NEAR(0.0, transform.m23(), epsilon);
+    EXPECT_NEAR(0.0, transform.m24(), epsilon);
+    EXPECT_NEAR(0.0, transform.m31(), epsilon);
+    EXPECT_NEAR(0.0, transform.m32(), epsilon);
+    EXPECT_NEAR(1.0, transform.m33(), epsilon);
+    EXPECT_NEAR(0.0, transform.m34(), epsilon);
+    EXPECT_NEAR(0.0, transform.m41(), epsilon);
+    EXPECT_NEAR(0.0, transform.m42(), epsilon);
+    EXPECT_NEAR(0.0, transform.m43(), epsilon);
+    EXPECT_NEAR(1.0, transform.m44(), epsilon);
+}
+
+TEST(TransformationMatrix, Blend4)
+{
+    WebCore::TransformationMatrix transform;
+
+    WebCore::TransformationMatrix scaled;
+    scaled.scale(2.0);
+
+    transform.blend4(scaled, 30);
+
+    static const double epsilon = 0.0001;
+    EXPECT_NEAR(-28.0, transform.m11(), epsilon);
+    EXPECT_NEAR(0.0, transform.m12(), epsilon);
+    EXPECT_NEAR(0.0, transform.m13(), epsilon);
+    EXPECT_NEAR(0.0, transform.m14(), epsilon);
+    EXPECT_NEAR(0.0, transform.m21(), epsilon);
+    EXPECT_NEAR(-28.0, transform.m22(), epsilon);
+    EXPECT_NEAR(0.0, transform.m23(), epsilon);
+    EXPECT_NEAR(0.0, transform.m24(), epsilon);
+    EXPECT_NEAR(0.0, transform.m31(), epsilon);
+    EXPECT_NEAR(0.0, transform.m32(), epsilon);
+    EXPECT_NEAR(1.0, transform.m33(), epsilon);
+    EXPECT_NEAR(0.0, transform.m34(), epsilon);
+    EXPECT_NEAR(0.0, transform.m41(), epsilon);
+    EXPECT_NEAR(0.0, transform.m42(), epsilon);
+    EXPECT_NEAR(0.0, transform.m43(), epsilon);
+    EXPECT_NEAR(1.0, transform.m44(), epsilon);
+}
+
+TEST(TransformationMatrix, Equality)
+{
+    WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix test2;
+
+    ASSERT_FALSE(test == test2);
+    ASSERT_TRUE(test != test2);
+
+    test.makeIdentity();
+
+    ASSERT_TRUE(test == test2);
+    ASSERT_FALSE(test != test2);
+
+    WebCore::TransformationMatrix test3(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix test4(test3);
+
+    ASSERT_TRUE(test3 == test4);
+    ASSERT_FALSE(test3 != test4);
+
+    test4.setM43(1002.22);
+
+    ASSERT_FALSE(test3 == test4);
+    ASSERT_TRUE(test3 != test4);
+}
+
+static void testTranslationMatrix(const WebCore::TransformationMatrix& matrix)
+{
+    EXPECT_DOUBLE_EQ(1.0, matrix.m11());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m12());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m13());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m14());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m21());
+    EXPECT_DOUBLE_EQ(1.0, matrix.m22());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m23());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m24());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m31());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m32());
+    EXPECT_DOUBLE_EQ(1.0, matrix.m33());
+    EXPECT_DOUBLE_EQ(0.0, matrix.m34());
+    EXPECT_DOUBLE_EQ(10.0, matrix.m41());
+    EXPECT_DOUBLE_EQ(15.0, matrix.m42());
+    EXPECT_DOUBLE_EQ(30.0, matrix.m43());
+    EXPECT_DOUBLE_EQ(1.0, matrix.m44());
+}
+
+TEST(TransformationMatrix, Casting)
+{
+    WebCore::TransformationMatrix test(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+        9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+#if USE(CA)
+    CATransform3D caTransform = CATransform3DMakeTranslation(10.0f, 15.0f, 30.0f);
+
+    WebCore::TransformationMatrix fromCATransform(caTransform);
+
+    testTranslationMatrix(fromCATransform);
+
+    CATransform3D caFromWK = test;
+
+    EXPECT_DOUBLE_EQ(16.0, caFromWK.m11);
+    EXPECT_DOUBLE_EQ(15.0, caFromWK.m12);
+    EXPECT_DOUBLE_EQ(14.0, caFromWK.m13);
+    EXPECT_DOUBLE_EQ(13.0, caFromWK.m14);
+    EXPECT_DOUBLE_EQ(12.0, caFromWK.m21);
+    EXPECT_DOUBLE_EQ(11.0, caFromWK.m22);
+    EXPECT_DOUBLE_EQ(10.0, caFromWK.m23);
+    EXPECT_DOUBLE_EQ(9.0, caFromWK.m24);
+    EXPECT_DOUBLE_EQ(8.0, caFromWK.m31);
+    EXPECT_DOUBLE_EQ(7.0, caFromWK.m32);
+    EXPECT_DOUBLE_EQ(6.0, caFromWK.m33);
+    EXPECT_DOUBLE_EQ(5.0, caFromWK.m34);
+    EXPECT_DOUBLE_EQ(4.0, caFromWK.m41);
+    EXPECT_DOUBLE_EQ(3.0, caFromWK.m42);
+    EXPECT_DOUBLE_EQ(2.0, caFromWK.m43);
+    EXPECT_DOUBLE_EQ(1.0, caFromWK.m44);
+#endif
+
+#if USE(CG)
+    CGAffineTransform cgTransform = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix fromCGTransform(cgTransform);
+
+    testAffineLikeConstruction(fromCGTransform);
+
+    CGAffineTransform cgFromWK = test;
+    EXPECT_DOUBLE_EQ(16.0, cgFromWK.a);
+    EXPECT_DOUBLE_EQ(15.0, cgFromWK.b);
+    EXPECT_DOUBLE_EQ(12.0, cgFromWK.c);
+    EXPECT_DOUBLE_EQ(11.0, cgFromWK.d);
+    EXPECT_DOUBLE_EQ(4.0, cgFromWK.tx);
+    EXPECT_DOUBLE_EQ(3.0, cgFromWK.ty);
+#endif
+
+#if PLATFORM(WIN) || (PLATFORM(GTK) && OS(WINDOWS))
+    XFORM gdiFromWK = test;
+    EXPECT_DOUBLE_EQ(16.0, gdiFromWK.eM11);
+    EXPECT_DOUBLE_EQ(15.0, gdiFromWK.eM12);
+    EXPECT_DOUBLE_EQ(12.0, gdiFromWK.eM21);
+    EXPECT_DOUBLE_EQ(11.0, gdiFromWK.eM22);
+    EXPECT_DOUBLE_EQ(4.0, gdiFromWK.eDx);
+    EXPECT_DOUBLE_EQ(3.0, gdiFromWK.eDy);
+#endif
+
+#if PLATFORM(WIN)
+    D2D1_MATRIX_3X2_F d2dTransform = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+    WebCore::TransformationMatrix fromD2DTransform(d2dTransform);
+
+    testAffineLikeConstruction(fromD2DTransform);
+
+    D2D1_MATRIX_3X2_F d2dFromWK = test;
+    EXPECT_DOUBLE_EQ(16.0, d2dFromWK._11);
+    EXPECT_DOUBLE_EQ(15.0, d2dFromWK._12);
+    EXPECT_DOUBLE_EQ(12.0, d2dFromWK._21);
+    EXPECT_DOUBLE_EQ(11.0, d2dFromWK._22);
+    EXPECT_DOUBLE_EQ(4.0, d2dFromWK._31);
+    EXPECT_DOUBLE_EQ(3.0, d2dFromWK._32);
+#endif
+}
+
+TEST(TransformationMatrix, MakeMapBetweenRects)
+{
+    WebCore::TransformationMatrix transform;
+
+    WebCore::FloatRect fromRect(10.0f, 10.0f, 100.0f, 100.0f);
+    WebCore::FloatRect toRect(70.0f, 70.0f, 200.0f, 50.0f);
+
+    auto mapBetween = WebCore::TransformationMatrix::rectToRect(fromRect, toRect);
+
+    EXPECT_DOUBLE_EQ(2.0, mapBetween.a());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.b());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.c());
+    EXPECT_DOUBLE_EQ(0.5, mapBetween.d());
+    EXPECT_DOUBLE_EQ(60.0, mapBetween.e());
+    EXPECT_DOUBLE_EQ(60.0, mapBetween.f());
+
+    EXPECT_DOUBLE_EQ(2.0, mapBetween.m11());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m12());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m13());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m14());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m21());
+    EXPECT_DOUBLE_EQ(0.5, mapBetween.m22());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m23());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m24());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m31());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m32());
+    EXPECT_DOUBLE_EQ(1.0, mapBetween.m33());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m34());
+    EXPECT_DOUBLE_EQ(60.0, mapBetween.m41());
+    EXPECT_DOUBLE_EQ(60.0, mapBetween.m42());
+    EXPECT_DOUBLE_EQ(0.0, mapBetween.m43());
+    EXPECT_DOUBLE_EQ(1.0, mapBetween.m44());
+}
+
 }