1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2008 by Sun Microsystems, Inc. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * $RCSfile: b2dmultirange.cxx,v $ 10 * $Revision: 1.8 $ 11 * 12 * This file is part of OpenOffice.org. 13 * 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. 17 * 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). 23 * 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. 28 * 29 ************************************************************************/ 30 31 // MARKER(update_precomp.py): autogen include statement, do not remove 32 #include "precompiled_basegfx.hxx" 33 #include <basegfx/range/b2dpolyrange.hxx> 34 35 #include <basegfx/range/b2drange.hxx> 36 #include <basegfx/range/b2drangeclipper.hxx> 37 #include <basegfx/tuple/b2dtuple.hxx> 38 #include <basegfx/polygon/b2dpolypolygon.hxx> 39 40 #include <boost/bind.hpp> 41 #include <boost/tuple/tuple.hpp> 42 #include <algorithm> 43 #include <vector> 44 45 static basegfx::B2VectorOrientation flipOrientation( 46 basegfx::B2VectorOrientation eOrient) 47 { 48 return eOrient == basegfx::ORIENTATION_POSITIVE ? 49 basegfx::ORIENTATION_NEGATIVE : basegfx::ORIENTATION_POSITIVE; 50 } 51 52 namespace basegfx 53 { 54 class ImplB2DPolyRange 55 { 56 void updateBounds() 57 { 58 maBounds.reset(); 59 std::for_each(maRanges.begin(), 60 maRanges.end(), 61 boost::bind( 62 (void (B2DRange::*)(const B2DRange&))( 63 &B2DRange::expand), 64 boost::ref(maBounds), 65 _1)); 66 } 67 68 public: 69 ImplB2DPolyRange() : 70 maBounds(), 71 maRanges(), 72 maOrient() 73 {} 74 75 explicit ImplB2DPolyRange( const B2DPolyRange::ElementType& rElem ) : 76 maBounds( boost::get<0>(rElem) ), 77 maRanges( 1, boost::get<0>(rElem) ), 78 maOrient( 1, boost::get<1>(rElem) ) 79 {} 80 81 explicit ImplB2DPolyRange( const B2DRange& rRange, B2VectorOrientation eOrient ) : 82 maBounds( rRange ), 83 maRanges( 1, rRange ), 84 maOrient( 1, eOrient ) 85 {} 86 87 bool operator==(const ImplB2DPolyRange& rRHS) const 88 { 89 return maRanges == rRHS.maRanges && maOrient == rRHS.maOrient; 90 } 91 92 sal_uInt32 count() const 93 { 94 return maRanges.size(); 95 } 96 97 B2DPolyRange::ElementType getElement(sal_uInt32 nIndex) const 98 { 99 return boost::make_tuple(maRanges[nIndex], 100 maOrient[nIndex]); 101 } 102 103 void setElement(sal_uInt32 nIndex, const B2DPolyRange::ElementType& rElement ) 104 { 105 maRanges[nIndex] = boost::get<0>(rElement); 106 maOrient[nIndex] = boost::get<1>(rElement); 107 updateBounds(); 108 } 109 110 void setElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient ) 111 { 112 maRanges[nIndex] = rRange; 113 maOrient[nIndex] = eOrient; 114 updateBounds(); 115 } 116 117 void insertElement(sal_uInt32 nIndex, const B2DPolyRange::ElementType& rElement, sal_uInt32 nCount) 118 { 119 maRanges.insert(maRanges.begin()+nIndex, nCount, boost::get<0>(rElement)); 120 maOrient.insert(maOrient.begin()+nIndex, nCount, boost::get<1>(rElement)); 121 maBounds.expand(boost::get<0>(rElement)); 122 } 123 124 void insertElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount) 125 { 126 maRanges.insert(maRanges.begin()+nIndex, nCount, rRange); 127 maOrient.insert(maOrient.begin()+nIndex, nCount, eOrient); 128 maBounds.expand(rRange); 129 } 130 131 void appendElement(const B2DPolyRange::ElementType& rElement, sal_uInt32 nCount) 132 { 133 maRanges.insert(maRanges.end(), nCount, boost::get<0>(rElement)); 134 maOrient.insert(maOrient.end(), nCount, boost::get<1>(rElement)); 135 maBounds.expand(boost::get<0>(rElement)); 136 } 137 138 void appendElement(const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount) 139 { 140 maRanges.insert(maRanges.end(), nCount, rRange); 141 maOrient.insert(maOrient.end(), nCount, eOrient); 142 maBounds.expand(rRange); 143 } 144 145 void insertPolyRange(sal_uInt32 nIndex, const ImplB2DPolyRange& rPolyRange) 146 { 147 maRanges.insert(maRanges.begin()+nIndex, rPolyRange.maRanges.begin(), rPolyRange.maRanges.end()); 148 maOrient.insert(maOrient.begin()+nIndex, rPolyRange.maOrient.begin(), rPolyRange.maOrient.end()); 149 updateBounds(); 150 } 151 152 void appendPolyRange(const ImplB2DPolyRange& rPolyRange) 153 { 154 maRanges.insert(maRanges.end(), 155 rPolyRange.maRanges.begin(), 156 rPolyRange.maRanges.end()); 157 maOrient.insert(maOrient.end(), 158 rPolyRange.maOrient.begin(), 159 rPolyRange.maOrient.end()); 160 updateBounds(); 161 } 162 163 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 164 { 165 maRanges.erase(maRanges.begin()+nIndex,maRanges.begin()+nIndex+nCount); 166 maOrient.erase(maOrient.begin()+nIndex,maOrient.begin()+nIndex+nCount); 167 updateBounds(); 168 } 169 170 void clear() 171 { 172 std::vector<B2DRange> aTmpRanges; 173 std::vector<B2VectorOrientation> aTmpOrient; 174 175 maRanges.swap(aTmpRanges); 176 maOrient.swap(aTmpOrient); 177 178 maBounds.reset(); 179 } 180 181 void flip() 182 { 183 std::for_each(maOrient.begin(), 184 maOrient.end(), 185 boost::bind( 186 &flipOrientation, 187 _1)); 188 } 189 190 B2DRange getBounds() const 191 { 192 return maBounds; 193 } 194 195 template< typename ValueType > bool isInside( const ValueType& rValue ) const 196 { 197 if( !maBounds.isInside( rValue ) ) 198 return false; 199 200 // cannot use boost::bind here, since isInside is overloaded. 201 // It is currently not possible to resolve the overload 202 // by considering one of the other template arguments. 203 std::vector<B2DRange>::const_iterator aCurr( maRanges.begin() ); 204 const std::vector<B2DRange>::const_iterator aEnd ( maRanges.end() ); 205 while( aCurr != aEnd ) 206 if( aCurr->isInside( rValue ) ) 207 return true; 208 209 return false; 210 } 211 212 bool overlaps( const B2DRange& rRange ) const 213 { 214 if( !maBounds.overlaps( rRange ) ) 215 return false; 216 217 const std::vector<B2DRange>::const_iterator aEnd( maRanges.end() ); 218 return std::find_if( maRanges.begin(), 219 aEnd, 220 boost::bind<bool>( boost::mem_fn( &B2DRange::overlaps ), 221 _1, 222 boost::cref(rRange) ) ) != aEnd; 223 } 224 225 B2DPolyPolygon solveCrossovers() const 226 { 227 return tools::solveCrossovers(maRanges,maOrient); 228 } 229 230 const B2DRange* begin() const 231 { 232 if(maRanges.empty()) 233 return 0; 234 else 235 return &maRanges.front(); 236 } 237 238 const B2DRange* end() const 239 { 240 if(maRanges.empty()) 241 return 0; 242 else 243 return (&maRanges.back())+1; 244 } 245 246 B2DRange* begin() 247 { 248 if(maRanges.empty()) 249 return 0; 250 else 251 return &maRanges.front(); 252 } 253 254 B2DRange* end() 255 { 256 if(maRanges.empty()) 257 return 0; 258 else 259 return (&maRanges.back())+1; 260 } 261 262 private: 263 B2DRange maBounds; 264 std::vector<B2DRange> maRanges; 265 std::vector<B2VectorOrientation> maOrient; 266 }; 267 268 B2DPolyRange::B2DPolyRange() : 269 mpImpl() 270 {} 271 272 B2DPolyRange::~B2DPolyRange() 273 {} 274 275 B2DPolyRange::B2DPolyRange( const ElementType& rElem ) : 276 mpImpl( ImplB2DPolyRange( rElem ) ) 277 {} 278 279 B2DPolyRange::B2DPolyRange( const B2DRange& rRange, B2VectorOrientation eOrient ) : 280 mpImpl( ImplB2DPolyRange( rRange, eOrient ) ) 281 {} 282 283 B2DPolyRange::B2DPolyRange( const B2DPolyRange& rRange ) : 284 mpImpl( rRange.mpImpl ) 285 {} 286 287 B2DPolyRange& B2DPolyRange::operator=( const B2DPolyRange& rRange ) 288 { 289 mpImpl = rRange.mpImpl; 290 return *this; 291 } 292 293 void B2DPolyRange::makeUnique() 294 { 295 mpImpl.make_unique(); 296 } 297 298 bool B2DPolyRange::operator==(const B2DPolyRange& rRange) const 299 { 300 if(mpImpl.same_object(rRange.mpImpl)) 301 return true; 302 303 return ((*mpImpl) == (*rRange.mpImpl)); 304 } 305 306 bool B2DPolyRange::operator!=(const B2DPolyRange& rRange) const 307 { 308 return !(*this == rRange); 309 } 310 311 sal_uInt32 B2DPolyRange::count() const 312 { 313 return mpImpl->count(); 314 } 315 316 B2DPolyRange::ElementType B2DPolyRange::getElement(sal_uInt32 nIndex) const 317 { 318 return mpImpl->getElement(nIndex); 319 } 320 321 void B2DPolyRange::setElement(sal_uInt32 nIndex, const ElementType& rElement ) 322 { 323 mpImpl->setElement(nIndex, rElement); 324 } 325 326 void B2DPolyRange::setElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient ) 327 { 328 mpImpl->setElement(nIndex, rRange, eOrient ); 329 } 330 331 void B2DPolyRange::insertElement(sal_uInt32 nIndex, const ElementType& rElement, sal_uInt32 nCount) 332 { 333 mpImpl->insertElement(nIndex, rElement, nCount ); 334 } 335 336 void B2DPolyRange::insertElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount) 337 { 338 mpImpl->insertElement(nIndex, rRange, eOrient, nCount ); 339 } 340 341 void B2DPolyRange::appendElement(const ElementType& rElement, sal_uInt32 nCount) 342 { 343 mpImpl->appendElement(rElement, nCount); 344 } 345 346 void B2DPolyRange::appendElement(const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount) 347 { 348 mpImpl->appendElement(rRange, eOrient, nCount ); 349 } 350 351 void B2DPolyRange::insertPolyRange(sal_uInt32 nIndex, const B2DPolyRange& rRange) 352 { 353 mpImpl->insertPolyRange(nIndex, *rRange.mpImpl); 354 } 355 356 void B2DPolyRange::appendPolyRange(const B2DPolyRange& rRange) 357 { 358 mpImpl->appendPolyRange(*rRange.mpImpl); 359 } 360 361 void B2DPolyRange::remove(sal_uInt32 nIndex, sal_uInt32 nCount) 362 { 363 mpImpl->remove(nIndex, nCount); 364 } 365 366 void B2DPolyRange::clear() 367 { 368 mpImpl->clear(); 369 } 370 371 void B2DPolyRange::flip() 372 { 373 mpImpl->flip(); 374 } 375 376 B2DRange B2DPolyRange::getBounds() const 377 { 378 return mpImpl->getBounds(); 379 } 380 381 bool B2DPolyRange::isInside( const B2DTuple& rTuple ) const 382 { 383 return mpImpl->isInside(rTuple); 384 } 385 386 bool B2DPolyRange::isInside( const B2DRange& rRange ) const 387 { 388 return mpImpl->isInside(rRange); 389 } 390 391 bool B2DPolyRange::overlaps( const B2DRange& rRange ) const 392 { 393 return mpImpl->overlaps(rRange); 394 } 395 396 B2DPolyPolygon B2DPolyRange::solveCrossovers() const 397 { 398 return mpImpl->solveCrossovers(); 399 } 400 401 const B2DRange* B2DPolyRange::begin() const 402 { 403 return mpImpl->begin(); 404 } 405 406 const B2DRange* B2DPolyRange::end() const 407 { 408 return mpImpl->end(); 409 } 410 411 B2DRange* B2DPolyRange::begin() 412 { 413 return mpImpl->begin(); 414 } 415 416 B2DRange* B2DPolyRange::end() 417 { 418 return mpImpl->end(); 419 } 420 421 } // end of namespace basegfx 422 423 // eof 424