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:
committed by
Noel Grandin
parent
1b9702920d
commit
fdd06037e0
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user