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.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin
2023-05-18 21:18:06 +02:00
committed by Noel Grandin
parent 1b9702920d
commit fdd06037e0
16 changed files with 181 additions and 279 deletions
+102 -109
View File
@@ -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;
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-=(const B2DHomMatrix& rMat)
/* Compute the determinant, given the adjoint matrix */
double B2DHomMatrix::computeDeterminant(double (&dst)[6]) const
{
maImpl.doSubMatrix(rMat.maImpl);
return *this;
}
B2DHomMatrix& B2DHomMatrix::operator*=(double fValue)
{
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));
-15
View File
@@ -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;
-15
View File
@@ -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);
-54
View File
@@ -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,
+7 -6
View File
@@ -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;
}
-14
View File
@@ -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);
}
@@ -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)
+4 -3
View File
@@ -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;
+30 -30
View File
@@ -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
+3 -3
View File
@@ -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);
}
+4 -3
View File
@@ -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;
+7 -6
View File
@@ -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;
+7 -6
View File
@@ -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);
+7 -6
View File
@@ -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;
}
}
}
+4 -3
View File
@@ -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,
+3 -3
View File
@@ -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));
}