1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_basegfx.hxx" 30 #include <basegfx/curve/b2dbeziertools.hxx> 31 #include <basegfx/curve/b2dcubicbezier.hxx> 32 #include <algorithm> 33 34 ////////////////////////////////////////////////////////////////////////////// 35 36 namespace basegfx 37 { 38 B2DCubicBezierHelper::B2DCubicBezierHelper(const B2DCubicBezier& rBase, sal_uInt32 nDivisions) 39 : maLengthArray(), 40 mnEdgeCount(0) 41 { 42 const bool bIsBezier(rBase.isBezier()); 43 44 if(bIsBezier) 45 { 46 // check nDivisions; at least one is needed, but also prevent too big values 47 if(nDivisions < 1) 48 { 49 nDivisions = 1; 50 } 51 else if(nDivisions > 1000) 52 { 53 nDivisions = 1000; 54 } 55 56 // set nEdgeCount 57 mnEdgeCount = nDivisions + 1; 58 59 // fill in maLengthArray 60 maLengthArray.clear(); 61 maLengthArray.reserve(mnEdgeCount); 62 B2DPoint aCurrent(rBase.getStartPoint()); 63 double fLength(0.0); 64 65 for(sal_uInt32 a(1);;) 66 { 67 const B2DPoint aNext(rBase.interpolatePoint((double)a / (double)mnEdgeCount)); 68 const B2DVector aEdge(aNext - aCurrent); 69 70 fLength += aEdge.getLength(); 71 maLengthArray.push_back(fLength); 72 73 if(++a < mnEdgeCount) 74 { 75 aCurrent = aNext; 76 } 77 else 78 { 79 const B2DPoint aLastNext(rBase.getEndPoint()); 80 const B2DVector aLastEdge(aLastNext - aNext); 81 82 fLength += aLastEdge.getLength(); 83 maLengthArray.push_back(fLength); 84 break; 85 } 86 } 87 } 88 else 89 { 90 maLengthArray.clear(); 91 maLengthArray.push_back(rBase.getEdgeLength()); 92 mnEdgeCount = 1; 93 } 94 } 95 96 double B2DCubicBezierHelper::distanceToRelative(double fDistance) const 97 { 98 if(fDistance <= 0.0) 99 { 100 return 0.0; 101 } 102 103 const double fLength(getLength()); 104 105 if(fTools::moreOrEqual(fDistance, fLength)) 106 { 107 return 1.0; 108 } 109 110 // fDistance is in ]0.0 .. fLength[ 111 112 if(1 == mnEdgeCount) 113 { 114 // not a bezier, linear edge 115 return fDistance / fLength; 116 } 117 118 // it is a bezier 119 ::std::vector< double >::const_iterator aIter = ::std::lower_bound(maLengthArray.begin(), maLengthArray.end(), fDistance); 120 const sal_uInt32 nIndex(aIter - maLengthArray.begin()); 121 const double fHighBound(maLengthArray[nIndex]); 122 const double fLowBound(nIndex ? maLengthArray[nIndex - 1] : 0.0); 123 const double fLinearInterpolatedLength((fDistance - fLowBound) / (fHighBound - fLowBound)); 124 125 return (static_cast< double >(nIndex) + fLinearInterpolatedLength) / static_cast< double >(mnEdgeCount); 126 } 127 128 double B2DCubicBezierHelper::relativeToDistance(double fRelative) const 129 { 130 if(fRelative <= 0.0) 131 { 132 return 0.0; 133 } 134 135 const double fLength(getLength()); 136 137 if(fTools::moreOrEqual(fRelative, 1.0)) 138 { 139 return fLength; 140 } 141 142 // fRelative is in ]0.0 .. 1.0[ 143 144 if(1 == mnEdgeCount) 145 { 146 // not a bezier, linear edge 147 return fRelative * fLength; 148 } 149 150 // fRelative is in ]0.0 .. 1.0[ 151 const double fIndex(fRelative * static_cast< double >(mnEdgeCount)); 152 double fIntIndex; 153 const double fFractIndex(modf(fIndex, &fIntIndex)); 154 const sal_uInt32 nIntIndex(static_cast< sal_uInt32 >(fIntIndex)); 155 const double fStartDistance(nIntIndex ? maLengthArray[nIntIndex - 1] : 0.0); 156 157 return fStartDistance + ((maLengthArray[nIntIndex] - fStartDistance) * fFractIndex); 158 } 159 } // end of namespace basegfx 160 161 ////////////////////////////////////////////////////////////////////////////// 162 163 // eof 164