Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <basegfx/curve/b2dbeziertools.hxx>
21 : #include <basegfx/curve/b2dcubicbezier.hxx>
22 : #include <algorithm>
23 :
24 : namespace basegfx
25 : {
26 266 : B2DCubicBezierHelper::B2DCubicBezierHelper(const B2DCubicBezier& rBase, sal_uInt32 nDivisions)
27 : : maLengthArray(),
28 266 : mnEdgeCount(0)
29 : {
30 266 : const bool bIsBezier(rBase.isBezier());
31 :
32 266 : if(bIsBezier)
33 : {
34 : // check nDivisions; at least one is needed, but also prevent too big values
35 266 : if(nDivisions < 1)
36 : {
37 0 : nDivisions = 1;
38 : }
39 266 : else if(nDivisions > 1000)
40 : {
41 0 : nDivisions = 1000;
42 : }
43 :
44 : // set nEdgeCount
45 266 : mnEdgeCount = nDivisions + 1;
46 :
47 : // fill in maLengthArray
48 266 : maLengthArray.clear();
49 266 : maLengthArray.reserve(mnEdgeCount);
50 266 : B2DPoint aCurrent(rBase.getStartPoint());
51 266 : double fLength(0.0);
52 :
53 266 : for(sal_uInt32 a(1);;)
54 : {
55 2394 : const B2DPoint aNext(rBase.interpolatePoint((double)a / (double)mnEdgeCount));
56 4522 : const B2DVector aEdge(aNext - aCurrent);
57 :
58 2394 : fLength += aEdge.getLength();
59 2394 : maLengthArray.push_back(fLength);
60 :
61 2394 : if(++a < mnEdgeCount)
62 : {
63 2128 : aCurrent = aNext;
64 : }
65 : else
66 : {
67 266 : const B2DPoint aLastNext(rBase.getEndPoint());
68 532 : const B2DVector aLastEdge(aLastNext - aNext);
69 :
70 266 : fLength += aLastEdge.getLength();
71 266 : maLengthArray.push_back(fLength);
72 532 : break;
73 : }
74 2128 : }
75 : }
76 : else
77 : {
78 0 : maLengthArray.clear();
79 0 : maLengthArray.push_back(rBase.getEdgeLength());
80 0 : mnEdgeCount = 1;
81 : }
82 266 : }
83 :
84 2479 : double B2DCubicBezierHelper::distanceToRelative(double fDistance) const
85 : {
86 2479 : if(fDistance <= 0.0)
87 : {
88 186 : return 0.0;
89 : }
90 :
91 2293 : const double fLength(getLength());
92 :
93 2293 : if(fTools::moreOrEqual(fDistance, fLength))
94 : {
95 0 : return 1.0;
96 : }
97 :
98 : // fDistance is in ]0.0 .. fLength[
99 :
100 2293 : if(1 == mnEdgeCount)
101 : {
102 : // not a bezier, linear edge
103 0 : return fDistance / fLength;
104 : }
105 :
106 : // it is a bezier
107 2293 : ::std::vector< double >::const_iterator aIter = ::std::lower_bound(maLengthArray.begin(), maLengthArray.end(), fDistance);
108 2293 : const sal_uInt32 nIndex(aIter - maLengthArray.begin());
109 2293 : const double fHighBound(maLengthArray[nIndex]);
110 2293 : const double fLowBound(nIndex ? maLengthArray[nIndex - 1] : 0.0);
111 2293 : const double fLinearInterpolatedLength((fDistance - fLowBound) / (fHighBound - fLowBound));
112 :
113 2293 : return (static_cast< double >(nIndex) + fLinearInterpolatedLength) / static_cast< double >(mnEdgeCount);
114 : }
115 :
116 : } // end of namespace basegfx
117 :
118 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|