diff options
Diffstat (limited to 'basegfx/source/curve/b2dbeziertools.cxx')
-rw-r--r-- | basegfx/source/curve/b2dbeziertools.cxx | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/basegfx/source/curve/b2dbeziertools.cxx b/basegfx/source/curve/b2dbeziertools.cxx new file mode 100644 index 000000000000..dd19356af488 --- /dev/null +++ b/basegfx/source/curve/b2dbeziertools.cxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dbeziertools.cxx,v $ + * $Revision: 1.14 $ + * + * 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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basegfx.hxx" +#include <basegfx/curve/b2dbeziertools.hxx> +#include <basegfx/curve/b2dcubicbezier.hxx> +#include <algorithm> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + B2DCubicBezierHelper::B2DCubicBezierHelper(const B2DCubicBezier& rBase, sal_uInt32 nDivisions) + : maLengthArray(), + mnEdgeCount(0) + { + const bool bIsBezier(rBase.isBezier()); + + if(bIsBezier) + { + // check nDivisions; at least one is needed, but also prevent too big values + if(nDivisions < 1) + { + nDivisions = 1; + } + else if(nDivisions > 1000) + { + nDivisions = 1000; + } + + // set nEdgeCount + mnEdgeCount = nDivisions + 1; + + // fill in maLengthArray + maLengthArray.clear(); + maLengthArray.reserve(mnEdgeCount); + B2DPoint aCurrent(rBase.getStartPoint()); + double fLength(0.0); + + for(sal_uInt32 a(1);;) + { + const B2DPoint aNext(rBase.interpolatePoint((double)a / (double)mnEdgeCount)); + const B2DVector aEdge(aNext - aCurrent); + + fLength += aEdge.getLength(); + maLengthArray.push_back(fLength); + + if(++a < mnEdgeCount) + { + aCurrent = aNext; + } + else + { + const B2DPoint aLastNext(rBase.getEndPoint()); + const B2DVector aLastEdge(aLastNext - aNext); + + fLength += aLastEdge.getLength(); + maLengthArray.push_back(fLength); + break; + } + } + } + else + { + maLengthArray.clear(); + maLengthArray.push_back(rBase.getEdgeLength()); + mnEdgeCount = 1; + } + } + + double B2DCubicBezierHelper::distanceToRelative(double fDistance) const + { + if(fDistance <= 0.0) + { + return 0.0; + } + + const double fLength(getLength()); + + if(fTools::moreOrEqual(fDistance, fLength)) + { + return 1.0; + } + + // fDistance is in ]0.0 .. fLength[ + + if(1 == mnEdgeCount) + { + // not a bezier, linear edge + return fDistance / fLength; + } + + // it is a bezier + ::std::vector< double >::const_iterator aIter = ::std::lower_bound(maLengthArray.begin(), maLengthArray.end(), fDistance); + const sal_uInt32 nIndex(aIter - maLengthArray.begin()); + const double fHighBound(maLengthArray[nIndex]); + const double fLowBound(nIndex ? maLengthArray[nIndex - 1] : 0.0); + const double fLinearInterpolatedLength((fDistance - fLowBound) / (fHighBound - fLowBound)); + + return (static_cast< double >(nIndex) + fLinearInterpolatedLength) / static_cast< double >(mnEdgeCount); + } + + double B2DCubicBezierHelper::relativeToDistance(double fRelative) const + { + if(fRelative <= 0.0) + { + return 0.0; + } + + const double fLength(getLength()); + + if(fTools::moreOrEqual(fRelative, 1.0)) + { + return fLength; + } + + // fRelative is in ]0.0 .. 1.0[ + + if(1 == mnEdgeCount) + { + // not a bezier, linear edge + return fRelative * fLength; + } + + // fRelative is in ]0.0 .. 1.0[ + const double fIndex(fRelative * static_cast< double >(mnEdgeCount)); + double fIntIndex; + const double fFractIndex(modf(fIndex, &fIntIndex)); + const sal_uInt32 nIntIndex(static_cast< sal_uInt32 >(fIntIndex)); + const double fStartDistance(nIntIndex ? maLengthArray[nIntIndex - 1] : 0.0); + + return fStartDistance + ((maLengthArray[nIntIndex] - fStartDistance) * fFractIndex); + } +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +// eof |