summaryrefslogtreecommitdiff
path: root/basegfx
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2023-05-15 15:28:34 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2023-05-16 07:57:51 +0200
commit83650c82b56f496cd165981aa34edef9d5547697 (patch)
tree47bd3f94197fc668a26852b11da4fa27b5d88425 /basegfx
parent1303d88047e21fd40c0d1cf056727efc7d690d9c (diff)
tdf#63130 make B2DHomMatrix a flat object
instead of using COW for its data. This takes the load time from 1m29 to 1m12 Also fix a bug in ImplHomMatrixTemplate::operator= which never triggered before because the usage of o3tl::cow_wrapper means it very seldom gets used. Change-Id: Ib0a7bdddf6c014f583e06d15e8dce5025e67e4a1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151793 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'basegfx')
-rw-r--r--basegfx/source/inc/hommatrixtemplate.hxx525
-rw-r--r--basegfx/source/matrix/b2dhommatrix.cxx92
-rw-r--r--basegfx/source/matrix/b3dhommatrix.cxx2
3 files changed, 34 insertions, 585 deletions
diff --git a/basegfx/source/inc/hommatrixtemplate.hxx b/basegfx/source/inc/hommatrixtemplate.hxx
deleted file mode 100644
index a80df114c3e3..000000000000
--- a/basegfx/source/inc/hommatrixtemplate.hxx
+++ /dev/null
@@ -1,525 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#pragma once
-
-#include <sal/types.h>
-#include <basegfx/numeric/ftools.hxx>
-#include <cmath>
-#include <string.h>
-
-#include <memory>
-
-namespace basegfx::internal
- {
-
- inline double implGetDefaultValue(sal_uInt16 nRow, sal_uInt16 nColumn)
- {
- if(nRow == nColumn)
- return 1.0;
- return 0.0;
- }
-
- template < sal_uInt16 RowSize > class ImplMatLine
- {
- double mfValue[RowSize];
-
- public:
- ImplMatLine()
- {
- }
-
- explicit ImplMatLine(sal_uInt16 nRow, ImplMatLine< RowSize >* pToBeCopied)
- {
- if(pToBeCopied)
- {
- memcpy(&mfValue, pToBeCopied, sizeof(double) * RowSize);
- }
- else
- {
- for(sal_uInt16 a(0); a < RowSize; a++)
- {
- mfValue[a] = implGetDefaultValue(nRow, a);
- }
- }
- }
-
- double get(sal_uInt16 nColumn) const
- {
- return mfValue[nColumn];
- }
-
- void set(sal_uInt16 nColumn, const double& rValue)
- {
- mfValue[nColumn] = rValue;
- }
- };
-
- template < sal_uInt16 RowSize > class ImplHomMatrixTemplate
- {
- ImplMatLine< RowSize > maLine[RowSize - 1];
- std::unique_ptr<ImplMatLine< RowSize >> mutable mpLine;
-
- public:
- // Is last line used?
- bool isLastLineDefault() const
- {
- if(!mpLine)
- return true;
-
- for(sal_uInt16 a(0); a < RowSize; a++)
- {
- const double fDefault(implGetDefaultValue((RowSize - 1), a));
- const double fLineValue(mpLine->get(a));
-
- if(!::basegfx::fTools::equal(fDefault, fLineValue))
- {
- return false;
- }
- }
-
- // reset last line, it equals default
- mpLine.reset();
-
- return true;
- }
-
- ImplHomMatrixTemplate()
- {
- // complete initialization with identity matrix, all lines
- // were initialized with a trailing 1 followed by 0's.
- for(sal_uInt16 a(0); a < RowSize-1; a++)
- {
- for(sal_uInt16 b(0); b < RowSize; b++)
- maLine[a].set(b, implGetDefaultValue(a, b) );
- }
- }
-
- ImplHomMatrixTemplate(const ImplHomMatrixTemplate& rToBeCopied)
- {
- operator=(rToBeCopied);
- }
-
- ImplHomMatrixTemplate& operator=(const ImplHomMatrixTemplate& rToBeCopied)
- {
- if (this != &rToBeCopied)
- {
- // complete initialization using copy
- for(sal_uInt16 a(0); a < (RowSize - 1); a++)
- {
- memcpy(&maLine[a], &rToBeCopied.maLine[a], sizeof(ImplMatLine< RowSize >));
- }
- if(rToBeCopied.mpLine)
- {
- mpLine.reset( new ImplMatLine< RowSize >((RowSize - 1), rToBeCopied.mpLine.get()) );
- }
- }
- return *this;
- }
-
- static sal_uInt16 getEdgeLength() { return RowSize; }
-
- double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
- {
- if(nRow < (RowSize - 1))
- {
- return maLine[nRow].get(nColumn);
- }
-
- if(mpLine)
- {
- return mpLine->get(nColumn);
- }
-
- return implGetDefaultValue((RowSize - 1), nColumn);
- }
-
- void set(sal_uInt16 nRow, sal_uInt16 nColumn, const double& rValue)
- {
- if(nRow < (RowSize - 1))
- {
- maLine[nRow].set(nColumn, rValue);
- }
- else if(mpLine)
- {
- mpLine->set(nColumn, rValue);
- }
- else
- {
- const double fDefault(implGetDefaultValue((RowSize - 1), nColumn));
-
- if(!::basegfx::fTools::equal(fDefault, rValue))
- {
- mpLine.reset(new ImplMatLine< RowSize >((RowSize - 1), nullptr));
- mpLine->set(nColumn, rValue);
- }
- }
- }
-
- void testLastLine()
- {
- if(!mpLine)
- return;
-
- bool bNecessary(false);
-
- for(sal_uInt16 a(0);!bNecessary && a < RowSize; a++)
- {
- const double fDefault(implGetDefaultValue((RowSize - 1), a));
- const double fLineValue(mpLine->get(a));
-
- if(!::basegfx::fTools::equal(fDefault, fLineValue))
- {
- bNecessary = true;
- }
- }
-
- if(!bNecessary)
- {
- mpLine.reset();
- }
- }
-
- // Left-upper decomposition
- bool ludcmp(sal_uInt16 nIndex[], sal_Int16& nParity)
- {
- double fBig, fSum, fDum;
- double fStorage[RowSize];
- sal_uInt16 a, b, c;
-
- // #i30874# Initialize nAMax (compiler warns)
- sal_uInt16 nAMax = 0;
-
- nParity = 1;
-
- // Calc the max of each line. If a line is empty,
- // stop immediately since matrix is not invertible then.
- for(a = 0; a < RowSize; a++)
- {
- fBig = 0.0;
-
- for(b = 0; b < RowSize; b++)
- {
- double fTemp(fabs(get(a, b)));
-
- if(::basegfx::fTools::more(fTemp, fBig))
- {
- fBig = fTemp;
- }
- }
-
- if(::basegfx::fTools::equalZero(fBig))
- {
- return false;
- }
-
- fStorage[a] = 1.0 / fBig;
- }
-
- // start normalizing
- for(b = 0; b < RowSize; b++)
- {
- for(a = 0; a < b; a++)
- {
- fSum = get(a, b);
-
- for(c = 0; c < a; c++)
- {
- fSum -= get(a, c) * get(c, b);
- }
-
- set(a, b, fSum);
- }
-
- fBig = 0.0;
-
- for(a = b; a < RowSize; a++)
- {
- fSum = get(a, b);
-
- for(c = 0; c < b; c++)
- {
- fSum -= get(a, c) * get(c, b);
- }
-
- set(a, b, fSum);
- fDum = fStorage[a] * fabs(fSum);
-
- if(::basegfx::fTools::moreOrEqual(fDum, fBig))
- {
- fBig = fDum;
- nAMax = a;
- }
- }
-
- if(b != nAMax)
- {
- for(c = 0; c < RowSize; c++)
- {
- fDum = get(nAMax, c);
- set(nAMax, c, get(b, c));
- set(b, c, fDum);
- }
-
- nParity = -nParity;
- fStorage[nAMax] = fStorage[b];
- }
-
- nIndex[b] = nAMax;
-
- // here the failure of precision occurs
- const double fValBB(fabs(get(b, b)));
-
- if(::basegfx::fTools::equalZero(fValBB))
- {
- return false;
- }
-
- if(b != (RowSize - 1))
- {
- fDum = 1.0 / get(b, b);
-
- for(a = b + 1; a < RowSize; a++)
- {
- set(a, b, get(a, b) * fDum);
- }
- }
- }
-
- return true;
- }
-
- void lubksb(const sal_uInt16 nIndex[], double fRow[]) const
- {
- sal_uInt16 b, ip;
- sal_Int16 a, a2 = -1;
- double fSum;
-
- for(a = 0; a < RowSize; a++)
- {
- ip = nIndex[a];
- fSum = fRow[ip];
- fRow[ip] = fRow[a];
-
- if(a2 >= 0)
- {
- for(b = a2; b < a; b++)
- {
- fSum -= get(a, b) * fRow[b];
- }
- }
- else if(!::basegfx::fTools::equalZero(fSum))
- {
- a2 = a;
- }
-
- fRow[a] = fSum;
- }
-
- for(a = (RowSize - 1); a >= 0; a--)
- {
- fSum = fRow[a];
-
- for(b = a + 1; b < RowSize; b++)
- {
- fSum -= get(a, b) * fRow[b];
- }
-
- const double fValueAA(get(a, a));
-
- if(!::basegfx::fTools::equalZero(fValueAA))
- {
- fRow[a] = fSum / get(a, a);
- }
- }
- }
-
- bool isIdentity() const
- {
- // last line needs no testing if not existing
- const sal_uInt16 nMaxLine(
- sal::static_int_cast<sal_uInt16>(mpLine ? RowSize : (RowSize - 1)) );
-
- for(sal_uInt16 a(0); a < nMaxLine; a++)
- {
- for(sal_uInt16 b(0); b < RowSize; b++)
- {
- const double fDefault(implGetDefaultValue(a, b));
- const double fValueAB(get(a, b));
-
- if(!::basegfx::fTools::equal(fDefault, fValueAB))
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- bool isInvertible() const
- {
- ImplHomMatrixTemplate aWork(*this);
- sal_uInt16 nIndex[RowSize];
- sal_Int16 nParity;
-
- return aWork.ludcmp(nIndex, nParity);
- }
-
- void doInvert(const ImplHomMatrixTemplate& rWork, const sal_uInt16 nIndex[])
- {
- double fArray[RowSize];
-
- for(sal_uInt16 a(0); a < RowSize; a++)
- {
- // prepare line
- sal_uInt16 b;
- for( b = 0; b < RowSize; b++)
- {
- fArray[b] = implGetDefaultValue(a, b);
- }
-
- // expand line
- rWork.lubksb(nIndex, fArray);
-
- // copy line transposed to this matrix
- for( b = 0; b < RowSize; b++)
- {
- set(b, a, fArray[b]);
- }
- }
-
- // evtl. get rid of last matrix line
- testLastLine();
- }
-
- double doDeterminant() const
- {
- ImplHomMatrixTemplate aWork(*this);
- sal_uInt16 nIndex[RowSize];
- sal_Int16 nParity;
- double fRetval(0.0);
-
- if(aWork.ludcmp(nIndex, nParity))
- {
- fRetval = static_cast<double>(nParity);
-
- // last line needs no multiply if not existing; default value would be 1.
- const sal_uInt16 nMaxLine(
- sal::static_int_cast<sal_uInt16>(aWork.mpLine ? RowSize : (RowSize - 1)) );
-
- for(sal_uInt16 a(0); a < nMaxLine; a++)
- {
- fRetval *= aWork.get(a, a);
- }
- }
-
- return fRetval;
- }
-
- void doAddMatrix(const ImplHomMatrixTemplate& rMat)
- {
- for(sal_uInt16 a(0); a < RowSize; a++)
- {
- for(sal_uInt16 b(0); b < RowSize; b++)
- {
- set(a, b, get(a, b) + rMat.get(a, b));
- }
- }
-
- testLastLine();
- }
-
- void doSubMatrix(const ImplHomMatrixTemplate& rMat)
- {
- for(sal_uInt16 a(0); a < RowSize; a++)
- {
- for(sal_uInt16 b(0); b < RowSize; b++)
- {
- set(a, b, get(a, b) - rMat.get(a, b));
- }
- }
-
- testLastLine();
- }
-
- void doMulMatrix(const double& rfValue)
- {
- for(sal_uInt16 a(0); a < RowSize; a++)
- {
- for(sal_uInt16 b(0); b < RowSize; b++)
- {
- set(a, b, get(a, b) * rfValue);
- }
- }
-
- testLastLine();
- }
-
- void doMulMatrix(const ImplHomMatrixTemplate& rMat)
- {
- // create a copy as source for the original values
- const ImplHomMatrixTemplate aCopy(*this);
-
- // TODO: maybe optimize cases where last line is [0 0 1].
-
- double fValue(0.0);
-
- for(sal_uInt16 a(0); a < RowSize; ++a)
- {
- for(sal_uInt16 b(0); b < RowSize; ++b)
- {
- fValue = 0.0;
-
- for(sal_uInt16 c(0); c < RowSize; ++c)
- fValue += aCopy.get(c, b) * rMat.get(a, c);
-
- set(a, b, fValue);
- }
- }
-
- testLastLine();
- }
-
- bool isEqual(const ImplHomMatrixTemplate& rMat) const
- {
- const sal_uInt16 nMaxLine(
- sal::static_int_cast<sal_uInt16>((mpLine || rMat.mpLine) ? RowSize : (RowSize - 1)) );
-
- for(sal_uInt16 a(0); a < nMaxLine; a++)
- {
- for(sal_uInt16 b(0); b < RowSize; b++)
- {
- const double fValueA(get(a, b));
- const double fValueB(rMat.get(a, b));
-
- if(!::basegfx::fTools::equal(fValueA, fValueB))
- {
- return false;
- }
- }
- }
-
- return true;
- }
- };
-
-} // namespace basegfx::internal
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/source/matrix/b2dhommatrix.cxx b/basegfx/source/matrix/b2dhommatrix.cxx
index 9811304ccccd..565be5c68b1c 100644
--- a/basegfx/source/matrix/b2dhommatrix.cxx
+++ b/basegfx/source/matrix/b2dhommatrix.cxx
@@ -18,7 +18,7 @@
*/
#include <basegfx/matrix/b2dhommatrix.hxx>
-#include <hommatrixtemplate.hxx>
+#include <basegfx/matrix/hommatrixtemplate.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
@@ -26,73 +26,50 @@
namespace basegfx
{
- typedef ::basegfx::internal::ImplHomMatrixTemplate< 3 > Impl2DHomMatrix_Base;
- class Impl2DHomMatrix : public Impl2DHomMatrix_Base
- {
- };
-
- static o3tl::cow_wrapper<Impl2DHomMatrix> DEFAULT;
-
- B2DHomMatrix::B2DHomMatrix() : mpImpl(DEFAULT) {}
-
- B2DHomMatrix::B2DHomMatrix(const B2DHomMatrix&) = default;
-
- B2DHomMatrix::B2DHomMatrix(B2DHomMatrix&&) = default;
-
- B2DHomMatrix::~B2DHomMatrix() = default;
B2DHomMatrix::B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2)
{
- mpImpl->set(0, 0, f_0x0);
- mpImpl->set(0, 1, f_0x1);
- mpImpl->set(0, 2, f_0x2);
- mpImpl->set(1, 0, f_1x0);
- mpImpl->set(1, 1, f_1x1);
- mpImpl->set(1, 2, f_1x2);
- }
-
- B2DHomMatrix& B2DHomMatrix::operator=(const B2DHomMatrix&) = default;
-
- B2DHomMatrix& B2DHomMatrix::operator=(B2DHomMatrix&&) = default;
-
- double B2DHomMatrix::get(sal_uInt16 nRow, sal_uInt16 nColumn) const
- {
- return mpImpl->get(nRow, nColumn);
+ 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)
{
- mpImpl->set(nRow, nColumn, fValue);
+ maImpl.set(nRow, nColumn, fValue);
}
void B2DHomMatrix::set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2)
{
- mpImpl->set(0, 0, f_0x0);
- mpImpl->set(0, 1, f_0x1);
- mpImpl->set(0, 2, f_0x2);
- mpImpl->set(1, 0, f_1x0);
- mpImpl->set(1, 1, f_1x1);
- mpImpl->set(1, 2, 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 mpImpl->isLastLineDefault();
+ return maImpl.isLastLineDefault();
}
bool B2DHomMatrix::isIdentity() const
{
- return mpImpl.same_object(DEFAULT) || mpImpl->isIdentity();
+ return maImpl.isIdentity();
}
void B2DHomMatrix::identity()
{
- *mpImpl = Impl2DHomMatrix();
+ maImpl = Impl2DHomMatrix();
}
bool B2DHomMatrix::isInvertible() const
{
- return mpImpl->isInvertible();
+ return maImpl.isInvertible();
}
bool B2DHomMatrix::invert()
@@ -102,13 +79,13 @@ namespace basegfx
return true;
}
- Impl2DHomMatrix aWork(*mpImpl);
- sal_uInt16* pIndex = static_cast<sal_uInt16*>(alloca( sizeof(sal_uInt16) * Impl2DHomMatrix_Base::getEdgeLength() ));
+ Impl2DHomMatrix aWork(maImpl);
+ sal_uInt16* pIndex = static_cast<sal_uInt16*>(alloca( sizeof(sal_uInt16) * Impl2DHomMatrix::getEdgeLength() ));
sal_Int16 nParity;
if(aWork.ludcmp(pIndex, nParity))
{
- mpImpl->doInvert(aWork, pIndex);
+ maImpl.doInvert(aWork, pIndex);
return true;
}
@@ -117,13 +94,13 @@ namespace basegfx
B2DHomMatrix& B2DHomMatrix::operator+=(const B2DHomMatrix& rMat)
{
- mpImpl->doAddMatrix(*rMat.mpImpl);
+ maImpl.doAddMatrix(rMat.maImpl);
return *this;
}
B2DHomMatrix& B2DHomMatrix::operator-=(const B2DHomMatrix& rMat)
{
- mpImpl->doSubMatrix(*rMat.mpImpl);
+ maImpl.doSubMatrix(rMat.maImpl);
return *this;
}
@@ -132,7 +109,7 @@ namespace basegfx
const double fOne(1.0);
if(!fTools::equal(fOne, fValue))
- mpImpl->doMulMatrix(fValue);
+ maImpl.doMulMatrix(fValue);
return *this;
}
@@ -142,7 +119,7 @@ namespace basegfx
const double fOne(1.0);
if(!fTools::equal(fOne, fValue))
- mpImpl->doMulMatrix(1.0 / fValue);
+ maImpl.doMulMatrix(1.0 / fValue);
return *this;
}
@@ -161,7 +138,7 @@ namespace basegfx
else
{
// multiply
- mpImpl->doMulMatrix(*rMat.mpImpl);
+ maImpl.doMulMatrix(rMat.maImpl);
}
return *this;
@@ -169,10 +146,7 @@ namespace basegfx
bool B2DHomMatrix::operator==(const B2DHomMatrix& rMat) const
{
- if(mpImpl.same_object(rMat.mpImpl))
- return true;
-
- return mpImpl->isEqual(*rMat.mpImpl);
+ return &rMat == this || maImpl.isEqual(rMat.maImpl);
}
bool B2DHomMatrix::operator!=(const B2DHomMatrix& rMat) const
@@ -196,7 +170,7 @@ namespace basegfx
aRotMat.set(1, 0, fSin);
aRotMat.set(0, 1, -fSin);
- mpImpl->doMulMatrix(aRotMat);
+ maImpl.doMulMatrix(aRotMat);
}
void B2DHomMatrix::translate(double fX, double fY)
@@ -208,7 +182,7 @@ namespace basegfx
aTransMat.set(0, 2, fX);
aTransMat.set(1, 2, fY);
- mpImpl->doMulMatrix(aTransMat);
+ maImpl.doMulMatrix(aTransMat);
}
}
@@ -228,7 +202,7 @@ namespace basegfx
aScaleMat.set(0, 0, fX);
aScaleMat.set(1, 1, fY);
- mpImpl->doMulMatrix(aScaleMat);
+ maImpl.doMulMatrix(aScaleMat);
}
}
@@ -246,7 +220,7 @@ namespace basegfx
aShearXMat.set(0, 1, fSx);
- mpImpl->doMulMatrix(aShearXMat);
+ maImpl.doMulMatrix(aShearXMat);
}
}
@@ -259,7 +233,7 @@ namespace basegfx
aShearYMat.set(1, 0, fSy);
- mpImpl->doMulMatrix(aShearYMat);
+ maImpl.doMulMatrix(aShearYMat);
}
}
@@ -273,7 +247,7 @@ namespace basegfx
bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
{
// when perspective is used, decompose is not made here
- if(!mpImpl->isLastLineDefault())
+ if(!maImpl.isLastLineDefault())
{
return false;
}
diff --git a/basegfx/source/matrix/b3dhommatrix.cxx b/basegfx/source/matrix/b3dhommatrix.cxx
index 3605767d681d..f9018c69793f 100644
--- a/basegfx/source/matrix/b3dhommatrix.cxx
+++ b/basegfx/source/matrix/b3dhommatrix.cxx
@@ -18,7 +18,7 @@
*/
#include <basegfx/matrix/b3dhommatrix.hxx>
-#include <hommatrixtemplate.hxx>
+#include <basegfx/matrix/hommatrixtemplate.hxx>
#include <basegfx/vector/b3dvector.hxx>
#include <memory>