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_basegfx.hxx" 30 #include <basegfx/polygon/b2dpolypolygon.hxx> 31 #include <osl/diagnose.h> 32 #include <basegfx/polygon/b2dpolygon.hxx> 33 #include <basegfx/polygon/b2dpolypolygontools.hxx> 34 #include <rtl/instance.hxx> 35 #include <basegfx/matrix/b2dhommatrix.hxx> 36 37 #include <functional> 38 #include <vector> 39 #include <algorithm> 40 41 ////////////////////////////////////////////////////////////////////////////// 42 43 class ImplB2DPolyPolygon 44 { 45 typedef ::std::vector< basegfx::B2DPolygon > PolygonVector; 46 47 PolygonVector maPolygons; 48 49 public: 50 ImplB2DPolyPolygon() : maPolygons() 51 { 52 } 53 54 ImplB2DPolyPolygon(const basegfx::B2DPolygon& rToBeCopied) : 55 maPolygons(1,rToBeCopied) 56 { 57 } 58 59 bool operator==(const ImplB2DPolyPolygon& rPolygonList) const 60 { 61 // same polygon count? 62 if(maPolygons.size() != rPolygonList.maPolygons.size()) 63 return false; 64 65 // compare polygon content 66 if(!(maPolygons == rPolygonList.maPolygons)) 67 return false; 68 69 return true; 70 } 71 72 const basegfx::B2DPolygon& getB2DPolygon(sal_uInt32 nIndex) const 73 { 74 return maPolygons[nIndex]; 75 } 76 77 void setB2DPolygon(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon) 78 { 79 maPolygons[nIndex] = rPolygon; 80 } 81 82 void insert(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon, sal_uInt32 nCount) 83 { 84 if(nCount) 85 { 86 // add nCount copies of rPolygon 87 PolygonVector::iterator aIndex(maPolygons.begin()); 88 aIndex += nIndex; 89 maPolygons.insert(aIndex, nCount, rPolygon); 90 } 91 } 92 93 void insert(sal_uInt32 nIndex, const basegfx::B2DPolyPolygon& rPolyPolygon) 94 { 95 const sal_uInt32 nCount = rPolyPolygon.count(); 96 97 if(nCount) 98 { 99 // add nCount polygons from rPolyPolygon 100 maPolygons.reserve(maPolygons.size() + nCount); 101 PolygonVector::iterator aIndex(maPolygons.begin()); 102 aIndex += nIndex; 103 104 for(sal_uInt32 a(0L); a < nCount; a++) 105 { 106 aIndex = maPolygons.insert(aIndex, rPolyPolygon.getB2DPolygon(a)); 107 aIndex++; 108 } 109 } 110 } 111 112 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 113 { 114 if(nCount) 115 { 116 // remove polygon data 117 PolygonVector::iterator aStart(maPolygons.begin()); 118 aStart += nIndex; 119 const PolygonVector::iterator aEnd(aStart + nCount); 120 121 maPolygons.erase(aStart, aEnd); 122 } 123 } 124 125 sal_uInt32 count() const 126 { 127 return maPolygons.size(); 128 } 129 130 void setClosed(bool bNew) 131 { 132 for(sal_uInt32 a(0L); a < maPolygons.size(); a++) 133 { 134 maPolygons[a].setClosed(bNew); 135 } 136 } 137 138 void flip() 139 { 140 std::for_each( maPolygons.begin(), 141 maPolygons.end(), 142 std::mem_fun_ref( &basegfx::B2DPolygon::flip )); 143 } 144 145 void removeDoublePoints() 146 { 147 std::for_each( maPolygons.begin(), 148 maPolygons.end(), 149 std::mem_fun_ref( &basegfx::B2DPolygon::removeDoublePoints )); 150 } 151 152 void transform(const basegfx::B2DHomMatrix& rMatrix) 153 { 154 for(sal_uInt32 a(0L); a < maPolygons.size(); a++) 155 { 156 maPolygons[a].transform(rMatrix); 157 } 158 } 159 160 void makeUnique() 161 { 162 std::for_each( maPolygons.begin(), 163 maPolygons.end(), 164 std::mem_fun_ref( &basegfx::B2DPolygon::makeUnique )); 165 } 166 167 const basegfx::B2DPolygon* begin() const 168 { 169 if(maPolygons.empty()) 170 return 0; 171 else 172 return &maPolygons.front(); 173 } 174 175 const basegfx::B2DPolygon* end() const 176 { 177 if(maPolygons.empty()) 178 return 0; 179 else 180 return (&maPolygons.back())+1; 181 } 182 183 basegfx::B2DPolygon* begin() 184 { 185 if(maPolygons.empty()) 186 return 0; 187 else 188 return &maPolygons.front(); 189 } 190 191 basegfx::B2DPolygon* end() 192 { 193 if(maPolygons.empty()) 194 return 0; 195 else 196 return &(maPolygons.back())+1; 197 } 198 }; 199 200 ////////////////////////////////////////////////////////////////////////////// 201 202 namespace basegfx 203 { 204 namespace { struct DefaultPolyPolygon: public rtl::Static<B2DPolyPolygon::ImplType, 205 DefaultPolyPolygon> {}; } 206 207 B2DPolyPolygon::B2DPolyPolygon() : 208 mpPolyPolygon(DefaultPolyPolygon::get()) 209 { 210 } 211 212 B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon) : 213 mpPolyPolygon(rPolyPolygon.mpPolyPolygon) 214 { 215 } 216 217 B2DPolyPolygon::B2DPolyPolygon(const B2DPolygon& rPolygon) : 218 mpPolyPolygon( ImplB2DPolyPolygon(rPolygon) ) 219 { 220 } 221 222 B2DPolyPolygon::~B2DPolyPolygon() 223 { 224 } 225 226 B2DPolyPolygon& B2DPolyPolygon::operator=(const B2DPolyPolygon& rPolyPolygon) 227 { 228 mpPolyPolygon = rPolyPolygon.mpPolyPolygon; 229 return *this; 230 } 231 232 void B2DPolyPolygon::makeUnique() 233 { 234 mpPolyPolygon.make_unique(); 235 mpPolyPolygon->makeUnique(); 236 } 237 238 bool B2DPolyPolygon::operator==(const B2DPolyPolygon& rPolyPolygon) const 239 { 240 if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon)) 241 return true; 242 243 return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon)); 244 } 245 246 bool B2DPolyPolygon::operator!=(const B2DPolyPolygon& rPolyPolygon) const 247 { 248 return !((*this) == rPolyPolygon); 249 } 250 251 sal_uInt32 B2DPolyPolygon::count() const 252 { 253 return mpPolyPolygon->count(); 254 } 255 256 B2DPolygon B2DPolyPolygon::getB2DPolygon(sal_uInt32 nIndex) const 257 { 258 OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)"); 259 260 return mpPolyPolygon->getB2DPolygon(nIndex); 261 } 262 263 void B2DPolyPolygon::setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon) 264 { 265 OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)"); 266 267 if(getB2DPolygon(nIndex) != rPolygon) 268 mpPolyPolygon->setB2DPolygon(nIndex, rPolygon); 269 } 270 271 bool B2DPolyPolygon::areControlPointsUsed() const 272 { 273 for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++) 274 { 275 const B2DPolygon& rPolygon = mpPolyPolygon->getB2DPolygon(a); 276 277 if(rPolygon.areControlPointsUsed()) 278 { 279 return true; 280 } 281 } 282 283 return false; 284 } 285 286 void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolygon& rPolygon, sal_uInt32 nCount) 287 { 288 OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)"); 289 290 if(nCount) 291 mpPolyPolygon->insert(nIndex, rPolygon, nCount); 292 } 293 294 void B2DPolyPolygon::append(const B2DPolygon& rPolygon, sal_uInt32 nCount) 295 { 296 if(nCount) 297 mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount); 298 } 299 300 B2DPolyPolygon B2DPolyPolygon::getDefaultAdaptiveSubdivision() const 301 { 302 B2DPolyPolygon aRetval; 303 304 for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++) 305 { 306 aRetval.append(mpPolyPolygon->getB2DPolygon(a).getDefaultAdaptiveSubdivision()); 307 } 308 309 return aRetval; 310 } 311 312 B2DRange B2DPolyPolygon::getB2DRange() const 313 { 314 B2DRange aRetval; 315 316 for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++) 317 { 318 aRetval.expand(mpPolyPolygon->getB2DPolygon(a).getB2DRange()); 319 } 320 321 return aRetval; 322 } 323 324 void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon) 325 { 326 OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)"); 327 328 if(rPolyPolygon.count()) 329 mpPolyPolygon->insert(nIndex, rPolyPolygon); 330 } 331 332 void B2DPolyPolygon::append(const B2DPolyPolygon& rPolyPolygon) 333 { 334 if(rPolyPolygon.count()) 335 mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon); 336 } 337 338 void B2DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount) 339 { 340 OSL_ENSURE(nIndex + nCount <= mpPolyPolygon->count(), "B2DPolyPolygon Remove outside range (!)"); 341 342 if(nCount) 343 mpPolyPolygon->remove(nIndex, nCount); 344 } 345 346 void B2DPolyPolygon::clear() 347 { 348 mpPolyPolygon = DefaultPolyPolygon::get(); 349 } 350 351 bool B2DPolyPolygon::isClosed() const 352 { 353 bool bRetval(true); 354 355 // PolyPOlygon is closed when all contained Polygons are closed or 356 // no Polygon exists. 357 for(sal_uInt32 a(0L); bRetval && a < mpPolyPolygon->count(); a++) 358 { 359 if(!(mpPolyPolygon->getB2DPolygon(a)).isClosed()) 360 { 361 bRetval = false; 362 } 363 } 364 365 return bRetval; 366 } 367 368 void B2DPolyPolygon::setClosed(bool bNew) 369 { 370 if(bNew != isClosed()) 371 mpPolyPolygon->setClosed(bNew); 372 } 373 374 void B2DPolyPolygon::flip() 375 { 376 if(mpPolyPolygon->count()) 377 { 378 mpPolyPolygon->flip(); 379 } 380 } 381 382 bool B2DPolyPolygon::hasDoublePoints() const 383 { 384 bool bRetval(false); 385 386 for(sal_uInt32 a(0L); !bRetval && a < mpPolyPolygon->count(); a++) 387 { 388 if((mpPolyPolygon->getB2DPolygon(a)).hasDoublePoints()) 389 { 390 bRetval = true; 391 } 392 } 393 394 return bRetval; 395 } 396 397 void B2DPolyPolygon::removeDoublePoints() 398 { 399 if(hasDoublePoints()) 400 mpPolyPolygon->removeDoublePoints(); 401 } 402 403 void B2DPolyPolygon::transform(const B2DHomMatrix& rMatrix) 404 { 405 if(mpPolyPolygon->count() && !rMatrix.isIdentity()) 406 { 407 mpPolyPolygon->transform(rMatrix); 408 } 409 } 410 411 const B2DPolygon* B2DPolyPolygon::begin() const 412 { 413 return mpPolyPolygon->begin(); 414 } 415 416 const B2DPolygon* B2DPolyPolygon::end() const 417 { 418 return mpPolyPolygon->end(); 419 } 420 421 B2DPolygon* B2DPolyPolygon::begin() 422 { 423 return mpPolyPolygon->begin(); 424 } 425 426 B2DPolygon* B2DPolyPolygon::end() 427 { 428 return mpPolyPolygon->end(); 429 } 430 } // end of namespace basegfx 431 432 // eof 433