diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-05-15 15:28:34 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-05-16 07:57:51 +0200 |
commit | 83650c82b56f496cd165981aa34edef9d5547697 (patch) | |
tree | 47bd3f94197fc668a26852b11da4fa27b5d88425 /basegfx/source | |
parent | 1303d88047e21fd40c0d1cf056727efc7d690d9c (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/source')
-rw-r--r-- | basegfx/source/inc/hommatrixtemplate.hxx | 525 | ||||
-rw-r--r-- | basegfx/source/matrix/b2dhommatrix.cxx | 92 | ||||
-rw-r--r-- | basegfx/source/matrix/b3dhommatrix.cxx | 2 |
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> |