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_svx.hxx" 30 31 #include <basegfx/polygon/b2dpolygon.hxx> 32 #include <basegfx/polygon/b2dpolygontools.hxx> 33 34 #include "svx/polypolygoneditor.hxx" 35 36 namespace sdr { 37 38 PolyPolygonEditor::PolyPolygonEditor( const basegfx::B2DPolyPolygon& rPolyPolygon, bool bClosed ) 39 : maPolyPolygon( rPolyPolygon ) 40 , mbIsClosed( bClosed ) 41 { 42 } 43 44 bool PolyPolygonEditor::DeletePoints( const std::set< sal_uInt16 >& rAbsPoints ) 45 { 46 bool bPolyPolyChanged = false; 47 48 std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() ); 49 for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ ) 50 { 51 sal_uInt32 nPoly, nPnt; 52 if( GetRelativePolyPoint(maPolyPolygon,(*aIter), nPoly, nPnt) ) 53 { 54 // remove point 55 basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPoly)); 56 57 aCandidate.remove(nPnt); 58 59 if( ( mbIsClosed && aCandidate.count() < 3L) || (aCandidate.count() < 2L) ) 60 { 61 maPolyPolygon.remove(nPoly); 62 } 63 else 64 { 65 maPolyPolygon.setB2DPolygon(nPoly, aCandidate); 66 } 67 68 bPolyPolyChanged = true; 69 } 70 } 71 72 return bPolyPolyChanged; 73 } 74 75 bool PolyPolygonEditor::SetSegmentsKind(SdrPathSegmentKind eKind, const std::set< sal_uInt16 >& rAbsPoints ) 76 { 77 bool bPolyPolyChanged = false; 78 79 std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() ); 80 for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ ) 81 { 82 sal_uInt32 nPolyNum, nPntNum; 83 84 if(PolyPolygonEditor::GetRelativePolyPoint(maPolyPolygon, (*aIter), nPolyNum, nPntNum)) 85 { 86 // do change at aNewPolyPolygon. Take a look at edge. 87 basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPolyNum)); 88 bool bCandidateChanged(false); 89 const sal_uInt32 nCount(aCandidate.count()); 90 91 if(nCount && (nPntNum + 1 < nCount || aCandidate.isClosed())) 92 { 93 // it's a valid edge, check control point usage 94 const sal_uInt32 nNextIndex((nPntNum + 1) % nCount); 95 const bool bContolUsed(aCandidate.areControlPointsUsed() 96 && (aCandidate.isNextControlPointUsed(nPntNum) || aCandidate.isPrevControlPointUsed(nNextIndex))); 97 98 if(bContolUsed) 99 { 100 if(SDRPATHSEGMENT_TOGGLE == eKind || SDRPATHSEGMENT_LINE == eKind) 101 { 102 // remove control 103 aCandidate.resetNextControlPoint(nPntNum); 104 aCandidate.resetPrevControlPoint(nNextIndex); 105 bCandidateChanged = true; 106 } 107 } 108 else 109 { 110 if(SDRPATHSEGMENT_TOGGLE == eKind || SDRPATHSEGMENT_CURVE == eKind) 111 { 112 // add control 113 const basegfx::B2DPoint aStart(aCandidate.getB2DPoint(nPntNum)); 114 const basegfx::B2DPoint aEnd(aCandidate.getB2DPoint(nNextIndex)); 115 116 aCandidate.setNextControlPoint(nPntNum, interpolate(aStart, aEnd, (1.0 / 3.0))); 117 aCandidate.setPrevControlPoint(nNextIndex, interpolate(aStart, aEnd, (2.0 / 3.0))); 118 bCandidateChanged = true; 119 } 120 } 121 122 if(bCandidateChanged) 123 { 124 maPolyPolygon.setB2DPolygon(nPolyNum, aCandidate); 125 bPolyPolyChanged = true; 126 } 127 } 128 } 129 } 130 131 return bPolyPolyChanged; 132 } 133 134 bool PolyPolygonEditor::SetPointsSmooth( basegfx::B2VectorContinuity eFlags, const std::set< sal_uInt16 >& rAbsPoints) 135 { 136 bool bPolyPolygonChanged(false); 137 138 std::set< sal_uInt16 >::const_reverse_iterator aIter;( rAbsPoints.rbegin() ); 139 for( aIter = rAbsPoints.rbegin(); aIter != rAbsPoints.rend(); aIter++ ) 140 { 141 sal_uInt32 nPolyNum, nPntNum; 142 143 if(PolyPolygonEditor::GetRelativePolyPoint(maPolyPolygon, (*aIter), nPolyNum, nPntNum)) 144 { 145 // do change at aNewPolyPolygon... 146 basegfx::B2DPolygon aCandidate(maPolyPolygon.getB2DPolygon(nPolyNum)); 147 148 // set continuity in point, make sure there is a curve 149 bool bPolygonChanged(false); 150 bPolygonChanged = basegfx::tools::expandToCurveInPoint(aCandidate, nPntNum); 151 bPolygonChanged |= basegfx::tools::setContinuityInPoint(aCandidate, nPntNum, eFlags); 152 153 if(bPolygonChanged) 154 { 155 maPolyPolygon.setB2DPolygon(nPolyNum, aCandidate); 156 bPolyPolygonChanged = true; 157 } 158 } 159 } 160 161 return bPolyPolygonChanged; 162 } 163 164 bool PolyPolygonEditor::GetRelativePolyPoint( const basegfx::B2DPolyPolygon& rPoly, sal_uInt32 nAbsPnt, sal_uInt32& rPolyNum, sal_uInt32& rPointNum ) 165 { 166 const sal_uInt32 nPolyCount(rPoly.count()); 167 sal_uInt32 nPolyNum(0L); 168 169 while(nPolyNum < nPolyCount) 170 { 171 const sal_uInt32 nPointCount(rPoly.getB2DPolygon(nPolyNum).count()); 172 173 if(nAbsPnt < nPointCount) 174 { 175 rPolyNum = nPolyNum; 176 rPointNum = nAbsPnt; 177 178 return true; 179 } 180 else 181 { 182 nPolyNum++; 183 nAbsPnt -= nPointCount; 184 } 185 } 186 187 return false; 188 } 189 190 } // end of namespace sdr 191