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