109dbbe93SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 309dbbe93SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 409dbbe93SAndrew Rist * or more contributor license agreements. See the NOTICE file 509dbbe93SAndrew Rist * distributed with this work for additional information 609dbbe93SAndrew Rist * regarding copyright ownership. The ASF licenses this file 709dbbe93SAndrew Rist * to you under the Apache License, Version 2.0 (the 809dbbe93SAndrew Rist * "License"); you may not use this file except in compliance 909dbbe93SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 1109dbbe93SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 1309dbbe93SAndrew Rist * Unless required by applicable law or agreed to in writing, 1409dbbe93SAndrew Rist * software distributed under the License is distributed on an 1509dbbe93SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1609dbbe93SAndrew Rist * KIND, either express or implied. See the License for the 1709dbbe93SAndrew Rist * specific language governing permissions and limitations 1809dbbe93SAndrew Rist * under the License. 19cdf0e10cSrcweir * 2009dbbe93SAndrew Rist *************************************************************/ 2109dbbe93SAndrew Rist 22cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 23cdf0e10cSrcweir #include "precompiled_basegfx.hxx" 24cdf0e10cSrcweir #include <basegfx/curve/b2dbeziertools.hxx> 25cdf0e10cSrcweir #include <basegfx/curve/b2dcubicbezier.hxx> 26cdf0e10cSrcweir #include <algorithm> 27cdf0e10cSrcweir 28cdf0e10cSrcweir namespace basegfx 29cdf0e10cSrcweir { B2DCubicBezierHelper(const B2DCubicBezier & rBase,sal_uInt32 nDivisions)30cdf0e10cSrcweir B2DCubicBezierHelper::B2DCubicBezierHelper(const B2DCubicBezier& rBase, sal_uInt32 nDivisions) 31cdf0e10cSrcweir : maLengthArray(), 32cdf0e10cSrcweir mnEdgeCount(0) 33cdf0e10cSrcweir { 34cdf0e10cSrcweir const bool bIsBezier(rBase.isBezier()); 35cdf0e10cSrcweir 36cdf0e10cSrcweir if(bIsBezier) 37cdf0e10cSrcweir { 38cdf0e10cSrcweir // check nDivisions; at least one is needed, but also prevent too big values 39cdf0e10cSrcweir if(nDivisions < 1) 40cdf0e10cSrcweir { 41cdf0e10cSrcweir nDivisions = 1; 42cdf0e10cSrcweir } 43cdf0e10cSrcweir else if(nDivisions > 1000) 44cdf0e10cSrcweir { 45cdf0e10cSrcweir nDivisions = 1000; 46cdf0e10cSrcweir } 47cdf0e10cSrcweir 48cdf0e10cSrcweir // set nEdgeCount 49cdf0e10cSrcweir mnEdgeCount = nDivisions + 1; 50cdf0e10cSrcweir 51cdf0e10cSrcweir // fill in maLengthArray 52cdf0e10cSrcweir maLengthArray.clear(); 53cdf0e10cSrcweir maLengthArray.reserve(mnEdgeCount); 54cdf0e10cSrcweir B2DPoint aCurrent(rBase.getStartPoint()); 55cdf0e10cSrcweir double fLength(0.0); 56cdf0e10cSrcweir 57cdf0e10cSrcweir for(sal_uInt32 a(1);;) 58cdf0e10cSrcweir { 59cdf0e10cSrcweir const B2DPoint aNext(rBase.interpolatePoint((double)a / (double)mnEdgeCount)); 60cdf0e10cSrcweir const B2DVector aEdge(aNext - aCurrent); 61cdf0e10cSrcweir 62cdf0e10cSrcweir fLength += aEdge.getLength(); 63cdf0e10cSrcweir maLengthArray.push_back(fLength); 64cdf0e10cSrcweir 65cdf0e10cSrcweir if(++a < mnEdgeCount) 66cdf0e10cSrcweir { 67cdf0e10cSrcweir aCurrent = aNext; 68cdf0e10cSrcweir } 69cdf0e10cSrcweir else 70cdf0e10cSrcweir { 71cdf0e10cSrcweir const B2DPoint aLastNext(rBase.getEndPoint()); 72cdf0e10cSrcweir const B2DVector aLastEdge(aLastNext - aNext); 73cdf0e10cSrcweir 74cdf0e10cSrcweir fLength += aLastEdge.getLength(); 75cdf0e10cSrcweir maLengthArray.push_back(fLength); 76cdf0e10cSrcweir break; 77cdf0e10cSrcweir } 78cdf0e10cSrcweir } 79cdf0e10cSrcweir } 80cdf0e10cSrcweir else 81cdf0e10cSrcweir { 82cdf0e10cSrcweir maLengthArray.clear(); 83cdf0e10cSrcweir maLengthArray.push_back(rBase.getEdgeLength()); 84cdf0e10cSrcweir mnEdgeCount = 1; 85cdf0e10cSrcweir } 86cdf0e10cSrcweir } 87cdf0e10cSrcweir distanceToRelative(double fDistance) const88cdf0e10cSrcweir double B2DCubicBezierHelper::distanceToRelative(double fDistance) const 89cdf0e10cSrcweir { 90cdf0e10cSrcweir if(fDistance <= 0.0) 91cdf0e10cSrcweir { 92cdf0e10cSrcweir return 0.0; 93cdf0e10cSrcweir } 94cdf0e10cSrcweir 95cdf0e10cSrcweir const double fLength(getLength()); 96cdf0e10cSrcweir 97cdf0e10cSrcweir if(fTools::moreOrEqual(fDistance, fLength)) 98cdf0e10cSrcweir { 99cdf0e10cSrcweir return 1.0; 100cdf0e10cSrcweir } 101cdf0e10cSrcweir 102cdf0e10cSrcweir // fDistance is in ]0.0 .. fLength[ 103cdf0e10cSrcweir 104cdf0e10cSrcweir if(1 == mnEdgeCount) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir // not a bezier, linear edge 107cdf0e10cSrcweir return fDistance / fLength; 108cdf0e10cSrcweir } 109cdf0e10cSrcweir 110cdf0e10cSrcweir // it is a bezier 111cdf0e10cSrcweir ::std::vector< double >::const_iterator aIter = ::std::lower_bound(maLengthArray.begin(), maLengthArray.end(), fDistance); 112cdf0e10cSrcweir const sal_uInt32 nIndex(aIter - maLengthArray.begin()); 113cdf0e10cSrcweir const double fHighBound(maLengthArray[nIndex]); 114cdf0e10cSrcweir const double fLowBound(nIndex ? maLengthArray[nIndex - 1] : 0.0); 115cdf0e10cSrcweir const double fLinearInterpolatedLength((fDistance - fLowBound) / (fHighBound - fLowBound)); 116cdf0e10cSrcweir 117cdf0e10cSrcweir return (static_cast< double >(nIndex) + fLinearInterpolatedLength) / static_cast< double >(mnEdgeCount); 118cdf0e10cSrcweir } 119cdf0e10cSrcweir relativeToDistance(double fRelative) const120cdf0e10cSrcweir double B2DCubicBezierHelper::relativeToDistance(double fRelative) const 121cdf0e10cSrcweir { 122cdf0e10cSrcweir if(fRelative <= 0.0) 123cdf0e10cSrcweir { 124cdf0e10cSrcweir return 0.0; 125cdf0e10cSrcweir } 126cdf0e10cSrcweir 127cdf0e10cSrcweir const double fLength(getLength()); 128cdf0e10cSrcweir 129cdf0e10cSrcweir if(fTools::moreOrEqual(fRelative, 1.0)) 130cdf0e10cSrcweir { 131cdf0e10cSrcweir return fLength; 132cdf0e10cSrcweir } 133cdf0e10cSrcweir 134cdf0e10cSrcweir // fRelative is in ]0.0 .. 1.0[ 135cdf0e10cSrcweir 136cdf0e10cSrcweir if(1 == mnEdgeCount) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir // not a bezier, linear edge 139cdf0e10cSrcweir return fRelative * fLength; 140cdf0e10cSrcweir } 141cdf0e10cSrcweir 142cdf0e10cSrcweir // fRelative is in ]0.0 .. 1.0[ 143cdf0e10cSrcweir const double fIndex(fRelative * static_cast< double >(mnEdgeCount)); 144cdf0e10cSrcweir double fIntIndex; 145cdf0e10cSrcweir const double fFractIndex(modf(fIndex, &fIntIndex)); 146cdf0e10cSrcweir const sal_uInt32 nIntIndex(static_cast< sal_uInt32 >(fIntIndex)); 147cdf0e10cSrcweir const double fStartDistance(nIntIndex ? maLengthArray[nIntIndex - 1] : 0.0); 148cdf0e10cSrcweir 149cdf0e10cSrcweir return fStartDistance + ((maLengthArray[nIntIndex] - fStartDistance) * fFractIndex); 150cdf0e10cSrcweir } 151cdf0e10cSrcweir } // end of namespace basegfx 152cdf0e10cSrcweir 153*42fb6e95Smseidel /* vim: set noet sw=4 ts=4: */ 154