diff options
Diffstat (limited to 'basegfx/source/inc')
-rw-r--r-- | basegfx/source/inc/PolygonPoint.hxx | 538 | ||||
-rw-r--r-- | basegfx/source/inc/hommatrixtemplate.hxx | 613 | ||||
-rw-r--r-- | basegfx/source/inc/polygontemplate.hxx | 538 |
3 files changed, 1689 insertions, 0 deletions
diff --git a/basegfx/source/inc/PolygonPoint.hxx b/basegfx/source/inc/PolygonPoint.hxx new file mode 100644 index 000000000000..49b9cd19758b --- /dev/null +++ b/basegfx/source/inc/PolygonPoint.hxx @@ -0,0 +1,538 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _POLYGON_POINT_HXX +#define _POLYGON_POINT_HXX + +#include <vector> + +////////////////////////////////////////////////////////////////////////////// + +template < class Point > class SimplePointEntry +{ + Point maPoint; + +public: + SimplePointEntry() + : maPoint(Point::getEmptyPoint()) + { + } + + SimplePointEntry(const Point& rInitPoint) + : maPoint(rInitPoint) + { + } + + const Point& getPoint() const + { + return maPoint; + } + + void setPoint(const Point& rValue) + { + maPoint = rValue; + } + + bool operator==(const SimplePointEntry& rEntry) const + { + return (maPoint == rEntry.maPoint); + } +}; + +////////////////////////////////////////////////////////////////////////////// + +template < class Vector > class SimpleBezierEntry +{ + Vector maBackward; + Vector maForward; + +public: + SimpleBezierEntry() + : maBackward(Vector::getEmptyVector()), + maForward(Vector::getEmptyVector()) + { + } + + SimpleBezierEntry(const Vector& rInitBackward, const Vector& rInitForward) + : maBackward(rInitBackward), + maForward(rInitForward) + { + } + + const Vector& getBackwardVector() const + { + return maBackward; + } + + void setBackwardVector(const Vector& rValue) + { + maBackward = rValue; + } + + const Vector& getForwardVector() const + { + return maForward; + } + + void setForwardVector(const Vector& rValue) + { + maForward = rValue; + } + + bool isBezierNeeded() + { + if(maBackward != Vector::getEmptyVector() || maForward != Vector::getEmptyVector()) + return true; + return false; + } + + bool operator==(const SimpleBezierEntry& rEntry) const + { + return ((maBackward == rEntry.maBackward) && (maForward == rEntry.maForward)); + } + + void doInvertForFlip() + { + maBackward = -maBackward; + maForward = -maForward; + } +}; + +////////////////////////////////////////////////////////////////////////////// + +template < class Point, class Vector > class PolygonPointList +{ + typedef SimplePointEntry< Point > LocalSimplePointEntry; + typedef SimpleBezierEntry< Vector > LocalSimpleBezierEntry; + typedef ::std::vector< LocalSimplePointEntry > SimplePointVector; + typedef ::std::vector< LocalSimpleBezierEntry > SimpleBezierVector; + + sal_uInt32 mnBezierCount; + SimplePointVector maPoints; + SimpleBezierVector* mpVectors; + + unsigned mbIsClosed : 1; + + void implTryToReduceToPointVector() + { + if(!mnBezierCount && mpVectors) + { + delete mpVectors; + mpVectors = 0L; + } + } + +public: + bool isBezier() const + { + return bool(mnBezierCount); + } + + bool isClosed() const + { + return bool(mbIsClosed); + } + + void setClosed(bool bNew) + { + mbIsClosed = bNew; + } + + sal_uInt32 count() const + { + return maPoints.size(); + } + + PolygonPointList() + : mnBezierCount(0L), + mpVectors(0L), + mbIsClosed(false) + { + // complete initialization with defaults + } + + PolygonPointList(const PolygonPointList& rSource) + : mnBezierCount(0L), + maPoints(rSource.maPoints), + mpVectors(0L), + mbIsClosed(rSource.mbIsClosed) + { + // complete initialization using copy + if(rSource.mpVectors && rSource.mnBezierCount) + { + mpVectors = new SimpleBezierVector(*rSource.mpVectors); + mnBezierCount = rSource.mnBezierCount; + } + } + + PolygonPointList(const PolygonPointList& rSource, sal_uInt32 nIndex, sal_uInt32 nCount) + : mnBezierCount(0L), + maPoints(nCount), + mpVectors(0L), + mbIsClosed(rSource.mbIsClosed) + { + // complete initialization using partly copy + if(nCount) + { + // copy point data + { + SimplePointVector::const_iterator aStart(rSource.maPoints.begin()); + aStart += nIndex; + SimplePointVector::const_iterator aEnd(aStart); + aEnd += nCount; + maPoints.insert(0L, aStart, aEnd); + } + + // copy bezier data + if(rSource.mpVectors && rSource.mnBezierCount) + { + mpVectors = new SimpleBezierVector(); + mpVectors->reserve(nCount); + + SimpleBezierVector::iterator aStart(mpVectors->begin()); + aStart += nIndex; + SimpleBezierVector::iterator aEnd(aStart); + aEnd += nCount; + + for( ; aStart != aEnd; ++aStart ) + { + if(aStart->IsBezierNeeded()) + { + mnBezierCount++; + } + + mpVectors->push_back(*aStart); + } + + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + } + } + } + + ~PolygonPointList() + { + if(mpVectors) + { + delete mpVectors; + } + } + + bool isEqual(const PolygonPointList& rPointList) const + { + // same point count? + if(maPoints.size() != rPointList.maPoints.size()) + return false; + + // if zero points the polys are equal + if(!maPoints.size()) + return true; + + // if bezier count used it needs to be equal + if(mnBezierCount != rPointList.mnBezierCount) + return false; + + // compare point content + if(maPoints != rPointList.maPoints) + return false; + + // beziercounts are equal: if it's zero, we are done + if(!mnBezierCount) + return true; + + // beziercounts are equal and not zero; compare them + OSL_ENSURE(0L != mpVectors, "Error: Bezier list needs to exist here(!)"); + OSL_ENSURE(0L != rPointList.mpVectors, "Error: Bezier list needs to exist here(!)"); + + return (*mpVectors == *rPointList.mpVectors); + } + + const Point& getPoint(sal_uInt32 nIndex) const + { + return maPoints[nIndex].getPoint(); + } + + void setPoint(sal_uInt32 nIndex, const Point& rValue) + { + maPoints[nIndex].setPoint(rValue); + } + + const Vector& getBackwardVector(sal_uInt32 nIndex) const + { + if(mpVectors) + return ((*mpVectors)[nIndex]).getBackwardVector(); + else + return Vector::getEmptyVector(); + } + + void setBackwardVector(sal_uInt32 nIndex, const Vector& rValue) + { + if(mpVectors) + { + LocalSimpleBezierEntry& rDest = (*mpVectors)[nIndex]; + bool bBezierNeededBefore(rDest.isBezierNeeded()); + ((*mpVectors)[nIndex]).setBackwardVector(rValue); + bool bBezierNeededAfter(rDest.isBezierNeeded()); + + if(bBezierNeededBefore != bBezierNeededAfter) + { + if(bBezierNeededAfter) + mnBezierCount++; + else + mnBezierCount--; + } + } + else + { + bool bEmptyVector(rValue == Vector::getEmptyVector()); + + if(bEmptyVector) + return; + + mpVectors = new SimpleBezierVector(maPoints.size()); + ((*mpVectors)[nIndex]).setBackwardVector(rValue); + mnBezierCount++; + } + } + + const Vector& getForwardVector(sal_uInt32 nIndex) const + { + if(mpVectors) + return ((*mpVectors)[nIndex]).getForwardVector(); + else + return Vector::getEmptyVector(); + } + + void setForwardVector(sal_uInt32 nIndex, const Vector& rValue) + { + if(mpVectors) + { + LocalSimpleBezierEntry& rDest = (*mpVectors)[nIndex]; + bool bBezierNeededBefore(rDest.isBezierNeeded()); + ((*mpVectors)[nIndex]).setForwardVector(rValue); + bool bBezierNeededAfter(rDest.isBezierNeeded()); + + if(bBezierNeededBefore != bBezierNeededAfter) + { + if(bBezierNeededAfter) + mnBezierCount++; + else + mnBezierCount--; + } + } + else + { + bool bEmptyVector(rValue == Vector::getEmptyVector()); + + if(bEmptyVector) + return; + + mpVectors = new SimpleBezierVector(maPoints.size()); + ((*mpVectors)[nIndex]).setForwardVector(rValue); + mnBezierCount++; + } + } + + void insert(sal_uInt32 nIndex, const Point& rPoint, sal_uInt32 nCount) + { + if(nCount) + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // add nCount copies of rPoint + { + LocalSimplePointEntry aNode(rPoint); + SimplePointVector::iterator aIndex(maPoints.begin()); + aIndex += nIndex; + maPoints.insert(aIndex, nCount, aNode); + } + + // add nCount empty entries to keep indices synchronized + if(mpVectors) + { + LocalSimpleBezierEntry aNode; + SimpleBezierVector::iterator aIndex(mpVectors->begin()); + aIndex += nIndex; + mpVectors->insert(aIndex, nCount, aNode); + } + } + } + + void insert(sal_uInt32 nIndex, const PolygonPointList& rSource) + { + const sal_uInt32 nCount(rSource.maPoints.size()); + + if(nCount) + { + // instert point data + { + SimplePointVector::iterator aIndex(maPoints.begin()); + aIndex += nIndex; + + SimplePointVector::const_iterator aStart(rSource.maPoints.begin()); + SimplePointVector::const_iterator aEnd(rSource.maPoints.end()); + + maPoints.insert(aIndex, aStart, aEnd); + } + + // insert bezier data + if(rSource.mpVectors && rSource.mnBezierCount) + { + SimpleBezierVector::iterator aIndex(mpVectors->begin()); + aIndex += nIndex; + + SimpleBezierVector::iterator aStart(rSource.mpVectors->begin()); + SimpleBezierVector::iterator aEnd(rSource.mpVectors->end()); + + if(!mpVectors) + { + mpVectors = new SimpleBezierVector(maPoints.size() - nCount); + } + + mpVectors->insert(aIndex, aStart, aEnd); + + mnBezierCount += rSource.mnBezierCount; + } + else + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // add nCount empty entries to keep indices synchronized + if(mpVectors) + { + LocalSimpleBezierEntry aNode; + SimpleBezierVector::iterator aIndex(mpVectors->begin()); + aIndex += nIndex; + mpVectors->insert(aIndex, nCount, aNode); + } + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // remove point data + { + SimplePointVector::iterator aStart(maPoints.begin()); + aStart += nIndex; + const SimplePointVector::iterator aEnd(aStart + nCount); + + maPoints.erase(aStart, aEnd); + } + + // remove bezier data + if(mpVectors) + { + SimpleBezierVector::iterator aStart(mpVectors->begin()); + aStart += nIndex; + const SimpleBezierVector::iterator aEnd(aStart + nCount); + + // take care for correct mnBezierCount BEFORE erase + if(mnBezierCount) + { + SimpleBezierVector::iterator aTestIter(aStart); + + for( ; mnBezierCount && aTestIter != aEnd; ++aTestIter) + { + if(aTestIter->isBezierNeeded()) + mnBezierCount--; + } + } + + if(mnBezierCount) + { + // erase nodes + mpVectors->erase(aStart, aEnd); + } + else + { + // try to reduce, maybe 0L == mnBezierCount + implTryToReduceToPointVector(); + } + } + } + } + + void flip() + { + if(maPoints.size() > 1) + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // calculate half size + const sal_uInt32 nHalfSize(maPoints.size() >> 1L); + + // flip point data + { + SimplePointVector::iterator aStart(maPoints.begin()); + SimplePointVector::iterator aEnd(maPoints.end()); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + LocalSimplePointEntry aTemp = *aStart; + *aStart++ = *aEnd; + *aEnd-- = aTemp; + } + } + + // flip bezier data + if(mpVectors) + { + SimpleBezierVector::iterator aStart(mpVectors->begin()); + SimpleBezierVector::iterator aEnd(mpVectors->end()); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + LocalSimpleBezierEntry aTemp = *aStart; + aTemp.doInvertForFlip(); + *aStart = *aEnd; + aStart->doInvertForFlip(); + aStart++; + *aEnd-- = aTemp; + } + + // also flip vectors of middle point (if existing) + if(maPoints.size() % 2) + { + (*mpVectors)[nHalfSize].doInvertForFlip(); + } + } + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +#endif _POLYGON_POINT_HXX diff --git a/basegfx/source/inc/hommatrixtemplate.hxx b/basegfx/source/inc/hommatrixtemplate.hxx new file mode 100644 index 000000000000..fe58ed260291 --- /dev/null +++ b/basegfx/source/inc/hommatrixtemplate.hxx @@ -0,0 +1,613 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _HOMMATRIX_TEMPLATE_HXX +#define _HOMMATRIX_TEMPLATE_HXX + +#include <sal/types.h> +#include <basegfx/numeric/ftools.hxx> +#include <math.h> +#include <string.h> + +namespace basegfx +{ + namespace internal + { + + inline double implGetDefaultValue(sal_uInt16 nRow, sal_uInt16 nColumn) + { + if(nRow == nColumn) + return 1.0; + return 0.0; + } + + template < unsigned int _RowSize > class ImplMatLine + { + enum { RowSize = _RowSize }; + + double mfValue[RowSize]; + + public: + ImplMatLine() + { + } + + ImplMatLine(sal_uInt16 nRow, ImplMatLine< RowSize >* pToBeCopied = 0L) + { + 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 < unsigned int _RowSize > class ImplHomMatrixTemplate + { + enum { RowSize = _RowSize }; + + ImplMatLine< RowSize > maLine[RowSize - 1]; + ImplMatLine< RowSize >* 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 + delete ((ImplHomMatrixTemplate< RowSize >*)this)->mpLine; + ((ImplHomMatrixTemplate< RowSize >*)this)->mpLine = 0L; + + return true; + } + + ImplHomMatrixTemplate() + : mpLine(0L) + { + // 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) + : mpLine(0L) + { + // 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 = new ImplMatLine< RowSize >((RowSize - 1), rToBeCopied.mpLine); + } + } + + ~ImplHomMatrixTemplate() + { + if(mpLine) + { + delete mpLine; + } + } + + sal_uInt16 getEdgeLength() const { 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 = new ImplMatLine< RowSize >((RowSize - 1), 0L); + mpLine->set(nColumn, rValue); + } + } + } + + void testLastLine() + { + if(mpLine) + { + 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) + { + delete mpLine; + mpLine = 0L; + } + } + } + + // Left-upper decompositon + 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); + } + + bool isNormalized() const + { + if(!mpLine) + return true; + + const double fHomValue(get((RowSize - 1), (RowSize - 1))); + + if(::basegfx::fTools::equalZero(fHomValue)) + { + return true; + } + + const double fOne(1.0); + + if(::basegfx::fTools::equal(fOne, fHomValue)) + { + return true; + } + + return false; + } + + 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(); + } + + void doNormalize() + { + if(mpLine) + { + const double fHomValue(get((RowSize - 1), (RowSize - 1))); + + for(sal_uInt16 a(0); a < RowSize; a++) + { + for(sal_uInt16 b(0); b < RowSize; b++) + { + set(a, b, get(a, b) / fHomValue); + } + } + + // 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 = (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; + } + + double doTrace() const + { + double fTrace = (mpLine) ? 0.0 : 1.0; + const sal_uInt16 nMaxLine( + sal::static_int_cast<sal_uInt16>(mpLine ? RowSize : (RowSize - 1)) ); + + for(sal_uInt16 a(0); a < nMaxLine; a++) + { + fTrace += get(a, a); + } + + return fTrace; + } + + void doTranspose() + { + for(sal_uInt16 a(0); a < (RowSize - 1); a++) + { + for(sal_uInt16 b(a + 1); b < RowSize; b++) + { + const double fTemp(get(a, b)); + set(a, b, get(b, a)); + set(b, a, fTemp); + } + } + + testLastLine(); + } + + 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 internal +} // namespace basegfx + +#endif /* _HOMMATRIX_TEMPLATE_HXX */ diff --git a/basegfx/source/inc/polygontemplate.hxx b/basegfx/source/inc/polygontemplate.hxx new file mode 100644 index 000000000000..9ab7fdd941bd --- /dev/null +++ b/basegfx/source/inc/polygontemplate.hxx @@ -0,0 +1,538 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _POLYGON_TEMPLATE_HXX +#define _POLYGON_TEMPLATE_HXX + +#include <vector> + +////////////////////////////////////////////////////////////////////////////// + +template < class Point > class ImplSimplePointEntry +{ + Point maPoint; + +public: + ImplSimplePointEntry() + : maPoint(Point::getEmptyPoint()) + { + } + + ImplSimplePointEntry(const Point& rInitPoint) + : maPoint(rInitPoint) + { + } + + const Point& getPoint() const + { + return maPoint; + } + + void setPoint(const Point& rValue) + { + maPoint = rValue; + } + + bool operator==(const ImplSimplePointEntry& rEntry) const + { + return (maPoint == rEntry.maPoint); + } +}; + +////////////////////////////////////////////////////////////////////////////// + +template < class Vector > class ImplSimpleBezierEntry +{ + Vector maBackward; + Vector maForward; + +public: + ImplSimpleBezierEntry() + : maBackward(Vector::getEmptyVector()), + maForward(Vector::getEmptyVector()) + { + } + + ImplSimpleBezierEntry(const Vector& rInitBackward, const Vector& rInitForward) + : maBackward(rInitBackward), + maForward(rInitForward) + { + } + + const Vector& getBackwardVector() const + { + return maBackward; + } + + void setBackwardVector(const Vector& rValue) + { + maBackward = rValue; + } + + const Vector& getForwardVector() const + { + return maForward; + } + + void setForwardVector(const Vector& rValue) + { + maForward = rValue; + } + + bool isBezierNeeded() + { + if(!maBackward.equalZero() || !maForward.equalZero()) + return true; + return false; + } + + bool operator==(const ImplSimpleBezierEntry& rEntry) const + { + return ((maBackward == rEntry.maBackward) && (maForward == rEntry.maForward)); + } + + void doInvertForFlip() + { + maBackward = -maBackward; + maForward = -maForward; + } +}; + +////////////////////////////////////////////////////////////////////////////// + +template < class Point, class Vector > class ImplPolygonTemplate +{ + typedef ImplSimplePointEntry< Point > LocalImplSimplePointEntry; + typedef ImplSimpleBezierEntry< Vector > LocalImplSimpleBezierEntry; + typedef ::std::vector< LocalImplSimplePointEntry > SimplePointVector; + typedef ::std::vector< LocalImplSimpleBezierEntry > SimpleBezierVector; + + sal_uInt32 mnBezierCount; + SimplePointVector maPoints; + SimpleBezierVector* mpVectors; + + unsigned mbIsClosed : 1; + + void implTryToReduceToPointVector() + { + if(!mnBezierCount && mpVectors) + { + delete mpVectors; + mpVectors = 0L; + } + } + +public: + bool isBezier() const + { + return bool(mnBezierCount); + } + + bool isClosed() const + { + return bool(mbIsClosed); + } + + void setClosed(bool bNew) + { + mbIsClosed = bNew; + } + + sal_uInt32 count() const + { + return maPoints.size(); + } + + ImplPolygonTemplate() + : mnBezierCount(0L), + mpVectors(0L), + mbIsClosed(false) + { + // complete initialization with defaults + } + + ImplPolygonTemplate(const ImplPolygonTemplate& rSource) + : mnBezierCount(0L), + maPoints(rSource.maPoints), + mpVectors(0L), + mbIsClosed(rSource.mbIsClosed) + { + // complete initialization using copy + if(rSource.mpVectors && rSource.mnBezierCount) + { + mpVectors = new SimpleBezierVector(*rSource.mpVectors); + mnBezierCount = rSource.mnBezierCount; + } + } + + ImplPolygonTemplate(const ImplPolygonTemplate& rSource, sal_uInt32 nIndex, sal_uInt32 nCount) + : mnBezierCount(0L), + maPoints(nCount), + mpVectors(0L), + mbIsClosed(rSource.mbIsClosed) + { + // complete initialization using partly copy + if(nCount) + { + // copy point data + { + SimplePointVector::const_iterator aStart(rSource.maPoints.begin()); + aStart += nIndex; + SimplePointVector::const_iterator aEnd(aStart); + aEnd += nCount; + maPoints.insert(0L, aStart, aEnd); + } + + // copy bezier data + if(rSource.mpVectors && rSource.mnBezierCount) + { + mpVectors = new SimpleBezierVector(); + mpVectors->reserve(nCount); + + SimpleBezierVector::iterator aStart(mpVectors->begin()); + aStart += nIndex; + SimpleBezierVector::iterator aEnd(aStart); + aEnd += nCount; + + for( ; aStart != aEnd; ++aStart ) + { + if(aStart->isBezierNeeded()) + { + mnBezierCount++; + } + + mpVectors->push_back(*aStart); + } + + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + } + } + } + + ~ImplPolygonTemplate() + { + if(mpVectors) + { + delete mpVectors; + } + } + + bool isEqual(const ImplPolygonTemplate& rPointList) const + { + // same point count? + if(maPoints.size() != rPointList.maPoints.size()) + return false; + + // if zero points the polys are equal + if(!maPoints.size()) + return true; + + // if bezier count used it needs to be equal + if(mnBezierCount != rPointList.mnBezierCount) + return false; + + // compare point content + if(maPoints != rPointList.maPoints) + return false; + + // beziercounts are equal: if it's zero, we are done + if(!mnBezierCount) + return true; + + // beziercounts are equal and not zero; compare them + OSL_ENSURE(0L != mpVectors, "Error: Bezier list needs to exist here(!)"); + OSL_ENSURE(0L != rPointList.mpVectors, "Error: Bezier list needs to exist here(!)"); + + return (*mpVectors == *rPointList.mpVectors); + } + + const Point& getPoint(sal_uInt32 nIndex) const + { + return maPoints[nIndex].getPoint(); + } + + void setPoint(sal_uInt32 nIndex, const Point& rValue) + { + maPoints[nIndex].setPoint(rValue); + } + + const Vector& getBackwardVector(sal_uInt32 nIndex) const + { + if(mpVectors) + return ((*mpVectors)[nIndex]).getBackwardVector(); + else + return Vector::getEmptyVector(); + } + + void setBackwardVector(sal_uInt32 nIndex, const Vector& rValue) + { + if(mpVectors) + { + LocalImplSimpleBezierEntry& rDest = (*mpVectors)[nIndex]; + bool bBezierNeededBefore(rDest.isBezierNeeded()); + ((*mpVectors)[nIndex]).setBackwardVector(rValue); + bool bBezierNeededAfter(rDest.isBezierNeeded()); + + if(bBezierNeededBefore != bBezierNeededAfter) + { + if(bBezierNeededAfter) + mnBezierCount++; + else + mnBezierCount--; + } + } + else + { + bool bEmptyVector(rValue.equalZero()); + + if(bEmptyVector) + return; + + mpVectors = new SimpleBezierVector(maPoints.size()); + ((*mpVectors)[nIndex]).setBackwardVector(rValue); + mnBezierCount++; + } + } + + const Vector& getForwardVector(sal_uInt32 nIndex) const + { + if(mpVectors) + return ((*mpVectors)[nIndex]).getForwardVector(); + else + return Vector::getEmptyVector(); + } + + void setForwardVector(sal_uInt32 nIndex, const Vector& rValue) + { + if(mpVectors) + { + LocalImplSimpleBezierEntry& rDest = (*mpVectors)[nIndex]; + bool bBezierNeededBefore(rDest.isBezierNeeded()); + ((*mpVectors)[nIndex]).setForwardVector(rValue); + bool bBezierNeededAfter(rDest.isBezierNeeded()); + + if(bBezierNeededBefore != bBezierNeededAfter) + { + if(bBezierNeededAfter) + mnBezierCount++; + else + mnBezierCount--; + } + } + else + { + bool bEmptyVector(rValue.equalZero()); + + if(bEmptyVector) + return; + + mpVectors = new SimpleBezierVector(maPoints.size()); + ((*mpVectors)[nIndex]).setForwardVector(rValue); + mnBezierCount++; + } + } + + void insert(sal_uInt32 nIndex, const Point& rPoint, sal_uInt32 nCount) + { + if(nCount) + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // add nCount copies of rPoint + { + LocalImplSimplePointEntry aNode(rPoint); + SimplePointVector::iterator aIndex(maPoints.begin()); + aIndex += nIndex; + maPoints.insert(aIndex, nCount, aNode); + } + + // add nCount empty entries to keep indices synchronized + if(mpVectors) + { + LocalImplSimpleBezierEntry aNode; + SimpleBezierVector::iterator aIndex(mpVectors->begin()); + aIndex += nIndex; + mpVectors->insert(aIndex, nCount, aNode); + } + } + } + + void insert(sal_uInt32 nIndex, const ImplPolygonTemplate& rSource) + { + const sal_uInt32 nCount(rSource.maPoints.size()); + + if(nCount) + { + // instert point data + { + SimplePointVector::iterator aIndex(maPoints.begin()); + aIndex += nIndex; + + SimplePointVector::const_iterator aStart(rSource.maPoints.begin()); + SimplePointVector::const_iterator aEnd(rSource.maPoints.end()); + + maPoints.insert(aIndex, aStart, aEnd); + } + + // insert bezier data + if(rSource.mpVectors && rSource.mnBezierCount) + { + SimpleBezierVector::iterator aIndex(mpVectors->begin()); + aIndex += nIndex; + + SimpleBezierVector::iterator aStart(rSource.mpVectors->begin()); + SimpleBezierVector::iterator aEnd(rSource.mpVectors->end()); + + if(!mpVectors) + { + mpVectors = new SimpleBezierVector(maPoints.size() - nCount); + } + + mpVectors->insert(aIndex, aStart, aEnd); + + mnBezierCount += rSource.mnBezierCount; + } + else + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // add nCount empty entries to keep indices synchronized + if(mpVectors) + { + LocalImplSimpleBezierEntry aNode; + SimpleBezierVector::iterator aIndex(mpVectors->begin()); + aIndex += nIndex; + mpVectors->insert(aIndex, nCount, aNode); + } + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // remove point data + { + SimplePointVector::iterator aStart(maPoints.begin()); + aStart += nIndex; + const SimplePointVector::iterator aEnd(aStart + nCount); + + maPoints.erase(aStart, aEnd); + } + + // remove bezier data + if(mpVectors) + { + SimpleBezierVector::iterator aStart(mpVectors->begin()); + aStart += nIndex; + const SimpleBezierVector::iterator aEnd(aStart + nCount); + + // take care for correct mnBezierCount BEFORE erase + if(mnBezierCount) + { + SimpleBezierVector::iterator aTestIter(aStart); + + for( ; mnBezierCount && aTestIter != aEnd; ++aTestIter) + { + if(aTestIter->isBezierNeeded()) + mnBezierCount--; + } + } + + if(mnBezierCount) + { + // erase nodes + mpVectors->erase(aStart, aEnd); + } + else + { + // try to reduce, maybe 0L == mnBezierCount + implTryToReduceToPointVector(); + } + } + } + } + + void flip() + { + if(maPoints.size() > 1) + { + // maybe vectors are not needed anymore, try to reduce memory footprint + implTryToReduceToPointVector(); + + // calculate half size + const sal_uInt32 nHalfSize(maPoints.size() >> 1L); + + // flip point data + { + SimplePointVector::iterator aStart(maPoints.begin()); + SimplePointVector::iterator aEnd(maPoints.end()); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + LocalImplSimplePointEntry aTemp = *aStart; + *aStart++ = *aEnd; + *aEnd-- = aTemp; + } + } + + // flip bezier data + if(mpVectors) + { + SimpleBezierVector::iterator aStart(mpVectors->begin()); + SimpleBezierVector::iterator aEnd(mpVectors->end()); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + LocalImplSimpleBezierEntry aTemp = *aStart; + aTemp.doInvertForFlip(); + *aStart = *aEnd; + aStart->doInvertForFlip(); + aStart++; + *aEnd-- = aTemp; + } + + // also flip vectors of middle point (if existing) + if(maPoints.size() % 2) + { + (*mpVectors)[nHalfSize].doInvertForFlip(); + } + } + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +#endif _POLYGON_TEMPLATE_HXX |