summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fxcrt/fx_coordinates.cpp6
-rw-r--r--core/fxcrt/fx_coordinates.h2
-rw-r--r--core/fxcrt/fx_coordinates_unittest.cpp64
3 files changed, 69 insertions, 3 deletions
diff --git a/core/fxcrt/fx_coordinates.cpp b/core/fxcrt/fx_coordinates.cpp
index ac13a32329..69fedb5522 100644
--- a/core/fxcrt/fx_coordinates.cpp
+++ b/core/fxcrt/fx_coordinates.cpp
@@ -271,10 +271,10 @@ void CFX_Matrix::Rotate(float fRadian, bool bPrepended) {
bPrepended);
}
-void CFX_Matrix::RotateAt(float fRadian, float dx, float dy, bool bPrepended) {
- Translate(dx, dy, bPrepended);
+void CFX_Matrix::RotateAt(float fRadian, float x, float y, bool bPrepended) {
+ Translate(-x, -y, bPrepended);
Rotate(fRadian, bPrepended);
- Translate(-dx, -dy, bPrepended);
+ Translate(x, y, bPrepended);
}
void CFX_Matrix::Shear(float fAlphaRadian, float fBetaRadian, bool bPrepended) {
diff --git a/core/fxcrt/fx_coordinates.h b/core/fxcrt/fx_coordinates.h
index 69d16d1c55..3d09652b13 100644
--- a/core/fxcrt/fx_coordinates.h
+++ b/core/fxcrt/fx_coordinates.h
@@ -637,6 +637,8 @@ class CFX_Matrix {
void Scale(float sx, float sy, bool bPrepended = false);
void Rotate(float fRadian, bool bPrepended = false);
+
+ // Rotates counterclockwise around the (x, y) point.
void RotateAt(float fRadian, float x, float y, bool bPrepended = false);
void Shear(float fAlphaRadian, float fBetaRadian, bool bPrepended = false);
diff --git a/core/fxcrt/fx_coordinates_unittest.cpp b/core/fxcrt/fx_coordinates_unittest.cpp
index 3368a40e18..6fec10ecac 100644
--- a/core/fxcrt/fx_coordinates_unittest.cpp
+++ b/core/fxcrt/fx_coordinates_unittest.cpp
@@ -289,3 +289,67 @@ TEST(CFX_Matrix, ReverseCR714187) {
EXPECT_FLOAT_EQ(expected.x, result.x);
EXPECT_FLOAT_EQ(expected.y, result.y);
}
+
+TEST(CFX_Matrix, RotateAt) {
+ CFX_Matrix m;
+ m.RotateAt(FX_PI, 10, 20);
+
+ // 180 degree rotation
+ CFX_PointF p(27, 19);
+ CFX_PointF new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(-7, new_p.x);
+ EXPECT_FLOAT_EQ(21, new_p.y);
+
+ p = CFX_PointF(10, 20);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(10, new_p.x);
+ EXPECT_FLOAT_EQ(20, new_p.y);
+
+ p = CFX_PointF(0, 0);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(20, new_p.x);
+ EXPECT_FLOAT_EQ(40, new_p.y);
+
+ // 90 degree rotation
+ m.SetIdentity();
+ m.RotateAt(FX_PI / 2, 10, 20);
+
+ p = CFX_PointF(6, 17);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(13, new_p.x);
+ EXPECT_FLOAT_EQ(16, new_p.y);
+
+ p = CFX_PointF(10, 20);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(10, new_p.x);
+ EXPECT_FLOAT_EQ(20, new_p.y);
+
+ p = CFX_PointF(0, 0);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(30, new_p.x);
+ EXPECT_FLOAT_EQ(10, new_p.y);
+
+ // 60 degree rotation
+ m.SetIdentity();
+ m.RotateAt(FX_PI / 3, 10, 20);
+
+ p = CFX_PointF(20, 20);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(15, new_p.x);
+ EXPECT_FLOAT_EQ(28.660254f, new_p.y);
+
+ p = CFX_PointF(10, 20);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(10, new_p.x);
+ EXPECT_FLOAT_EQ(20, new_p.y);
+
+ p = CFX_PointF(0, 0);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(22.320509f, new_p.x);
+ EXPECT_FLOAT_EQ(1.3397465f, new_p.y);
+
+ p = CFX_PointF(10, -80);
+ new_p = m.Transform(p);
+ EXPECT_FLOAT_EQ(96.602540f, new_p.x);
+ EXPECT_FLOAT_EQ(-30, new_p.y);
+}