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