diff options
author | Armin Weiss <aw@openoffice.org> | 2003-10-28 10:26:57 +0000 |
---|---|---|
committer | Armin Weiss <aw@openoffice.org> | 2003-10-28 10:26:57 +0000 |
commit | 5c35c4ae404294fede343dc4668d0b57c580b485 (patch) | |
tree | b46c73fca4ec3d4b3a8b330bfc2a412fd1eb6749 /basegfx/source/polygon | |
parent | 999a109d17bdce1000f7a69417de51668334c7fc (diff) |
basegfx reorganization
Diffstat (limited to 'basegfx/source/polygon')
-rw-r--r-- | basegfx/source/polygon/b2dpolygon.cxx | 1041 | ||||
-rw-r--r-- | basegfx/source/polygon/b2dpolygontools.cxx | 141 | ||||
-rw-r--r-- | basegfx/source/polygon/b2dpolypolygon.cxx | 355 | ||||
-rw-r--r-- | basegfx/source/polygon/makefile.mk | 84 |
4 files changed, 1621 insertions, 0 deletions
diff --git a/basegfx/source/polygon/b2dpolygon.cxx b/basegfx/source/polygon/b2dpolygon.cxx new file mode 100644 index 000000000000..37d795359e0f --- /dev/null +++ b/basegfx/source/polygon/b2dpolygon.cxx @@ -0,0 +1,1041 @@ +/************************************************************************* + * + * $RCSfile: b2dpolygon.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2003-10-28 11:23:54 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX +#include <basegfx/inc/polygon/b2dpolygon.hxx> +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#ifndef _BGFX_POINT_B2DPOINT_HXX +#include <basegfx/inc/point/b2dpoint.hxx> +#endif + +#ifndef _BGFX_VECTOR_B2DVECTOR_HXX +#include <basegfx/inc/vector/b2dvector.hxx> +#endif + +#include <vector> +#include <algorithm> + +////////////////////////////////////////////////////////////////////////////// + +class CoordinateData2D +{ + basegfx::point::B2DPoint maPoint; + +public: + CoordinateData2D() {} + CoordinateData2D(const basegfx::point::B2DPoint& rData) : maPoint(rData) {} + ~CoordinateData2D() {} + + const basegfx::point::B2DPoint& getCoordinate() const { return maPoint; } + void setCoordinate(const basegfx::point::B2DPoint& rValue) { if(rValue != maPoint) maPoint = rValue; } + sal_Bool operator==(const CoordinateData2D& rData ) const { return (maPoint == rData.getCoordinate()); } +}; + +////////////////////////////////////////////////////////////////////////////// + +class CoordinateDataArray2D +{ + typedef ::std::vector< CoordinateData2D > CoordinateData2DVector; + + CoordinateData2DVector maVector; + +public: + CoordinateDataArray2D(sal_uInt32 nCount) + : maVector(nCount) + { + } + + CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal) + : maVector(rOriginal.maVector) + { + } + + CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) + : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount)) + { + } + + sal_uInt32 count() const + { + return maVector.size(); + } + + sal_Bool isEqual(const CoordinateDataArray2D& rCandidate) const + { + return (maVector == rCandidate.maVector); + } + + const basegfx::vector::B2DVector& getCoordinate(sal_uInt32 nIndex) const + { + return maVector[nIndex].getCoordinate(); + } + + void setCoordinate(sal_uInt32 nIndex, const basegfx::vector::B2DVector& rValue) + { + maVector[nIndex].setCoordinate(rValue); + } + + void insert(sal_uInt32 nIndex, const CoordinateData2D& rValue, sal_uInt32 nCount) + { + if(nCount) + { + // add nCount copies of rValue + CoordinateData2DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + maVector.insert(aIndex, nCount, rValue); + } + } + + void insert(sal_uInt32 nIndex, const CoordinateDataArray2D& rSource) + { + const sal_uInt32 nCount(rSource.maVector.size()); + + if(nCount) + { + // insert data + CoordinateData2DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + CoordinateData2DVector::const_iterator aStart(rSource.maVector.begin()); + CoordinateData2DVector::const_iterator aEnd(rSource.maVector.end()); + maVector.insert(aIndex, aStart, aEnd); + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + // remove point data + CoordinateData2DVector::iterator aStart(maVector.begin()); + aStart += nIndex; + const CoordinateData2DVector::iterator aEnd(aStart + nCount); + maVector.erase(aStart, aEnd); + } + } + + void flip() + { + if(maVector.size() > 1) + { + const sal_uInt32 nHalfSize(maVector.size() >> 1L); + CoordinateData2DVector::iterator aStart(maVector.begin()); + CoordinateData2DVector::iterator aEnd(maVector.end()); + + for(sal_uInt32 a(0); a < nHalfSize; a++) + { + ::std::swap(*aStart, *aEnd); + aStart++; + aEnd--; + } + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +class ControlVectorPair2D +{ + basegfx::vector::B2DVector maVectorA; + basegfx::vector::B2DVector maVectorB; + +public: + ControlVectorPair2D() {} + ~ControlVectorPair2D() {} + + const basegfx::vector::B2DVector& getVectorA() const { return maVectorA; } + void setVectorA(const basegfx::vector::B2DVector& rValue) { if(rValue != maVectorA) maVectorA = rValue; } + + const basegfx::vector::B2DVector& getVectorB() const { return maVectorB; } + void setVectorB(const basegfx::vector::B2DVector& rValue) { if(rValue != maVectorB) maVectorB = rValue; } + + sal_Bool operator==(const ControlVectorPair2D& rData ) const + { return (maVectorA == rData.getVectorA() && maVectorB == rData.getVectorB()); } +}; + +////////////////////////////////////////////////////////////////////////////// + +class ControlVectorArray2D +{ + typedef ::std::vector< ControlVectorPair2D > ControlVectorPair2DVector; + + ControlVectorPair2DVector maVector; + sal_uInt32 mnUsedVectors; + +public: + ControlVectorArray2D(sal_uInt32 nCount) + : maVector(nCount), + mnUsedVectors(0L) + { + } + + ControlVectorArray2D(const ControlVectorArray2D& rOriginal) + : maVector(rOriginal.maVector), + mnUsedVectors(rOriginal.mnUsedVectors) + { + } + + ControlVectorArray2D(const ControlVectorArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount) + : maVector(), + mnUsedVectors(0L) + { + ControlVectorPair2DVector::const_iterator aStart(rOriginal.maVector.begin()); + aStart += nIndex; + ControlVectorPair2DVector::const_iterator aEnd(aStart); + aEnd += nCount; + maVector.reserve(nCount); + + for(; aStart != aEnd; aStart++) + { + if(!aStart->getVectorA().equalZero()) + mnUsedVectors++; + + if(!aStart->getVectorB().equalZero()) + mnUsedVectors++; + + maVector.push_back(*aStart); + } + } + + sal_uInt32 count() const + { + return maVector.size(); + } + + sal_Bool isEqual(const ControlVectorArray2D& rCandidate) const + { + return (maVector == rCandidate.maVector); + } + + sal_Bool isUsed() const + { + return (0L != mnUsedVectors); + } + + const basegfx::vector::B2DVector& getVectorA(sal_uInt32 nIndex) const + { + return maVector[nIndex].getVectorA(); + } + + void setVectorA(sal_uInt32 nIndex, const basegfx::vector::B2DVector& rValue) + { + sal_Bool bWasUsed(mnUsedVectors && !maVector[nIndex].getVectorA().equalZero()); + sal_Bool bIsUsed(!rValue.equalZero()); + + if(bWasUsed) + { + if(bIsUsed) + { + maVector[nIndex].setVectorA(rValue); + } + else + { + maVector[nIndex].setVectorA(basegfx::vector::B2DVector::getEmptyVector()); + mnUsedVectors--; + } + } + else + { + if(bIsUsed) + { + maVector[nIndex].setVectorA(rValue); + mnUsedVectors++; + } + } + } + + const basegfx::vector::B2DVector& getVectorB(sal_uInt32 nIndex) const + { + return maVector[nIndex].getVectorB(); + } + + void setVectorB(sal_uInt32 nIndex, const basegfx::vector::B2DVector& rValue) + { + sal_Bool bWasUsed(mnUsedVectors && !maVector[nIndex].getVectorB().equalZero()); + sal_Bool bIsUsed(!rValue.equalZero()); + + if(bWasUsed) + { + if(bIsUsed) + { + maVector[nIndex].setVectorB(rValue); + } + else + { + maVector[nIndex].setVectorB(basegfx::vector::B2DVector::getEmptyVector()); + mnUsedVectors--; + } + } + else + { + if(bIsUsed) + { + maVector[nIndex].setVectorB(rValue); + mnUsedVectors++; + } + } + } + + void insert(sal_uInt32 nIndex, const ControlVectorPair2D& rValue, sal_uInt32 nCount) + { + if(nCount) + { + // add nCount copies of rValue + ControlVectorPair2DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + maVector.insert(aIndex, nCount, rValue); + + if(!rValue.getVectorA().equalZero()) + mnUsedVectors += nCount; + + if(!rValue.getVectorB().equalZero()) + mnUsedVectors += nCount; + } + } + + void insert(sal_uInt32 nIndex, const ControlVectorArray2D& rSource) + { + const sal_uInt32 nCount(rSource.maVector.size()); + + if(nCount) + { + // insert data + ControlVectorPair2DVector::iterator aIndex(maVector.begin()); + aIndex += nIndex; + ControlVectorPair2DVector::const_iterator aStart(rSource.maVector.begin()); + ControlVectorPair2DVector::const_iterator aEnd(rSource.maVector.end()); + maVector.insert(aIndex, aStart, aEnd); + + for(; aStart != aEnd; aStart++) + { + if(!aStart->getVectorA().equalZero()) + mnUsedVectors++; + + if(!aStart->getVectorB().equalZero()) + mnUsedVectors++; + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + const ControlVectorPair2DVector::iterator aDeleteStart(maVector.begin() + nIndex); + const ControlVectorPair2DVector::iterator aDeleteEnd(aDeleteStart + nCount); + ControlVectorPair2DVector::const_iterator aStart(aDeleteStart); + + for(; mnUsedVectors && aStart != aDeleteEnd; aStart++) + { + if(!aStart->getVectorA().equalZero()) + mnUsedVectors--; + + if(mnUsedVectors && !aStart->getVectorB().equalZero()) + mnUsedVectors--; + } + + // remove point data + maVector.erase(aDeleteStart, aDeleteEnd); + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +class ImplB2DPolygon +{ + // the internal RefCount + sal_uInt32 mnRefCount; + + // The point vector. This vector exists always and defines the + // count of members. + CoordinateDataArray2D maPoints; + + // The control point vectors. This vectors are created on demand + // and may be zero. + ControlVectorArray2D* mpControlVector; + + // bitfield + // flag which decides if this polygon is opened or closed + unsigned mbIsClosed : 1; + +public: + // This constructor is only used from the static identity polygon, thus + // the RefCount is set to 1 to never 'delete' this static incarnation. + ImplB2DPolygon() + : mnRefCount(1), + maPoints(0L), + mpControlVector(0L), + mbIsClosed(sal_False) + { + // complete initialization with defaults + } + + ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied) + : mnRefCount(0), + maPoints(rToBeCopied.maPoints), + mpControlVector(0L), + mbIsClosed(rToBeCopied.mbIsClosed) + { + // complete initialization using copy + if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed()) + { + mpControlVector = new ControlVectorArray2D(*rToBeCopied.mpControlVector); + } + } + + ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount) + : mnRefCount(0), + maPoints(rToBeCopied.maPoints, nIndex, nCount), + mpControlVector(0L), + mbIsClosed(rToBeCopied.mbIsClosed) + { + // complete initialization using partly copy + if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed()) + { + mpControlVector = new ControlVectorArray2D(*rToBeCopied.mpControlVector, nIndex, nCount); + + if(!mpControlVector->isUsed()) + { + delete mpControlVector; + mpControlVector = 0L; + } + } + } + + ~ImplB2DPolygon() + { + if(mpControlVector) + { + delete mpControlVector; + mpControlVector = 0L; + } + } + + const sal_uInt32 getRefCount() const + { + return mnRefCount; + } + + void incRefCount() + { + mnRefCount++; + } + + void decRefCount() + { + mnRefCount--; + } + + sal_uInt32 count() const + { + return maPoints.count(); + } + + sal_Bool isClosed() const + { + return mbIsClosed; + } + + void setClosed(sal_Bool bNew) + { + if(bNew != mbIsClosed) + { + mbIsClosed = bNew; + } + } + + sal_Bool isEqual(const ImplB2DPolygon& rCandidate) const + { + if(mbIsClosed == rCandidate.mbIsClosed) + { + if(maPoints.isEqual(rCandidate.maPoints)) + { + sal_Bool bControlVectorsAreEqual(sal_True); + + if(mpControlVector) + { + if(rCandidate.mpControlVector) + { + bControlVectorsAreEqual = mpControlVector->isEqual(*rCandidate.mpControlVector); + } + else + { + // candidate has no control vector, so it's assumed all unused. + bControlVectorsAreEqual = !mpControlVector->isUsed(); + } + } + else + { + if(rCandidate.mpControlVector) + { + // we have no control vector, so it's assumed all unused. + bControlVectorsAreEqual = !rCandidate.mpControlVector->isUsed(); + } + } + + if(bControlVectorsAreEqual) + { + return sal_True; + } + } + } + + return sal_False; + } + + const basegfx::point::B2DPoint& getPoint(sal_uInt32 nIndex) const + { + return maPoints.getCoordinate(nIndex); + } + + void setPoint(sal_uInt32 nIndex, const basegfx::point::B2DPoint& rValue) + { + maPoints.setCoordinate(nIndex, rValue); + } + + void insert(sal_uInt32 nIndex, const basegfx::point::B2DPoint& rPoint, sal_uInt32 nCount) + { + if(nCount) + { + CoordinateData2D aCoordinate(rPoint); + maPoints.insert(nIndex, aCoordinate, nCount); + + if(mpControlVector) + { + ControlVectorPair2D aVectorPair; + mpControlVector->insert(nIndex, aVectorPair, nCount); + } + } + } + + const basegfx::point::B2DPoint& getControlPointA(sal_uInt32 nIndex) const + { + if(mpControlVector) + { + return mpControlVector->getVectorA(nIndex); + } + else + { + return basegfx::point::B2DPoint::getEmptyPoint(); + } + } + + void setControlPointA(sal_uInt32 nIndex, const basegfx::point::B2DPoint& rValue) + { + if(!mpControlVector) + { + if(!rValue.equalZero()) + { + mpControlVector = new ControlVectorArray2D(maPoints.count()); + mpControlVector->setVectorA(nIndex, rValue); + } + } + else + { + mpControlVector->setVectorA(nIndex, rValue); + + if(!mpControlVector->isUsed()) + { + delete mpControlVector; + mpControlVector = 0L; + } + } + } + + sal_Bool areControlPointsUsed() const + { + return (mpControlVector && mpControlVector->isUsed()); + } + + const basegfx::point::B2DPoint& getControlPointB(sal_uInt32 nIndex) const + { + if(mpControlVector) + { + return mpControlVector->getVectorB(nIndex); + } + else + { + return basegfx::point::B2DPoint::getEmptyPoint(); + } + } + + void setControlPointB(sal_uInt32 nIndex, const basegfx::point::B2DPoint& rValue) + { + if(!mpControlVector) + { + if(!rValue.equalZero()) + { + mpControlVector = new ControlVectorArray2D(maPoints.count()); + mpControlVector->setVectorB(nIndex, rValue); + } + } + else + { + mpControlVector->setVectorB(nIndex, rValue); + + if(!mpControlVector->isUsed()) + { + delete mpControlVector; + mpControlVector = 0L; + } + } + } + + void insert(sal_uInt32 nIndex, const ImplB2DPolygon& rSource) + { + const sal_uInt32 nCount(rSource.maPoints.count()); + + if(nCount) + { + if(rSource.mpControlVector && rSource.mpControlVector->isUsed() && !mpControlVector) + { + mpControlVector = new ControlVectorArray2D(maPoints.count()); + } + + maPoints.insert(nIndex, rSource.maPoints); + + if(rSource.mpControlVector) + { + mpControlVector->insert(nIndex, *rSource.mpControlVector); + + if(!mpControlVector->isUsed()) + { + delete mpControlVector; + mpControlVector = 0L; + } + } + else if(mpControlVector) + { + ControlVectorPair2D aVectorPair; + mpControlVector->insert(nIndex, aVectorPair, nCount); + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + maPoints.remove(nIndex, nCount); + + if(mpControlVector) + { + mpControlVector->remove(nIndex, nCount); + + if(!mpControlVector->isUsed()) + { + delete mpControlVector; + mpControlVector = 0L; + } + } + } + } + + void flip() + { + if(maPoints.count() > 1) + { + if(mpControlVector) + { + // Here, the vectors need to be completely flipped. The new vectors + // rely on the predecessor point and A,B need to be flipped. The last + // vectors need to be moved to first, too. It is also necessary to + // copy the points (of courcse, just to not forget). + const sal_uInt32 nCount(maPoints.count()); + + // create copies to have access to source data + CoordinateDataArray2D* pCoordinateCopy = new CoordinateDataArray2D(maPoints); + ControlVectorArray2D* pVectorCopy = new ControlVectorArray2D(*mpControlVector); + + // newly fill the local point and vector data + for(sal_uInt32 a(0L); a < nCount; a++) + { + // get index for source point + const sal_uInt32 nCoorSource(nCount - (a + 1)); + + // get index for predecessor point + const sal_uInt32 nVectorSource(nCoorSource ? nCoorSource - 1L : nCount - 1L); + + // get source data + const basegfx::point::B2DPoint& rSourceCoor = pCoordinateCopy->getCoordinate(nCoorSource); + const basegfx::point::B2DPoint& rVectorSourceCoor = pCoordinateCopy->getCoordinate(nVectorSource); + const basegfx::vector::B2DVector& rVectorSourceA = pVectorCopy->getVectorA(nVectorSource); + const basegfx::vector::B2DVector& rVectorSourceB = pVectorCopy->getVectorB(nVectorSource); + + // copy point data + maPoints.setCoordinate(a, rSourceCoor); + + // copy vector data A to B + if(rVectorSourceA.equalZero()) + { + // unused, use zero vector + mpControlVector->setVectorB(a, basegfx::vector::B2DVector::getEmptyVector()); + } + else + { + // calculate new vector relative to new point + basegfx::vector::B2DVector aNewVectorB((rVectorSourceA + rVectorSourceCoor) - rSourceCoor); + mpControlVector->setVectorB(a, aNewVectorB); + } + + // copy vector data B to A + if(rVectorSourceB.equalZero()) + { + // unused, use zero vector + mpControlVector->setVectorA(a, basegfx::vector::B2DVector::getEmptyVector()); + } + else + { + // calculate new vector relative to new point + basegfx::vector::B2DVector aNewVectorA((rVectorSourceB + rVectorSourceCoor) - rSourceCoor); + mpControlVector->setVectorA(a, aNewVectorA); + } + } + + // get rid of copied source data + delete pCoordinateCopy; + delete pVectorCopy; + } + else + { + maPoints.flip(); + } + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace polygon + { + // init static default Polygon + static ImplB2DPolygon maStaticDefaultPolygon; + + void B2DPolygon::implForceUniqueCopy() + { + if(mpPolygon->getRefCount()) + { + mpPolygon->decRefCount(); + mpPolygon = new ImplB2DPolygon(*mpPolygon); + } + } + + B2DPolygon::B2DPolygon() + : mpPolygon(&maStaticDefaultPolygon) + { + mpPolygon->incRefCount(); + } + + B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon) + : mpPolygon(rPolygon.mpPolygon) + { + mpPolygon->incRefCount(); + } + + B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount) + : mpPolygon(new ImplB2DPolygon(*rPolygon.mpPolygon, nIndex, nCount)) + { + DBG_ASSERT(nIndex + nCount > rPolygon.mpPolygon->count(), "B2DPolygon constructor outside range (!)"); + } + + B2DPolygon::~B2DPolygon() + { + if(mpPolygon->getRefCount()) + { + mpPolygon->decRefCount(); + } + else + { + delete mpPolygon; + } + } + + B2DPolygon& B2DPolygon::operator=(const B2DPolygon& rPolygon) + { + if(mpPolygon->getRefCount()) + { + mpPolygon->decRefCount(); + } + else + { + delete mpPolygon; + } + + mpPolygon = rPolygon.mpPolygon; + mpPolygon->incRefCount(); + + return *this; + } + + sal_Bool B2DPolygon::operator==(const B2DPolygon& rPolygon) const + { + if(mpPolygon == rPolygon.mpPolygon) + { + return true; + } + + return mpPolygon->isEqual(*(rPolygon.mpPolygon)); + } + + sal_Bool B2DPolygon::operator!=(const B2DPolygon& rPolygon) const + { + if(mpPolygon == rPolygon.mpPolygon) + { + return false; + } + + return !mpPolygon->isEqual(*(rPolygon.mpPolygon)); + } + + sal_uInt32 B2DPolygon::count() const + { + return mpPolygon->count(); + } + + point::B2DPoint B2DPolygon::getB2DPoint(sal_uInt32 nIndex) const + { + DBG_ASSERT(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)"); + + return mpPolygon->getPoint(nIndex); + } + + void B2DPolygon::setB2DPoint(sal_uInt32 nIndex, const point::B2DPoint& rValue) + { + DBG_ASSERT(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)"); + + if(mpPolygon->getPoint(nIndex) != rValue) + { + implForceUniqueCopy(); + mpPolygon->setPoint(nIndex, rValue); + } + } + + void B2DPolygon::insert(sal_uInt32 nIndex, const point::B2DPoint& rPoint, sal_uInt32 nCount) + { + DBG_ASSERT(nIndex <= mpPolygon->count(), "B2DPolygon Insert outside range (!)"); + + if(nCount) + { + implForceUniqueCopy(); + mpPolygon->insert(nIndex, rPoint, nCount); + } + } + + void B2DPolygon::append(const point::B2DPoint& rPoint, sal_uInt32 nCount) + { + if(nCount) + { + implForceUniqueCopy(); + mpPolygon->insert(mpPolygon->count(), rPoint, nCount); + } + } + + point::B2DPoint B2DPolygon::getControlPointA(sal_uInt32 nIndex) const + { + DBG_ASSERT(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)"); + + return mpPolygon->getControlPointA(nIndex); + } + + void B2DPolygon::setControlPointA(sal_uInt32 nIndex, const point::B2DPoint& rValue) + { + DBG_ASSERT(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)"); + + if(mpPolygon->getControlPointA(nIndex) != rValue) + { + implForceUniqueCopy(); + mpPolygon->setControlPointA(nIndex, rValue); + } + } + + point::B2DPoint B2DPolygon::getControlPointB(sal_uInt32 nIndex) const + { + DBG_ASSERT(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)"); + + return mpPolygon->getControlPointB(nIndex); + } + + void B2DPolygon::setControlPointB(sal_uInt32 nIndex, const point::B2DPoint& rValue) + { + DBG_ASSERT(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)"); + + if(mpPolygon->getControlPointB(nIndex) != rValue) + { + implForceUniqueCopy(); + mpPolygon->setControlPointB(nIndex, rValue); + } + } + + sal_Bool B2DPolygon::areControlPointsUsed() const + { + return mpPolygon->areControlPointsUsed(); + } + + void B2DPolygon::insert(sal_uInt32 nIndex, const B2DPolygon& rPoly, sal_uInt32 nIndex2, sal_uInt32 nCount) + { + DBG_ASSERT(nIndex <= mpPolygon->count(), "B2DPolygon Insert outside range (!)"); + + if(rPoly.count()) + { + implForceUniqueCopy(); + + if(!nCount) + { + nCount = rPoly.count(); + } + + if(0L == nIndex2 && nCount == rPoly.count()) + { + mpPolygon->insert(nIndex, *rPoly.mpPolygon); + } + else + { + DBG_ASSERT(nIndex2 + nCount > rPoly.mpPolygon->count(), "B2DPolygon Insert outside range (!)"); + ImplB2DPolygon aTempPoly(*rPoly.mpPolygon, nIndex2, nCount); + mpPolygon->insert(nIndex, aTempPoly); + } + } + } + + void B2DPolygon::append(const B2DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(rPoly.count()) + { + implForceUniqueCopy(); + + if(!nCount) + { + nCount = rPoly.count(); + } + + if(0L == nIndex && nCount == rPoly.count()) + { + mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon); + } + else + { + DBG_ASSERT(nIndex + nCount > rPoly.mpPolygon->count(), "B2DPolygon Append outside range (!)"); + ImplB2DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount); + mpPolygon->insert(mpPolygon->count(), aTempPoly); + } + } + } + + void B2DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + DBG_ASSERT(nIndex + nCount > mpPolygon->count(), "B2DPolygon Remove outside range (!)"); + + if(nCount) + { + implForceUniqueCopy(); + mpPolygon->remove(nIndex, nCount); + } + } + + void B2DPolygon::clear() + { + if(mpPolygon->getRefCount()) + { + mpPolygon->decRefCount(); + } + else + { + delete mpPolygon; + } + + mpPolygon = &maStaticDefaultPolygon; + mpPolygon->incRefCount(); + } + + sal_Bool B2DPolygon::isClosed() const + { + return mpPolygon->isClosed(); + } + + void B2DPolygon::setClosed(sal_Bool bNew) + { + if(mpPolygon->isClosed() != bNew) + { + implForceUniqueCopy(); + mpPolygon->setClosed(bNew); + } + } + + void B2DPolygon::flip() + { + if(mpPolygon->count() > 1) + { + implForceUniqueCopy(); + mpPolygon->flip(); + } + } + } // end of namespace polygon +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/basegfx/source/polygon/b2dpolygontools.cxx b/basegfx/source/polygon/b2dpolygontools.cxx new file mode 100644 index 000000000000..0df233f19bc2 --- /dev/null +++ b/basegfx/source/polygon/b2dpolygontools.cxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * $RCSfile: b2dpolygontools.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2003-10-28 11:23:54 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX +#include <basegfx/inc/polygon/b2dpolygontools.hxx> +#endif + +#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX +#include <basegfx/inc/polygon/b2dpolygon.hxx> +#endif + +#ifndef _BGFX_CURVE_B2DCUBICBEZIER_HXX +#include <basegfx/inc/curve/b2dcubicbezier.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace polygon + { + namespace tools + { + // B2DPolygon tools + void checkClosed(polygon::B2DPolygon& rCandidate) + { + while(rCandidate.count() > 1L) + { + bool bFirstLastPointEqual( + rCandidate.getB2DPoint(0L) == rCandidate.getB2DPoint(rCandidate.count() - 1L)); + + if(bFirstLastPointEqual) + { + rCandidate.setClosed(true); + rCandidate.remove(rCandidate.count() - 1L); + } + } + } + + // Checks if one of the control vectors is used + bool isEdgeBezier(const polygon::B2DPolygon& rPolygon, sal_uInt32 nEdgeIndex) + { + if(rPolygon.areControlPointsUsed()) + { + DBG_ASSERT(nEdgeIndex < rPolygon.count(), "EdgeIndex out of range (!)"); + + if(!rPolygon.getControlPointA(nEdgeIndex).equalZero()) + return true; + + if(!rPolygon.getControlPointB(nEdgeIndex).equalZero()) + return true; + } + + return false; + } + + bool isEdgeTrivialBezier(const polygon::B2DPolygon& rPolygon, sal_uInt32 nEdgeIndex) + { + if(rPolygon.areControlPointsUsed()) + { + DBG_ASSERT(nEdgeIndex < rPolygon.count(), "EdgeIndex out of range (!)"); + const sal_uInt32 nEndIndex((nEdgeIndex + 1L) % rPolygon.count()); + + curve::B2DCubicBezier aCubicBezier( + rPolygon.getB2DPoint(nEdgeIndex), + rPolygon.getControlPointA(nEdgeIndex), + rPolygon.getControlPointB(nEdgeIndex), + rPolygon.getB2DPoint(nEndIndex)); + + aCubicBezier.testAndSolveTrivialBezier(); + + return !aCubicBezier.isBezier(); + } + + return true; + } + } // end of namespace tools + } // end of namespace polygon +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +// eof diff --git a/basegfx/source/polygon/b2dpolypolygon.cxx b/basegfx/source/polygon/b2dpolypolygon.cxx new file mode 100644 index 000000000000..556a5006948c --- /dev/null +++ b/basegfx/source/polygon/b2dpolypolygon.cxx @@ -0,0 +1,355 @@ +/************************************************************************* + * + * $RCSfile: b2dpolypolygon.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2003-10-28 11:23:55 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX +#include <basegfx/inc/polygon/b2dpolypolygon.hxx> +#endif + +#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX +#include <basegfx/inc/polygon/b2dpolygon.hxx> +#endif + +#ifndef _TOOLS_DEBUG_HXX +#include <tools/debug.hxx> +#endif + +#include <vector> + +////////////////////////////////////////////////////////////////////////////// + +class ImplB2DPolyPolygon +{ + typedef ::std::vector< basegfx::polygon::B2DPolygon > PolygonVector; + + PolygonVector maPolygons; + sal_uInt32 mnRefCount; + +public: + // This constructor is only used from the static identity polygon, thus + // the RefCount is set to 1 to never 'delete' this static incarnation. + ImplB2DPolyPolygon() + : mnRefCount(1) + { + // complete initialization with defaults + } + + ImplB2DPolyPolygon(const ImplB2DPolyPolygon& rToBeCopied) + : mnRefCount(0) + { + // complete initialization using copy + maPolygons = rToBeCopied.maPolygons; + } + + ~ImplB2DPolyPolygon() + { + } + + const sal_uInt32 getRefCount() const { return mnRefCount; } + void incRefCount() { mnRefCount++; } + void decRefCount() { mnRefCount--; } + + bool isEqual(const ImplB2DPolyPolygon& rPolygonList) const + { + // same polygon count? + if(maPolygons.size() != rPolygonList.maPolygons.size()) + return false; + + // if zero polygons the polys are equal + if(!maPolygons.size()) + return true; + + // compare polygon content + if(maPolygons != rPolygonList.maPolygons) + return false; + + return true; + } + + const basegfx::polygon::B2DPolygon& getPolygon(sal_uInt32 nIndex) const + { + return maPolygons[nIndex]; + } + + void setPolygon(sal_uInt32 nIndex, const basegfx::polygon::B2DPolygon& rPolygon) + { + maPolygons[nIndex] = rPolygon; + } + + void insert(sal_uInt32 nIndex, const basegfx::polygon::B2DPolygon& rPolygon, sal_uInt32 nCount) + { + if(nCount) + { + // add nCount copies of rPolygon + PolygonVector::iterator aIndex(maPolygons.begin()); + aIndex += nIndex; + maPolygons.insert(aIndex, nCount, rPolygon); + } + } + + void insert(sal_uInt32 nIndex, const basegfx::polygon::B2DPolyPolygon& rPolyPolygon) + { + const sal_uInt32 nCount = rPolyPolygon.count(); + + if(nCount) + { + // add nCount polygons from rPolyPolygon + maPolygons.reserve(maPolygons.size() + nCount); + PolygonVector::iterator aIndex(maPolygons.begin()); + aIndex += nIndex; + + for(sal_uInt32 a(0L); a < nCount; a++) + { + maPolygons.insert(aIndex, rPolyPolygon.getPolygon(a)); + aIndex++; + } + } + } + + void remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + if(nCount) + { + // remove polygon data + PolygonVector::iterator aStart(maPolygons.begin()); + aStart += nIndex; + const PolygonVector::iterator aEnd(aStart + nCount); + + maPolygons.erase(aStart, aEnd); + } + } + + sal_uInt32 count() const + { + return maPolygons.size(); + } +}; + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace polygon + { + // init static default Polygon + static ImplB2DPolyPolygon maStaticDefaultPolyPolygon; + + void B2DPolyPolygon::implForceUniqueCopy() + { + if(mpPolyPolygon->getRefCount()) + { + mpPolyPolygon->decRefCount(); + mpPolyPolygon = new ImplB2DPolyPolygon(*mpPolyPolygon); + } + } + + B2DPolyPolygon::B2DPolyPolygon() + : mpPolyPolygon(&maStaticDefaultPolyPolygon) + { + mpPolyPolygon->incRefCount(); + } + + B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon) + : mpPolyPolygon(rPolyPolygon.mpPolyPolygon) + { + mpPolyPolygon->incRefCount(); + } + + B2DPolyPolygon::~B2DPolyPolygon() + { + if(mpPolyPolygon->getRefCount()) + { + mpPolyPolygon->decRefCount(); + } + else + { + delete mpPolyPolygon; + } + } + + B2DPolyPolygon& B2DPolyPolygon::operator=(const B2DPolyPolygon& rPolyPolygon) + { + if(mpPolyPolygon->getRefCount()) + { + mpPolyPolygon->decRefCount(); + } + else + { + delete mpPolyPolygon; + } + + mpPolyPolygon = rPolyPolygon.mpPolyPolygon; + mpPolyPolygon->incRefCount(); + + return *this; + } + + bool B2DPolyPolygon::operator==(const B2DPolyPolygon& rPolyPolygon) const + { + if(mpPolyPolygon == rPolyPolygon.mpPolyPolygon) + { + return true; + } + + return mpPolyPolygon->isEqual(*(rPolyPolygon.mpPolyPolygon)); + } + + bool B2DPolyPolygon::operator!=(const B2DPolyPolygon& rPolyPolygon) const + { + if(mpPolyPolygon == rPolyPolygon.mpPolyPolygon) + { + return false; + } + + return !mpPolyPolygon->isEqual(*(rPolyPolygon.mpPolyPolygon)); + } + + sal_uInt32 B2DPolyPolygon::count() const + { + return mpPolyPolygon->count(); + } + + B2DPolygon B2DPolyPolygon::getPolygon(sal_uInt32 nIndex) const + { + DBG_ASSERT(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)"); + + return mpPolyPolygon->getPolygon(nIndex); + } + + void B2DPolyPolygon::setPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon) + { + DBG_ASSERT(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)"); + + if(mpPolyPolygon->getPolygon(nIndex) != rPolygon) + { + implForceUniqueCopy(); + mpPolyPolygon->setPolygon(nIndex, rPolygon); + } + } + + void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolygon& rPolygon, sal_uInt32 nCount) + { + DBG_ASSERT(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)"); + + if(nCount) + { + implForceUniqueCopy(); + mpPolyPolygon->insert(nIndex, rPolygon, nCount); + } + } + + void B2DPolyPolygon::append(const B2DPolygon& rPolygon, sal_uInt32 nCount) + { + if(nCount) + { + implForceUniqueCopy(); + mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount); + } + } + + void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon) + { + DBG_ASSERT(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)"); + + if(rPolyPolygon.count()) + { + implForceUniqueCopy(); + mpPolyPolygon->insert(nIndex, rPolyPolygon); + } + } + + void B2DPolyPolygon::append(const B2DPolyPolygon& rPolyPolygon) + { + if(rPolyPolygon.count()) + { + implForceUniqueCopy(); + mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon); + } + } + + void B2DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount) + { + DBG_ASSERT(nIndex + nCount > mpPolyPolygon->count(), "B2DPolyPolygon Remove outside range (!)"); + + if(nCount) + { + implForceUniqueCopy(); + mpPolyPolygon->remove(nIndex, nCount); + } + } + + void B2DPolyPolygon::clear() + { + if(mpPolyPolygon->getRefCount()) + { + mpPolyPolygon->decRefCount(); + } + else + { + delete mpPolyPolygon; + } + + mpPolyPolygon = &maStaticDefaultPolyPolygon; + mpPolyPolygon->incRefCount(); + } + } // end of namespace polygon +} // end of namespace basegfx + +// eof diff --git a/basegfx/source/polygon/makefile.mk b/basegfx/source/polygon/makefile.mk new file mode 100644 index 000000000000..6d2921a7155f --- /dev/null +++ b/basegfx/source/polygon/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1 $ +# +# last change: $Author: aw $ $Date: 2003-10-28 11:23:55 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source License Version 1.1 (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.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=basegfx +TARGET=polygon + +#UNOUCRRDB=$(SOLARBINDIR)$/applicat.rdb +#ENABLE_EXCEPTIONS=FALSE +#USE_DEFFILE=TRUE + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/b2dpolygon.obj \ + $(SLO)$/b2dpolygontools.obj \ + $(SLO)$/b2dpolypolygon.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk |