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