xref: /AOO41X/main/svx/source/svdraw/polypolygoneditor.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <basegfx/polygon/b2dpolygon.hxx>
28 #include <basegfx/polygon/b2dpolygontools.hxx>
29 
30 #include "svx/polypolygoneditor.hxx"
31 
32 namespace sdr {
33 
PolyPolygonEditor(const basegfx::B2DPolyPolygon & rPolyPolygon,bool bClosed)34 PolyPolygonEditor::PolyPolygonEditor( const basegfx::B2DPolyPolygon& rPolyPolygon, bool bClosed )
35 : maPolyPolygon( rPolyPolygon )
36 , mbIsClosed( bClosed )
37 {
38 }
39 
DeletePoints(const std::set<sal_uInt16> & rAbsPoints)40 bool PolyPolygonEditor::DeletePoints( const std::set< sal_uInt16 >& rAbsPoints )
41 {
42     bool bPolyPolyChanged = false;
43 
44     std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() );
45     for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ )
46     {
47         sal_uInt32 nPoly, nPnt;
48         if( GetRelativePolyPoint(maPolyPolygon,(*aIter), nPoly, nPnt) )
49         {
50             // remove point
51             basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPoly));
52 
53             aCandidate.remove(nPnt);
54 
55             if( ( mbIsClosed && aCandidate.count() < 3L) || (aCandidate.count() < 2L) )
56             {
57                 maPolyPolygon.remove(nPoly);
58             }
59             else
60             {
61                 maPolyPolygon.setB2DPolygon(nPoly, aCandidate);
62             }
63 
64             bPolyPolyChanged = true;
65         }
66     }
67 
68     return bPolyPolyChanged;
69 }
70 
SetSegmentsKind(SdrPathSegmentKind eKind,const std::set<sal_uInt16> & rAbsPoints)71 bool PolyPolygonEditor::SetSegmentsKind(SdrPathSegmentKind eKind, const std::set< sal_uInt16 >& rAbsPoints )
72 {
73     bool bPolyPolyChanged = false;
74 
75     std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() );
76     for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ )
77     {
78         sal_uInt32 nPolyNum, nPntNum;
79 
80         if(PolyPolygonEditor::GetRelativePolyPoint(maPolyPolygon, (*aIter), nPolyNum, nPntNum))
81         {
82             // do change at aNewPolyPolygon. Take a look at edge.
83             basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPolyNum));
84             bool bCandidateChanged(false);
85             const sal_uInt32 nCount(aCandidate.count());
86 
87             if(nCount && (nPntNum + 1 < nCount || aCandidate.isClosed()))
88             {
89                 // it's a valid edge, check control point usage
90                 const sal_uInt32 nNextIndex((nPntNum + 1) % nCount);
91                 const bool bContolUsed(aCandidate.areControlPointsUsed()
92                     && (aCandidate.isNextControlPointUsed(nPntNum) || aCandidate.isPrevControlPointUsed(nNextIndex)));
93 
94                 if(bContolUsed)
95                 {
96                     if(SDRPATHSEGMENT_TOGGLE == eKind || SDRPATHSEGMENT_LINE == eKind)
97                     {
98                         // remove control
99                         aCandidate.resetNextControlPoint(nPntNum);
100                         aCandidate.resetPrevControlPoint(nNextIndex);
101                         bCandidateChanged = true;
102                     }
103                 }
104                 else
105                 {
106                     if(SDRPATHSEGMENT_TOGGLE == eKind || SDRPATHSEGMENT_CURVE == eKind)
107                     {
108                         // add control
109                         const basegfx::B2DPoint aStart(aCandidate.getB2DPoint(nPntNum));
110                         const basegfx::B2DPoint aEnd(aCandidate.getB2DPoint(nNextIndex));
111 
112                         aCandidate.setNextControlPoint(nPntNum, interpolate(aStart, aEnd, (1.0 / 3.0)));
113                         aCandidate.setPrevControlPoint(nNextIndex, interpolate(aStart, aEnd, (2.0 / 3.0)));
114                         bCandidateChanged = true;
115                     }
116                 }
117 
118                 if(bCandidateChanged)
119                 {
120                     maPolyPolygon.setB2DPolygon(nPolyNum, aCandidate);
121                     bPolyPolyChanged = true;
122                 }
123             }
124         }
125     }
126 
127     return bPolyPolyChanged;
128 }
129 
SetPointsSmooth(basegfx::B2VectorContinuity eFlags,const std::set<sal_uInt16> & rAbsPoints)130 bool PolyPolygonEditor::SetPointsSmooth( basegfx::B2VectorContinuity eFlags, const std::set< sal_uInt16 >& rAbsPoints)
131 {
132     bool bPolyPolygonChanged(false);
133 
134     std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() );
135     for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ )
136     {
137         sal_uInt32 nPolyNum, nPntNum;
138 
139         if(PolyPolygonEditor::GetRelativePolyPoint(maPolyPolygon, (*aIter), nPolyNum, nPntNum))
140         {
141             // do change at aNewPolyPolygon...
142             basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPolyNum));
143 
144             // set continuity in point, make sure there is a curve
145             bool bPolygonChanged(false);
146             bPolygonChanged = basegfx::tools::expandToCurveInPoint(aCandidate, nPntNum);
147             bPolygonChanged |= basegfx::tools::setContinuityInPoint(aCandidate, nPntNum, eFlags);
148 
149             if(bPolygonChanged)
150             {
151                 maPolyPolygon.setB2DPolygon(nPolyNum, aCandidate);
152                 bPolyPolygonChanged = true;
153             }
154         }
155     }
156 
157     return bPolyPolygonChanged;
158 }
159 
GetRelativePolyPoint(const basegfx::B2DPolyPolygon & rPoly,sal_uInt32 nAbsPnt,sal_uInt32 & rPolyNum,sal_uInt32 & rPointNum)160 bool PolyPolygonEditor::GetRelativePolyPoint( const basegfx::B2DPolyPolygon& rPoly, sal_uInt32 nAbsPnt, sal_uInt32& rPolyNum, sal_uInt32& rPointNum )
161 {
162     const sal_uInt32 nPolyCount(rPoly.count());
163     sal_uInt32 nPolyNum(0L);
164 
165     while(nPolyNum < nPolyCount)
166     {
167         const sal_uInt32 nPointCount(rPoly.getB2DPolygon(nPolyNum).count());
168 
169         if(nAbsPnt < nPointCount)
170         {
171             rPolyNum = nPolyNum;
172             rPointNum = nAbsPnt;
173 
174             return true;
175         }
176         else
177         {
178             nPolyNum++;
179             nAbsPnt -= nPointCount;
180         }
181     }
182 
183     return false;
184 }
185 
186 } // end of namespace sdr
187