From ebf965adeb93cf5612291ae69c3986526394b354 Mon Sep 17 00:00:00 2001 From: Henrique Nakashima Date: Fri, 19 Jan 2018 19:45:28 +0000 Subject: Fix CFX_Matrix.RotateAt() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The translations were in the opposite order they should be. First the specified (x, y) coord needs to be translated to the origin, then rotation should be applied, then the translation should be reversed. To translate (x, y) to the origin, the initial translation should be Tx = -x, Ty = -y. Bug: pdfium:987 Change-Id: I7f873c6a20858bf7fd03e5fdb49020b196b44a1d Reviewed-on: https://pdfium-review.googlesource.com/23210 Commit-Queue: Henrique Nakashima Reviewed-by: Nicolás Peña Moreno Reviewed-by: Shirleen Lou --- core/fxcrt/fx_coordinates.cpp | 6 ++-- core/fxcrt/fx_coordinates.h | 2 ++ core/fxcrt/fx_coordinates_unittest.cpp | 64 ++++++++++++++++++++++++++++++++++ 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); +} -- cgit v1.2.3