merge the formfield patch from ooo-build
[ooovba.git] / basegfx / source / range / b2dmultirange.cxx
blob738c5d149147d917818d2504204c2975cda9f742
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: b2dmultirange.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basegfx.hxx"
33 #include <basegfx/range/b2drange.hxx>
34 #include <basegfx/tuple/b2dtuple.hxx>
35 #include <basegfx/polygon/b2dpolypolygon.hxx>
36 #include <basegfx/range/b2dmultirange.hxx>
37 #include <basegfx/polygon/b2dpolygontools.hxx>
38 #include <basegfx/polygon/b2dpolypolygontools.hxx>
39 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
40 #include <boost/bind.hpp>
41 #include <boost/mem_fn.hpp>
42 #include <algorithm>
43 #include <vector>
46 namespace basegfx
48 class ImplB2DMultiRange
50 public:
51 ImplB2DMultiRange() :
52 maBounds(),
53 maRanges()
57 explicit ImplB2DMultiRange( const B2DRange& rRange ) :
58 maBounds(),
59 maRanges( 1, rRange )
63 bool isEmpty() const
65 // no ranges at all, or all ranges empty
66 return maRanges.empty() ||
67 ::std::count_if( maRanges.begin(),
68 maRanges.end(),
69 ::boost::mem_fn( &B2DRange::isEmpty ) )
70 == static_cast<VectorOfRanges::difference_type>(maRanges.size());
73 void reset()
75 // swap in empty vector
76 VectorOfRanges aTmp;
77 maRanges.swap( aTmp );
79 maBounds.reset();
82 template< typename ValueType > bool isInside( const ValueType& rValue ) const
84 if( !maBounds.isInside( rValue ) )
85 return false;
87 // cannot use ::boost::bind here, since isInside is overloaded.
88 // It is currently not possible to resolve the overload
89 // by considering one of the other template arguments.
90 VectorOfRanges::const_iterator aCurr( maRanges.begin() );
91 const VectorOfRanges::const_iterator aEnd ( maRanges.end() );
92 while( aCurr != aEnd )
93 if( aCurr->isInside( rValue ) )
94 return true;
96 return false;
99 bool overlaps( const B2DRange& rRange ) const
101 if( !maBounds.overlaps( rRange ) )
102 return false;
104 const VectorOfRanges::const_iterator aEnd( maRanges.end() );
105 return ::std::find_if( maRanges.begin(),
106 aEnd,
107 ::boost::bind<bool>( ::boost::mem_fn( &B2DRange::overlaps ),
109 rRange ) ) != aEnd;
112 void addRange( const B2DRange& rRange )
114 maRanges.push_back( rRange );
115 maBounds.expand( rRange );
118 B2DRange getBounds() const
120 return maBounds;
123 B2DPolyPolygon getPolyPolygon() const
125 B2DPolyPolygon aRes;
127 // Make range vector unique ( have to avoid duplicate
128 // rectangles. The polygon clipper will return an empty
129 // result in this case).
130 VectorOfRanges aUniqueRanges;
131 aUniqueRanges.reserve( maRanges.size() );
133 VectorOfRanges::const_iterator aCurr( maRanges.begin() );
134 const VectorOfRanges::const_iterator aEnd ( maRanges.end() );
135 while( aCurr != aEnd )
137 // TODO(F3): It's plain wasted resources to apply a
138 // general clipping algorithm to the problem at
139 // hand. Go for a dedicated, scan-line-based approach.
140 VectorOfRanges::const_iterator aCurrScan( aCurr+1 );
141 VectorOfRanges::const_iterator aFound( aEnd );
142 while( aCurrScan != aEnd )
144 if( aCurrScan->equal( *aCurr ) ||
145 aCurrScan->isInside( *aCurr ) )
147 // current probe is equal to aCurr, or
148 // completely contains aCurr. Thus, stop
149 // searching, because aCurr is definitely not
150 // a member of the unique rect list
151 aFound = aCurrScan;
152 break;
155 ++aCurrScan;
158 if( aFound == aEnd )
160 // check whether aCurr is fully contained in one
161 // of the already added rects. If yes, we can skip
162 // it.
163 bool bUnique( true );
164 VectorOfRanges::const_iterator aCurrUnique( aUniqueRanges.begin() );
165 VectorOfRanges::const_iterator aEndUnique ( aUniqueRanges.end() );
166 while( aCurrUnique != aEndUnique )
168 if( aCurrUnique->isInside( *aCurr ) )
170 // fully contained, no need to add
171 bUnique = false;
172 break;
175 ++aCurrUnique;
178 if( bUnique )
179 aUniqueRanges.push_back( *aCurr );
182 ++aCurr;
185 VectorOfRanges::const_iterator aCurrUnique( aUniqueRanges.begin() );
186 const VectorOfRanges::const_iterator aEndUnique ( aUniqueRanges.end() );
187 while( aCurrUnique != aEndUnique )
189 // simply merge all unique parts (OR)
190 aRes.append( tools::createPolygonFromRect( *aCurrUnique++ ) );
193 // remove redundant intersections. Note: since all added
194 // rectangles are positively oriented, this method cannot
195 // generate any holes.
196 aRes = basegfx::tools::solveCrossovers(aRes);
197 aRes = basegfx::tools::stripNeutralPolygons(aRes);
198 aRes = basegfx::tools::stripDispensablePolygons(aRes, false);
200 return aRes;
203 private:
204 typedef ::std::vector< B2DRange > VectorOfRanges;
206 B2DRange maBounds;
207 VectorOfRanges maRanges;
211 // ====================================================================
214 B2DMultiRange::B2DMultiRange() :
215 mpImpl()
219 B2DMultiRange::B2DMultiRange( const B2DRange& rRange ) :
220 mpImpl( ImplB2DMultiRange( rRange ) )
224 B2DMultiRange::~B2DMultiRange()
226 // otherwise, ImplB2DMultiRange would be an incomplete type
229 B2DMultiRange::B2DMultiRange( const B2DMultiRange& rSrc ) :
230 mpImpl( rSrc.mpImpl )
234 B2DMultiRange& B2DMultiRange::operator=( const B2DMultiRange& rSrc )
236 mpImpl = rSrc.mpImpl;
237 return *this;
240 bool B2DMultiRange::isEmpty() const
242 return mpImpl->isEmpty();
245 void B2DMultiRange::reset()
247 mpImpl->reset();
250 bool B2DMultiRange::isInside( const B2DTuple& rTuple ) const
252 return mpImpl->isInside( rTuple );
255 bool B2DMultiRange::isInside( const B2DRange& rRange ) const
257 return mpImpl->isInside( rRange );
260 bool B2DMultiRange::overlaps( const B2DRange& rRange ) const
262 return mpImpl->overlaps( rRange );
265 void B2DMultiRange::addRange( const B2DRange& rRange )
267 mpImpl->addRange( rRange );
270 B2DRange B2DMultiRange::getBounds() const
272 return mpImpl->getBounds();
275 B2DPolyPolygon B2DMultiRange::getPolyPolygon() const
277 return mpImpl->getPolyPolygon();
280 } // end of namespace basegfx
282 // eof