basegfx/source/matrix/b2dhommatrix.cxx | 211 +++++++++++------------ basegfx/source/point/b2dpoint.cxx | 15 - basegfx/source/point/b2ipoint.cxx | 15 - basegfx/test/B2DHomMatrixTest.cxx | 54 ----- chart2/source/tools/CommonConverters.cxx | 13 - drawinglayer/source/texture/texture.cxx | 14 - drawinglayer/source/tools/primitive2dxmldump.cxx | 6 filter/source/msfilter/eschesdo.cxx | 7 include/basegfx/matrix/b2dhommatrix.hxx | 60 +++--- oox/source/drawingml/shape.cxx | 6 oox/source/shape/WpsContext.cxx | 7 svx/source/unodraw/unoshape.cxx | 13 - sw/source/core/edit/edfcol.cxx | 13 - sw/source/core/unocore/unodraw.cxx | 13 - xmloff/source/draw/shapeexport.cxx | 7 xmloff/source/draw/ximpshap.cxx | 6 16 files changed, 181 insertions(+), 279 deletions(-)
New commits: commit fdd06037e0cf902d71270c4bf7a867efc7c9c1f4 Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Wed May 17 20:13:03 2023 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Thu May 18 21:18:06 2023 +0200 improved B2DHomMatrix since we know that this is a matrix only used for 2D transforms, we know that the last row of the matrix is always { 0, 0, 1 }. Therefore, we don't need to store that information, and we can simplify some of the computations. Also remove operations like operator+ which are not legal for such a matrix. Change-Id: I482de9a45ebbedf79e3b6033575aab590e61c2d5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151909 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/basegfx/source/matrix/b2dhommatrix.cxx b/basegfx/source/matrix/b2dhommatrix.cxx index 4222c7a351c2..e4a9dda9e3c5 100644 --- a/basegfx/source/matrix/b2dhommatrix.cxx +++ b/basegfx/source/matrix/b2dhommatrix.cxx @@ -26,50 +26,56 @@ namespace basegfx { - - B2DHomMatrix::B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2) - { - maImpl.set(0, 0, f_0x0); - maImpl.set(0, 1, f_0x1); - maImpl.set(0, 2, f_0x2); - maImpl.set(1, 0, f_1x0); - maImpl.set(1, 1, f_1x1); - maImpl.set(1, 2, f_1x2); - } - - void B2DHomMatrix::set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue) - { - maImpl.set(nRow, nColumn, fValue); - } + constexpr int RowSize = 3; void B2DHomMatrix::set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2) { - maImpl.set(0, 0, f_0x0); - maImpl.set(0, 1, f_0x1); - maImpl.set(0, 2, f_0x2); - maImpl.set(1, 0, f_1x0); - maImpl.set(1, 1, f_1x1); - maImpl.set(1, 2, f_1x2); - } - - bool B2DHomMatrix::isLastLineDefault() const - { - return maImpl.isLastLineDefault(); + mfValues[0][0] = f_0x0; + mfValues[0][1] = f_0x1; + mfValues[0][2] = f_0x2; + mfValues[1][0] = f_1x0; + mfValues[1][1] = f_1x1; + mfValues[1][2] = f_1x2; } bool B2DHomMatrix::isIdentity() const { - return maImpl.isIdentity(); + for(sal_uInt16 a(0); a < RowSize - 1; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + { + const double fDefault(internal::implGetDefaultValue(a, b)); + const double fValueAB(get(a, b)); + + if(!::basegfx::fTools::equal(fDefault, fValueAB)) + { + return false; + } + } + } + + return true; } void B2DHomMatrix::identity() { - maImpl = Impl2DHomMatrix(); + for(sal_uInt16 a(0); a < RowSize - 1; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + mfValues[a][b] = internal::implGetDefaultValue(a, b); + } } bool B2DHomMatrix::isInvertible() const { - return maImpl.isInvertible(); + double dst[6]; + /* Compute adjoint: */ + computeAdjoint(dst); + /* Compute determinant: */ + double det = computeDeterminant(dst); + if (fTools::equalZero(det)) + return false; + return true; } bool B2DHomMatrix::invert() @@ -77,85 +83,43 @@ namespace basegfx if(isIdentity()) return true; - - double dst[9]; + double dst[6]; /* Compute adjoint: */ - - dst[0] = + get(1, 1) * get(2, 2) - get(1, 2) * get(2, 1); - dst[1] = - get(0, 1) * get(2, 2) + get(0, 2) * get(2, 1); - dst[2] = + get(0, 1) * get(1, 2) - get(0, 2) * get(1, 1); - dst[3] = - get(1, 0) * get(2, 2) + get(1, 2) * get(2, 0); - dst[4] = + get(0, 0) * get(2, 2) - get(0, 2) * get(2, 0); - dst[5] = - get(0, 0) * get(1, 2) + get(0, 2) * get(1, 0); - dst[6] = + get(1, 0) * get(2, 1) - get(1, 1) * get(2, 0); - dst[7] = - get(0, 0) * get(2, 1) + get(0, 1) * get(2, 0); - dst[8] = + get(0, 0) * get(1, 1) - get(0, 1) * get(1, 0); + computeAdjoint(dst); /* Compute determinant: */ - - double det = get(0, 0) * dst[0] + get(0, 1) * dst[3] + get(0, 2) * dst[6]; + double det = computeDeterminant(dst); if (fTools::equalZero(det)) return false; /* Multiply adjoint with reciprocal of determinant: */ - det = 1.0 / det; - - maImpl.set(0, 0, dst[0] * det); - maImpl.set(0, 1, dst[1] * det); - maImpl.set(0, 2, dst[2] * det); - maImpl.set(1, 0, dst[3] * det); - maImpl.set(1, 1, dst[4] * det); - maImpl.set(1, 2, dst[5] * det); - maImpl.set(2, 0, dst[6] * det); - maImpl.set(2, 1, dst[7] * det); - maImpl.set(2, 2, dst[8] * det); - - // The above algorithm is very slightly less accurate then the old one, so - // we need to round the last row to make sure that functions like decompose - // still do the same thing with existing data, otherwise testTdf109143 - // in CppunitTest_vcl_pdfexport will fail. - if (fTools::equalZero(maImpl.get(2, 0))) - maImpl.set(2, 0, 0); - if (fTools::equalZero(maImpl.get(2, 1))) - maImpl.set(2, 1, 0); - if (fTools::equal(1.0, maImpl.get(2, 2))) - maImpl.set(2, 2, 1); + mfValues[0][0] = dst[0] * det; + mfValues[0][1] = dst[1] * det; + mfValues[0][2] = dst[2] * det; + mfValues[1][0] = dst[3] * det; + mfValues[1][1] = dst[4] * det; + mfValues[1][2] = dst[5] * det; return true; } - B2DHomMatrix& B2DHomMatrix::operator+=(const B2DHomMatrix& rMat) + /* Compute adjoint, optimised for the case where the last (not stored) row is { 0, 0, 1 } */ + void B2DHomMatrix::computeAdjoint(double (&dst)[6]) const { - maImpl.doAddMatrix(rMat.maImpl); - return *this; - } - - B2DHomMatrix& B2DHomMatrix::operator-=(const B2DHomMatrix& rMat) - { - maImpl.doSubMatrix(rMat.maImpl); - return *this; + dst[0] = + get(1, 1); + dst[1] = - get(0, 1); + dst[2] = + get(0, 1) * get(1, 2) - get(0, 2) * get(1, 1); + dst[3] = - get(1, 0); + dst[4] = + get(0, 0); + dst[5] = - get(0, 0) * get(1, 2) + get(0, 2) * get(1, 0); } - B2DHomMatrix& B2DHomMatrix::operator*=(double fValue) + /* Compute the determinant, given the adjoint matrix */ + double B2DHomMatrix::computeDeterminant(double (&dst)[6]) const { - const double fOne(1.0); - - if(!fTools::equal(fOne, fValue)) - maImpl.doMulMatrix(fValue); - - return *this; - } - - B2DHomMatrix& B2DHomMatrix::operator/=(double fValue) - { - const double fOne(1.0); - - if(!fTools::equal(fOne, fValue)) - maImpl.doMulMatrix(1.0 / fValue); - - return *this; + return mfValues[0][0] * dst[0] + mfValues[0][1] * dst[3]; } B2DHomMatrix& B2DHomMatrix::operator*=(const B2DHomMatrix& rMat) @@ -172,15 +136,50 @@ namespace basegfx else { // multiply - maImpl.doMulMatrix(rMat.maImpl); + doMulMatrix(rMat); } return *this; } + void B2DHomMatrix::doMulMatrix(const B2DHomMatrix& rMat) + { + // create a copy as source for the original values + const B2DHomMatrix aCopy(*this); + + for(sal_uInt16 a(0); a < 2; ++a) + { + for(sal_uInt16 b(0); b < 3; ++b) + { + double fValue = 0.0; + + for(sal_uInt16 c(0); c < 2; ++c) + fValue += aCopy.mfValues[c][b] * rMat.mfValues[a][c]; + + mfValues[a][b] = fValue; + } + mfValues[a][2] += rMat.mfValues[a][2]; + } + } + bool B2DHomMatrix::operator==(const B2DHomMatrix& rMat) const { - return &rMat == this || maImpl.isEqual(rMat.maImpl); + if (&rMat == this) + return true; + for(sal_uInt16 a(0); a < 2; a++) + { + for(sal_uInt16 b(0); b < 3; b++) + { + const double fValueA(mfValues[a][b]); + const double fValueB(rMat.mfValues[a][b]); + + if(!::basegfx::fTools::equal(fValueA, fValueB)) + { + return false; + } + } + } + return true; } bool B2DHomMatrix::operator!=(const B2DHomMatrix& rMat) const @@ -197,26 +196,26 @@ namespace basegfx double fCos(1.0); utils::createSinCosOrthogonal(fSin, fCos, fRadiant); - Impl2DHomMatrix aRotMat; + B2DHomMatrix aRotMat; aRotMat.set(0, 0, fCos); aRotMat.set(1, 1, fCos); aRotMat.set(1, 0, fSin); aRotMat.set(0, 1, -fSin); - maImpl.doMulMatrix(aRotMat); + doMulMatrix(aRotMat); } void B2DHomMatrix::translate(double fX, double fY) { if(!fTools::equalZero(fX) || !fTools::equalZero(fY)) { - Impl2DHomMatrix aTransMat; + B2DHomMatrix aTransMat; aTransMat.set(0, 2, fX); aTransMat.set(1, 2, fY); - maImpl.doMulMatrix(aTransMat); + doMulMatrix(aTransMat); } } @@ -231,12 +230,12 @@ namespace basegfx if(!fTools::equal(fOne, fX) || !fTools::equal(fOne, fY)) { - Impl2DHomMatrix aScaleMat; + B2DHomMatrix aScaleMat; aScaleMat.set(0, 0, fX); aScaleMat.set(1, 1, fY); - maImpl.doMulMatrix(aScaleMat); + doMulMatrix(aScaleMat); } } @@ -250,11 +249,11 @@ namespace basegfx // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) if(!fTools::equalZero(fSx)) { - Impl2DHomMatrix aShearXMat; + B2DHomMatrix aShearXMat; aShearXMat.set(0, 1, fSx); - maImpl.doMulMatrix(aShearXMat); + doMulMatrix(aShearXMat); } } @@ -263,11 +262,11 @@ namespace basegfx // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) if(!fTools::equalZero(fSy)) { - Impl2DHomMatrix aShearYMat; + B2DHomMatrix aShearYMat; aShearYMat.set(1, 0, fSy); - maImpl.doMulMatrix(aShearYMat); + doMulMatrix(aShearYMat); } } @@ -280,12 +279,6 @@ namespace basegfx */ bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const { - // when perspective is used, decompose is not made here - if(!maImpl.isLastLineDefault()) - { - return false; - } - // reset rotate and shear and copy translation values in every case rRotate = rShearX = 0.0; rTranslate.setX(get(0, 2)); diff --git a/basegfx/source/point/b2dpoint.cxx b/basegfx/source/point/b2dpoint.cxx index 02e6711ac44c..1d7f75158526 100644 --- a/basegfx/source/point/b2dpoint.cxx +++ b/basegfx/source/point/b2dpoint.cxx @@ -34,21 +34,6 @@ namespace basegfx rMat.get(1, 1) * mfY + rMat.get(1, 2)); - if(!rMat.isLastLineDefault()) - { - const double fOne(1.0); - const double fTempM( - rMat.get(2, 0) * mfX + - rMat.get(2, 1) * mfY + - rMat.get(2, 2)); - - if(!fTools::equalZero(fTempM) && !fTools::equal(fOne, fTempM)) - { - fTempX /= fTempM; - fTempY /= fTempM; - } - } - mfX = fTempX; mfY = fTempY; diff --git a/basegfx/source/point/b2ipoint.cxx b/basegfx/source/point/b2ipoint.cxx index 7b43ebc860e2..2790fe3a18a8 100644 --- a/basegfx/source/point/b2ipoint.cxx +++ b/basegfx/source/point/b2ipoint.cxx @@ -41,21 +41,6 @@ namespace basegfx rMat.get(1, 1) * mnY + rMat.get(1, 2)); - if(!rMat.isLastLineDefault()) - { - const double fOne(1.0); - const double fTempM( - rMat.get(2, 0) * mnX + - rMat.get(2, 1) * mnY + - rMat.get(2, 2)); - - if(!fTools::equalZero(fTempM) && !fTools::equal(fOne, fTempM)) - { - fTempX /= fTempM; - fTempY /= fTempM; - } - } - mnX = fround(fTempX); mnY = fround(fTempY); diff --git a/basegfx/test/B2DHomMatrixTest.cxx b/basegfx/test/B2DHomMatrixTest.cxx index bd6b1f8c8029..aace816d3e3a 100644 --- a/basegfx/test/B2DHomMatrixTest.cxx +++ b/basegfx/test/B2DHomMatrixTest.cxx @@ -79,9 +79,6 @@ public: maPerspective.set(1, 0, 4.0); maPerspective.set(1, 1, 5.0); maPerspective.set(1, 2, 6.0); - maPerspective.set(2, 0, 7.0); - maPerspective.set(2, 1, 8.0); - maPerspective.set(2, 2, 9.0); } void equal() @@ -129,9 +126,6 @@ public: aPerspective.set(1, 0, 4.0); aPerspective.set(1, 1, 5.0); aPerspective.set(1, 2, 6.0); - aPerspective.set(2, 0, 7.0); - aPerspective.set(2, 1, 8.0); - aPerspective.set(2, 2, 9.0); CPPUNIT_ASSERT_MESSAGE("operator==: identity matrix", aIdentity.operator==(maIdentity)); CPPUNIT_ASSERT_MESSAGE("operator==: scale matrix", aScale.operator==(maScale)); @@ -239,59 +233,11 @@ public: affineAffineProd.set(1, 1, 33); affineAffineProd.set(1, 2, 48); - B2DHomMatrix affinePerspectiveProd; - - affinePerspectiveProd.set(0, 0, 30); - affinePerspectiveProd.set(0, 1, 36); - affinePerspectiveProd.set(0, 2, 42); - affinePerspectiveProd.set(1, 0, 66); - affinePerspectiveProd.set(1, 1, 81); - affinePerspectiveProd.set(1, 2, 96); - affinePerspectiveProd.set(2, 0, 7); - affinePerspectiveProd.set(2, 1, 8); - affinePerspectiveProd.set(2, 2, 9); - - B2DHomMatrix perspectiveAffineProd; - - perspectiveAffineProd.set(0, 0, 9); - perspectiveAffineProd.set(0, 1, 12); - perspectiveAffineProd.set(0, 2, 18); - perspectiveAffineProd.set(1, 0, 24); - perspectiveAffineProd.set(1, 1, 33); - perspectiveAffineProd.set(1, 2, 48); - perspectiveAffineProd.set(2, 0, 39); - perspectiveAffineProd.set(2, 1, 54); - perspectiveAffineProd.set(2, 2, 78); - - B2DHomMatrix perspectivePerspectiveProd; - - perspectivePerspectiveProd.set(0, 0, 30); - perspectivePerspectiveProd.set(0, 1, 36); - perspectivePerspectiveProd.set(0, 2, 42); - perspectivePerspectiveProd.set(1, 0, 66); - perspectivePerspectiveProd.set(1, 1, 81); - perspectivePerspectiveProd.set(1, 2, 96); - perspectivePerspectiveProd.set(2, 0, 102); - perspectivePerspectiveProd.set(2, 1, 126); - perspectivePerspectiveProd.set(2, 2, 150); - B2DHomMatrix temp; temp = maAffine; temp *= maAffine; CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: both compact", affineAffineProd, temp); - - temp = maPerspective; - temp *= maAffine; - CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: first compact", affinePerspectiveProd, temp); - - temp = maAffine; - temp *= maPerspective; - CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: second compact", perspectiveAffineProd, temp); - - temp = maPerspective; - temp *= maPerspective; - CPPUNIT_ASSERT_EQUAL_MESSAGE("multiply: none compact", perspectivePerspectiveProd, temp); } void impFillMatrix(B2DHomMatrix& rSource, double fScaleX, double fScaleY, double fShearX, diff --git a/chart2/source/tools/CommonConverters.cxx b/chart2/source/tools/CommonConverters.cxx index 50b08397e1d4..293fa7b11ddf 100644 --- a/chart2/source/tools/CommonConverters.cxx +++ b/chart2/source/tools/CommonConverters.cxx @@ -92,9 +92,10 @@ drawing::HomogenMatrix B3DHomMatrixToHomogenMatrix( const ::basegfx::B3DHomMatri aM.set(1, 0, rM.get(1, 0)); aM.set(1, 1, rM.get(1, 1)); aM.set(1, 2, rM.get(1, 3)); - aM.set(2, 0, rM.get(3, 0)); - aM.set(2, 1, rM.get(3, 1)); - aM.set(2, 2, rM.get(3, 3)); + // For this to be a valid 2D transform matrix, the last row must be [0,0,1] + assert( rM.get(3, 0) == 0 ); + assert( rM.get(3, 1) == 0 ); + assert( rM.get(3, 3) == 1 ); return aM; } @@ -107,9 +108,9 @@ drawing::HomogenMatrix3 B2DHomMatrixToHomogenMatrix3( const ::basegfx::B2DHomMat aHM.Line2.Column1 = rM.get(1, 0); aHM.Line2.Column2 = rM.get(1, 1); aHM.Line2.Column3 = rM.get(1, 2); - aHM.Line3.Column1 = rM.get(2, 0); - aHM.Line3.Column2 = rM.get(2, 1); - aHM.Line3.Column3 = rM.get(2, 2); + aHM.Line3.Column1 = 0; + aHM.Line3.Column2 = 0; + aHM.Line3.Column3 = 1; return aHM; } diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx index 5176838d610e..ccfaa13bd8bf 100644 --- a/drawinglayer/source/texture/texture.cxx +++ b/drawinglayer/source/texture/texture.cxx @@ -944,20 +944,6 @@ namespace drawinglayer::texture rMat.get(1, 1) * fY + rMat.get(1, 2)); - if(!rMat.isLastLineDefault()) - { - const double fOne(1.0); - const double fTempM( - rMat.get(2, 0) * fX + - rMat.get(2, 1) * fY + - rMat.get(2, 2)); - - if(!basegfx::fTools::equalZero(fTempM) && !basegfx::fTools::equal(fOne, fTempM)) - { - fTempY /= fTempM; - } - } - return fmod(fTempY, mfDistance); } diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx index 08f585a3638b..2267a1080c13 100644 --- a/drawinglayer/source/tools/primitive2dxmldump.cxx +++ b/drawinglayer/source/tools/primitive2dxmldump.cxx @@ -81,9 +81,9 @@ void writeMatrix(::tools::XmlWriter& rWriter, const basegfx::B2DHomMatrix& rMatr rWriter.attribute("xy21", rMatrix.get(1, 0)); rWriter.attribute("xy22", rMatrix.get(1, 1)); rWriter.attribute("xy23", rMatrix.get(1, 2)); - rWriter.attribute("xy31", rMatrix.get(2, 0)); - rWriter.attribute("xy32", rMatrix.get(2, 1)); - rWriter.attribute("xy33", rMatrix.get(2, 2)); + rWriter.attribute("xy31", 0); + rWriter.attribute("xy32", 0); + rWriter.attribute("xy33", 1); } void writeMatrix3D(::tools::XmlWriter& rWriter, const basegfx::B3DHomMatrix& rMatrix) diff --git a/filter/source/msfilter/eschesdo.cxx b/filter/source/msfilter/eschesdo.cxx index 8c39297f1e59..efe6cdfaa495 100644 --- a/filter/source/msfilter/eschesdo.cxx +++ b/filter/source/msfilter/eschesdo.cxx @@ -1090,9 +1090,10 @@ static basegfx::B2DRange getUnrotatedGroupBoundRange(const Reference< XShape >& aHomogenMatrix.set(1, 0, aMatrix.Line2.Column1); aHomogenMatrix.set(1, 1, aMatrix.Line2.Column2); aHomogenMatrix.set(1, 2, aMatrix.Line2.Column3); - aHomogenMatrix.set(2, 0, aMatrix.Line3.Column1); - aHomogenMatrix.set(2, 1, aMatrix.Line3.Column2); - aHomogenMatrix.set(2, 2, aMatrix.Line3.Column3); + // For this to be a valid 2D transform matrix, the last row must be [0,0,1] + assert( aMatrix.Line3.Column1 == 0 ); + assert( aMatrix.Line3.Column2 == 0 ); + assert( aMatrix.Line3.Column3 == 1 ); basegfx::B2DVector aScale, aTranslate; double fRotate, fShearX; diff --git a/include/basegfx/matrix/b2dhommatrix.hxx b/include/basegfx/matrix/b2dhommatrix.hxx index e1fbf60dee1a..19660f786c99 100644 --- a/include/basegfx/matrix/b2dhommatrix.hxx +++ b/include/basegfx/matrix/b2dhommatrix.hxx @@ -26,22 +26,35 @@ #include <sal/types.h> #include <basegfx/basegfxdllapi.h> #include <basegfx/matrix/hommatrixtemplate.hxx> +#include <array> namespace basegfx { class B2DTuple; - using Impl2DHomMatrix = ::basegfx::internal::ImplHomMatrixTemplate< 3 >; - class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC B2DHomMatrix { private: - Impl2DHomMatrix maImpl; + // Since this is a graphics matrix, the last row is always 0 0 1, so we don't bother to store it. + std::array<std::array<double, 3>, 2> mfValues { + std::array<double, 3>{ 1.0, 0.0, 0.0 }, + std::array<double, 3>{ 0.0, 1.0, 0.0 } }; public: - B2DHomMatrix() {} - B2DHomMatrix(const B2DHomMatrix& rMat) = default; - B2DHomMatrix(B2DHomMatrix&& rMat) = default; + constexpr B2DHomMatrix() = default; + + /** constructor to allow setting all needed values for a 3x2 matrix at once. The + parameter f_0x1 e.g. is the same as using set(0, 1, f) + */ + constexpr B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2) + { + mfValues[0][0] = f_0x0; + mfValues[0][1] = f_0x1; + mfValues[0][2] = f_0x2; + mfValues[1][0] = f_1x0; + mfValues[1][1] = f_1x1; + mfValues[1][2] = f_1x2; + } /** Convenience creator for declaration of the matrix that is commonly used by web standards (SVG, CSS, HTML). @@ -70,27 +83,21 @@ namespace basegfx // Convenience accessor for value at 1,2 position in the matrix double f() const { return get(1,2); } - /** constructor to allow setting all needed values for a 3x2 matrix at once. The - parameter f_0x1 e.g. is the same as using set(0, 1, f) - */ - B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2); - double get(sal_uInt16 nRow, sal_uInt16 nColumn) const { - return maImpl.get(nRow, nColumn); + return mfValues[nRow][nColumn]; } - void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue); + void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue) + { + mfValues[nRow][nColumn] = fValue; + } /** allow setting all needed values for a 3x2 matrix in one call. The parameter f_0x1 e.g. is the same as using set(0, 1, f) */ void set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2); - // test if last line is default to see if last line needs to be - // involved in calculations - bool isLastLineDefault() const; - // reset to a standard matrix bool isIdentity() const; void identity(); @@ -110,22 +117,12 @@ namespace basegfx void shearX(double fSx); void shearY(double fSy); - B2DHomMatrix& operator+=(const B2DHomMatrix& rMat); - B2DHomMatrix& operator-=(const B2DHomMatrix& rMat); - bool operator==(const B2DHomMatrix& rMat) const; bool operator!=(const B2DHomMatrix& rMat) const; - B2DHomMatrix& operator*=(double fValue); - B2DHomMatrix& operator/=(double fValue); - // matrix multiplication from the left to the local B2DHomMatrix& operator*=(const B2DHomMatrix& rMat); - // assignment operator - B2DHomMatrix& operator=(const B2DHomMatrix& rMat) = default; - B2DHomMatrix& operator=(B2DHomMatrix&& rMat) = default; - /** * Help routine to decompose given homogen 3x3 matrix to components. A correction of the * components is done to avoid inaccuracies. @@ -134,6 +131,11 @@ namespace basegfx * compose a homogen 3x3 matrix from components. */ bool decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const; + + private: + void computeAdjoint(double (&dst)[6]) const; + double computeDeterminant(double (&dst)[6]) const; + void doMulMatrix(const B2DHomMatrix& rMat); }; inline B2DHomMatrix operator*(const B2DHomMatrix& rMatA, const B2DHomMatrix& rMatB) @@ -150,9 +152,7 @@ namespace basegfx return stream << '[' << matrix.get(0, 0) << ' ' << matrix.get(0, 1) << ' ' << matrix.get(0, 2) << "; " << matrix.get(1, 0) << ' ' - << matrix.get(1, 1) << ' ' << matrix.get(1, 2) << "; " - << matrix.get(2, 0) << ' ' << matrix.get(2, 1) << ' ' - << matrix.get(2, 2) << ']'; + << matrix.get(1, 1) << ' ' << matrix.get(1, 2) << ']'; } } // end of namespace basegfx diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index 9417551b0f86..b9aebab1b31d 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -1118,9 +1118,9 @@ Reference< XShape > const & Shape::createAndInsert( aMatrix.Line2.Column2 = aTransformation.get(1,1); aMatrix.Line2.Column3 = aTransformation.get(1,2); - aMatrix.Line3.Column1 = aTransformation.get(2,0); - aMatrix.Line3.Column2 = aTransformation.get(2,1); - aMatrix.Line3.Column3 = aTransformation.get(2,2); + aMatrix.Line3.Column1 = 0; + aMatrix.Line3.Column2 = 0; + aMatrix.Line3.Column3 = 1; maShapeProperties.setProperty(PROP_Transformation, aMatrix); } diff --git a/oox/source/shape/WpsContext.cxx b/oox/source/shape/WpsContext.cxx index 8e0cb8b544df..beaefc33fbbc 100644 --- a/oox/source/shape/WpsContext.cxx +++ b/oox/source/shape/WpsContext.cxx @@ -606,9 +606,10 @@ oox::core::ContextHandlerRef WpsContext::onCreateContext(sal_Int32 nElementToken aTransformation.set(1, 0, aMatrix.Line2.Column1); aTransformation.set(1, 1, aMatrix.Line2.Column2); aTransformation.set(1, 2, aMatrix.Line2.Column3); - aTransformation.set(2, 0, aMatrix.Line3.Column1); - aTransformation.set(2, 1, aMatrix.Line3.Column2); - aTransformation.set(2, 2, aMatrix.Line3.Column3); + // For this to be a valid 2D transform matrix, the last row must be [0,0,1] + assert(aMatrix.Line3.Column1 == 0); + assert(aMatrix.Line3.Column2 == 0); + assert(aMatrix.Line3.Column3 == 1); basegfx::B2DTuple aScale; basegfx::B2DTuple aTranslate; double fRotate = 0; diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx index f46727299cef..8494f493513d 100644 --- a/svx/source/unodraw/unoshape.cxx +++ b/svx/source/unodraw/unoshape.cxx @@ -2076,9 +2076,10 @@ bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn aNewHomogenMatrix.set(1, 0, aMatrix.Line2.Column1); aNewHomogenMatrix.set(1, 1, aMatrix.Line2.Column2); aNewHomogenMatrix.set(1, 2, aMatrix.Line2.Column3); - aNewHomogenMatrix.set(2, 0, aMatrix.Line3.Column1); - aNewHomogenMatrix.set(2, 1, aMatrix.Line3.Column2); - aNewHomogenMatrix.set(2, 2, aMatrix.Line3.Column3); + // For this to be a valid 2D transform matrix, the last row must be [0,0,1] + assert( aMatrix.Line3.Column1 == 0 ); + assert( aMatrix.Line3.Column2 == 0 ); + assert( aMatrix.Line3.Column3 == 1 ); // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm // Need to adapt aNewHomogenMatrix from 100thmm to app-specific @@ -2578,9 +2579,9 @@ bool SvxShape::getPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn aMatrix.Line2.Column1 = aNewHomogenMatrix.get(1, 0); aMatrix.Line2.Column2 = aNewHomogenMatrix.get(1, 1); aMatrix.Line2.Column3 = aNewHomogenMatrix.get(1, 2); - aMatrix.Line3.Column1 = aNewHomogenMatrix.get(2, 0); - aMatrix.Line3.Column2 = aNewHomogenMatrix.get(2, 1); - aMatrix.Line3.Column3 = aNewHomogenMatrix.get(2, 2); + aMatrix.Line3.Column1 = 0; + aMatrix.Line3.Column2 = 0; + aMatrix.Line3.Column3 = 1; rValue <<= aMatrix; diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 47b4eb61684d..1be771b89174 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -1379,9 +1379,10 @@ static sal_Int16 lcl_GetAngle(const drawing::HomogenMatrix3& rMatrix) aTransformation.set(1, 0, rMatrix.Line2.Column1); aTransformation.set(1, 1, rMatrix.Line2.Column2); aTransformation.set(1, 2, rMatrix.Line2.Column3); - aTransformation.set(2, 0, rMatrix.Line3.Column1); - aTransformation.set(2, 1, rMatrix.Line3.Column2); - aTransformation.set(2, 2, rMatrix.Line3.Column3); + // For this to be a valid 2D transform matrix, the last row must be [0,0,1] + assert( rMatrix.Line3.Column1 == 0 ); + assert( rMatrix.Line3.Column2 == 0 ); + assert( rMatrix.Line3.Column3 == 1 ); aTransformation.decompose(aScale, aTranslate, fRotate, fShear); sal_Int16 nDeg = round(basegfx::rad2deg(fRotate)); @@ -1553,9 +1554,9 @@ static void lcl_placeWatermarkInHeader(const SfxWatermarkItem& rWatermark, aMatrix.Line2.Column1 = aTransformation.get(1, 0); aMatrix.Line2.Column2 = aTransformation.get(1, 1); aMatrix.Line2.Column3 = aTransformation.get(1, 2); - aMatrix.Line3.Column1 = aTransformation.get(2, 0); - aMatrix.Line3.Column2 = aTransformation.get(2, 1); - aMatrix.Line3.Column3 = aTransformation.get(2, 2); + aMatrix.Line3.Column1 = 0; + aMatrix.Line3.Column2 = 0; + aMatrix.Line3.Column3 = 1; uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY); xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, uno::Any(text::TextContentAnchorType_AT_CHARACTER)); uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY); diff --git a/sw/source/core/unocore/unodraw.cxx b/sw/source/core/unocore/unodraw.cxx index a096f4f12268..cda4850d8671 100644 --- a/sw/source/core/unocore/unodraw.cxx +++ b/sw/source/core/unocore/unodraw.cxx @@ -2553,9 +2553,10 @@ drawing::HomogenMatrix3 SwXShape::ConvertTransformationToLayoutDir( aTempMatrix.set(1, 0, aMatrix.Line2.Column1 ); aTempMatrix.set(1, 1, aMatrix.Line2.Column2 ); aTempMatrix.set(1, 2, aMatrix.Line2.Column3 ); - aTempMatrix.set(2, 0, aMatrix.Line3.Column1 ); - aTempMatrix.set(2, 1, aMatrix.Line3.Column2 ); - aTempMatrix.set(2, 2, aMatrix.Line3.Column3 ); + // For this to be a valid 2D transform matrix, the last row must be [0,0,1] + assert( aMatrix.Line3.Column1 == 0 ); + assert( aMatrix.Line3.Column2 == 0 ); + assert( aMatrix.Line3.Column3 == 1 ); // #i73079# aTempMatrix.translate( aTranslateDiff.X, aTranslateDiff.Y ); aMatrix.Line1.Column1 = aTempMatrix.get(0, 0); @@ -2564,9 +2565,9 @@ drawing::HomogenMatrix3 SwXShape::ConvertTransformationToLayoutDir( aMatrix.Line2.Column1 = aTempMatrix.get(1, 0); aMatrix.Line2.Column2 = aTempMatrix.get(1, 1); aMatrix.Line2.Column3 = aTempMatrix.get(1, 2); - aMatrix.Line3.Column1 = aTempMatrix.get(2, 0); - aMatrix.Line3.Column2 = aTempMatrix.get(2, 1); - aMatrix.Line3.Column3 = aTempMatrix.get(2, 2); + aMatrix.Line3.Column1 = 0; + aMatrix.Line3.Column2 = 0; + aMatrix.Line3.Column3 = 1; } } } diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx index 7f19e7fe3688..51976a625c97 100644 --- a/xmloff/source/draw/shapeexport.cxx +++ b/xmloff/source/draw/shapeexport.cxx @@ -1513,9 +1513,10 @@ void XMLShapeExport::ImpExportNewTrans_GetB2DHomMatrix(::basegfx::B2DHomMatrix& rMatrix.set(1, 0, aMatrix.Line2.Column1); rMatrix.set(1, 1, aMatrix.Line2.Column2); rMatrix.set(1, 2, aMatrix.Line2.Column3); - rMatrix.set(2, 0, aMatrix.Line3.Column1); - rMatrix.set(2, 1, aMatrix.Line3.Column2); - rMatrix.set(2, 2, aMatrix.Line3.Column3); + // For this to be a valid 2D transform matrix, the last row must be [0,0,1] + assert( aMatrix.Line3.Column1 == 0 ); + assert( aMatrix.Line3.Column2 == 0 ); + assert( aMatrix.Line3.Column3 == 1 ); } void XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint(const ::basegfx::B2DHomMatrix& rMatrix, ::basegfx::B2DTuple& rTRScale, diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 74d5027e7c11..5e965eba5aaa 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -590,9 +590,9 @@ void SdXMLShapeContext::SetTransformation() aUnoMatrix.Line2.Column2 = aB2DHomMatrix.get(1, 1); aUnoMatrix.Line2.Column3 = aB2DHomMatrix.get(1, 2); - aUnoMatrix.Line3.Column1 = aB2DHomMatrix.get(2, 0); - aUnoMatrix.Line3.Column2 = aB2DHomMatrix.get(2, 1); - aUnoMatrix.Line3.Column3 = aB2DHomMatrix.get(2, 2); + aUnoMatrix.Line3.Column1 = 0; + aUnoMatrix.Line3.Column2 = 0; + aUnoMatrix.Line3.Column3 = 1; xPropSet->setPropertyValue("Transformation", Any(aUnoMatrix)); }