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 #ifndef _POLYGON_POINT_HXX 25 #define _POLYGON_POINT_HXX 26 27 #include <vector> 28 29 ////////////////////////////////////////////////////////////////////////////// 30 31 template < class Point > class SimplePointEntry 32 { 33 Point maPoint; 34 35 public: SimplePointEntry()36 SimplePointEntry() 37 : maPoint(Point::getEmptyPoint()) 38 { 39 } 40 SimplePointEntry(const Point & rInitPoint)41 SimplePointEntry(const Point& rInitPoint) 42 : maPoint(rInitPoint) 43 { 44 } 45 getPoint() const46 const Point& getPoint() const 47 { 48 return maPoint; 49 } 50 setPoint(const Point & rValue)51 void setPoint(const Point& rValue) 52 { 53 maPoint = rValue; 54 } 55 operator ==(const SimplePointEntry & rEntry) const56 bool operator==(const SimplePointEntry& rEntry) const 57 { 58 return (maPoint == rEntry.maPoint); 59 } 60 }; 61 62 ////////////////////////////////////////////////////////////////////////////// 63 64 template < class Vector > class SimpleBezierEntry 65 { 66 Vector maBackward; 67 Vector maForward; 68 69 public: SimpleBezierEntry()70 SimpleBezierEntry() 71 : maBackward(Vector::getEmptyVector()), 72 maForward(Vector::getEmptyVector()) 73 { 74 } 75 SimpleBezierEntry(const Vector & rInitBackward,const Vector & rInitForward)76 SimpleBezierEntry(const Vector& rInitBackward, const Vector& rInitForward) 77 : maBackward(rInitBackward), 78 maForward(rInitForward) 79 { 80 } 81 getBackwardVector() const82 const Vector& getBackwardVector() const 83 { 84 return maBackward; 85 } 86 setBackwardVector(const Vector & rValue)87 void setBackwardVector(const Vector& rValue) 88 { 89 maBackward = rValue; 90 } 91 getForwardVector() const92 const Vector& getForwardVector() const 93 { 94 return maForward; 95 } 96 setForwardVector(const Vector & rValue)97 void setForwardVector(const Vector& rValue) 98 { 99 maForward = rValue; 100 } 101 isBezierNeeded()102 bool isBezierNeeded() 103 { 104 if(maBackward != Vector::getEmptyVector() || maForward != Vector::getEmptyVector()) 105 return true; 106 return false; 107 } 108 operator ==(const SimpleBezierEntry & rEntry) const109 bool operator==(const SimpleBezierEntry& rEntry) const 110 { 111 return ((maBackward == rEntry.maBackward) && (maForward == rEntry.maForward)); 112 } 113 doInvertForFlip()114 void doInvertForFlip() 115 { 116 maBackward = -maBackward; 117 maForward = -maForward; 118 } 119 }; 120 121 ////////////////////////////////////////////////////////////////////////////// 122 123 template < class Point, class Vector > class PolygonPointList 124 { 125 typedef SimplePointEntry< Point > LocalSimplePointEntry; 126 typedef SimpleBezierEntry< Vector > LocalSimpleBezierEntry; 127 typedef ::std::vector< LocalSimplePointEntry > SimplePointVector; 128 typedef ::std::vector< LocalSimpleBezierEntry > SimpleBezierVector; 129 130 sal_uInt32 mnBezierCount; 131 SimplePointVector maPoints; 132 SimpleBezierVector* mpVectors; 133 134 unsigned mbIsClosed : 1; 135 implTryToReduceToPointVector()136 void implTryToReduceToPointVector() 137 { 138 if(!mnBezierCount && mpVectors) 139 { 140 delete mpVectors; 141 mpVectors = 0L; 142 } 143 } 144 145 public: isBezier() const146 bool isBezier() const 147 { 148 return bool(mnBezierCount); 149 } 150 isClosed() const151 bool isClosed() const 152 { 153 return bool(mbIsClosed); 154 } 155 setClosed(bool bNew)156 void setClosed(bool bNew) 157 { 158 mbIsClosed = bNew; 159 } 160 count() const161 sal_uInt32 count() const 162 { 163 return maPoints.size(); 164 } 165 PolygonPointList()166 PolygonPointList() 167 : mnBezierCount(0L), 168 mpVectors(0L), 169 mbIsClosed(false) 170 { 171 // complete initialization with defaults 172 } 173 PolygonPointList(const PolygonPointList & rSource)174 PolygonPointList(const PolygonPointList& rSource) 175 : mnBezierCount(0L), 176 maPoints(rSource.maPoints), 177 mpVectors(0L), 178 mbIsClosed(rSource.mbIsClosed) 179 { 180 // complete initialization using copy 181 if(rSource.mpVectors && rSource.mnBezierCount) 182 { 183 mpVectors = new SimpleBezierVector(*rSource.mpVectors); 184 mnBezierCount = rSource.mnBezierCount; 185 } 186 } 187 PolygonPointList(const PolygonPointList & rSource,sal_uInt32 nIndex,sal_uInt32 nCount)188 PolygonPointList(const PolygonPointList& rSource, sal_uInt32 nIndex, sal_uInt32 nCount) 189 : mnBezierCount(0L), 190 maPoints(nCount), 191 mpVectors(0L), 192 mbIsClosed(rSource.mbIsClosed) 193 { 194 // complete initialization using partly copy 195 if(nCount) 196 { 197 // copy point data 198 { 199 SimplePointVector::const_iterator aStart(rSource.maPoints.begin()); 200 aStart += nIndex; 201 SimplePointVector::const_iterator aEnd(aStart); 202 aEnd += nCount; 203 maPoints.insert(0L, aStart, aEnd); 204 } 205 206 // copy bezier data 207 if(rSource.mpVectors && rSource.mnBezierCount) 208 { 209 mpVectors = new SimpleBezierVector(); 210 mpVectors->reserve(nCount); 211 212 SimpleBezierVector::iterator aStart(mpVectors->begin()); 213 aStart += nIndex; 214 SimpleBezierVector::iterator aEnd(aStart); 215 aEnd += nCount; 216 217 for( ; aStart != aEnd; ++aStart ) 218 { 219 if(aStart->IsBezierNeeded()) 220 { 221 mnBezierCount++; 222 } 223 224 mpVectors->push_back(*aStart); 225 } 226 227 // maybe vectors are not needed anymore, try to reduce memory footprint 228 implTryToReduceToPointVector(); 229 } 230 } 231 } 232 ~PolygonPointList()233 ~PolygonPointList() 234 { 235 if(mpVectors) 236 { 237 delete mpVectors; 238 } 239 } 240 isEqual(const PolygonPointList & rPointList) const241 bool isEqual(const PolygonPointList& rPointList) const 242 { 243 // same point count? 244 if(maPoints.size() != rPointList.maPoints.size()) 245 return false; 246 247 // if zero points the polys are equal 248 if(!maPoints.size()) 249 return true; 250 251 // if bezier count used it needs to be equal 252 if(mnBezierCount != rPointList.mnBezierCount) 253 return false; 254 255 // compare point content 256 if(maPoints != rPointList.maPoints) 257 return false; 258 259 // beziercounts are equal: if it's zero, we are done 260 if(!mnBezierCount) 261 return true; 262 263 // beziercounts are equal and not zero; compare them 264 OSL_ENSURE(0L != mpVectors, "Error: Bezier list needs to exist here(!)"); 265 OSL_ENSURE(0L != rPointList.mpVectors, "Error: Bezier list needs to exist here(!)"); 266 267 return (*mpVectors == *rPointList.mpVectors); 268 } 269 getPoint(sal_uInt32 nIndex) const270 const Point& getPoint(sal_uInt32 nIndex) const 271 { 272 return maPoints[nIndex].getPoint(); 273 } 274 setPoint(sal_uInt32 nIndex,const Point & rValue)275 void setPoint(sal_uInt32 nIndex, const Point& rValue) 276 { 277 maPoints[nIndex].setPoint(rValue); 278 } 279 getBackwardVector(sal_uInt32 nIndex) const280 const Vector& getBackwardVector(sal_uInt32 nIndex) const 281 { 282 if(mpVectors) 283 return ((*mpVectors)[nIndex]).getBackwardVector(); 284 else 285 return Vector::getEmptyVector(); 286 } 287 setBackwardVector(sal_uInt32 nIndex,const Vector & rValue)288 void setBackwardVector(sal_uInt32 nIndex, const Vector& rValue) 289 { 290 if(mpVectors) 291 { 292 LocalSimpleBezierEntry& rDest = (*mpVectors)[nIndex]; 293 bool bBezierNeededBefore(rDest.isBezierNeeded()); 294 ((*mpVectors)[nIndex]).setBackwardVector(rValue); 295 bool bBezierNeededAfter(rDest.isBezierNeeded()); 296 297 if(bBezierNeededBefore != bBezierNeededAfter) 298 { 299 if(bBezierNeededAfter) 300 mnBezierCount++; 301 else 302 mnBezierCount--; 303 } 304 } 305 else 306 { 307 bool bEmptyVector(rValue == Vector::getEmptyVector()); 308 309 if(bEmptyVector) 310 return; 311 312 mpVectors = new SimpleBezierVector(maPoints.size()); 313 ((*mpVectors)[nIndex]).setBackwardVector(rValue); 314 mnBezierCount++; 315 } 316 } 317 getForwardVector(sal_uInt32 nIndex) const318 const Vector& getForwardVector(sal_uInt32 nIndex) const 319 { 320 if(mpVectors) 321 return ((*mpVectors)[nIndex]).getForwardVector(); 322 else 323 return Vector::getEmptyVector(); 324 } 325 setForwardVector(sal_uInt32 nIndex,const Vector & rValue)326 void setForwardVector(sal_uInt32 nIndex, const Vector& rValue) 327 { 328 if(mpVectors) 329 { 330 LocalSimpleBezierEntry& rDest = (*mpVectors)[nIndex]; 331 bool bBezierNeededBefore(rDest.isBezierNeeded()); 332 ((*mpVectors)[nIndex]).setForwardVector(rValue); 333 bool bBezierNeededAfter(rDest.isBezierNeeded()); 334 335 if(bBezierNeededBefore != bBezierNeededAfter) 336 { 337 if(bBezierNeededAfter) 338 mnBezierCount++; 339 else 340 mnBezierCount--; 341 } 342 } 343 else 344 { 345 bool bEmptyVector(rValue == Vector::getEmptyVector()); 346 347 if(bEmptyVector) 348 return; 349 350 mpVectors = new SimpleBezierVector(maPoints.size()); 351 ((*mpVectors)[nIndex]).setForwardVector(rValue); 352 mnBezierCount++; 353 } 354 } 355 insert(sal_uInt32 nIndex,const Point & rPoint,sal_uInt32 nCount)356 void insert(sal_uInt32 nIndex, const Point& rPoint, sal_uInt32 nCount) 357 { 358 if(nCount) 359 { 360 // maybe vectors are not needed anymore, try to reduce memory footprint 361 implTryToReduceToPointVector(); 362 363 // add nCount copies of rPoint 364 { 365 LocalSimplePointEntry aNode(rPoint); 366 SimplePointVector::iterator aIndex(maPoints.begin()); 367 aIndex += nIndex; 368 maPoints.insert(aIndex, nCount, aNode); 369 } 370 371 // add nCount empty entries to keep indices synchronized 372 if(mpVectors) 373 { 374 LocalSimpleBezierEntry aNode; 375 SimpleBezierVector::iterator aIndex(mpVectors->begin()); 376 aIndex += nIndex; 377 mpVectors->insert(aIndex, nCount, aNode); 378 } 379 } 380 } 381 insert(sal_uInt32 nIndex,const PolygonPointList & rSource)382 void insert(sal_uInt32 nIndex, const PolygonPointList& rSource) 383 { 384 const sal_uInt32 nCount(rSource.maPoints.size()); 385 386 if(nCount) 387 { 388 // instert point data 389 { 390 SimplePointVector::iterator aIndex(maPoints.begin()); 391 aIndex += nIndex; 392 393 SimplePointVector::const_iterator aStart(rSource.maPoints.begin()); 394 SimplePointVector::const_iterator aEnd(rSource.maPoints.end()); 395 396 maPoints.insert(aIndex, aStart, aEnd); 397 } 398 399 // insert bezier data 400 if(rSource.mpVectors && rSource.mnBezierCount) 401 { 402 SimpleBezierVector::iterator aIndex(mpVectors->begin()); 403 aIndex += nIndex; 404 405 SimpleBezierVector::iterator aStart(rSource.mpVectors->begin()); 406 SimpleBezierVector::iterator aEnd(rSource.mpVectors->end()); 407 408 if(!mpVectors) 409 { 410 mpVectors = new SimpleBezierVector(maPoints.size() - nCount); 411 } 412 413 mpVectors->insert(aIndex, aStart, aEnd); 414 415 mnBezierCount += rSource.mnBezierCount; 416 } 417 else 418 { 419 // maybe vectors are not needed anymore, try to reduce memory footprint 420 implTryToReduceToPointVector(); 421 422 // add nCount empty entries to keep indices synchronized 423 if(mpVectors) 424 { 425 LocalSimpleBezierEntry aNode; 426 SimpleBezierVector::iterator aIndex(mpVectors->begin()); 427 aIndex += nIndex; 428 mpVectors->insert(aIndex, nCount, aNode); 429 } 430 } 431 } 432 } 433 remove(sal_uInt32 nIndex,sal_uInt32 nCount)434 void remove(sal_uInt32 nIndex, sal_uInt32 nCount) 435 { 436 if(nCount) 437 { 438 // maybe vectors are not needed anymore, try to reduce memory footprint 439 implTryToReduceToPointVector(); 440 441 // remove point data 442 { 443 SimplePointVector::iterator aStart(maPoints.begin()); 444 aStart += nIndex; 445 const SimplePointVector::iterator aEnd(aStart + nCount); 446 447 maPoints.erase(aStart, aEnd); 448 } 449 450 // remove bezier data 451 if(mpVectors) 452 { 453 SimpleBezierVector::iterator aStart(mpVectors->begin()); 454 aStart += nIndex; 455 const SimpleBezierVector::iterator aEnd(aStart + nCount); 456 457 // take care for correct mnBezierCount BEFORE erase 458 if(mnBezierCount) 459 { 460 SimpleBezierVector::iterator aTestIter(aStart); 461 462 for( ; mnBezierCount && aTestIter != aEnd; ++aTestIter) 463 { 464 if(aTestIter->isBezierNeeded()) 465 mnBezierCount--; 466 } 467 } 468 469 if(mnBezierCount) 470 { 471 // erase nodes 472 mpVectors->erase(aStart, aEnd); 473 } 474 else 475 { 476 // try to reduce, maybe 0L == mnBezierCount 477 implTryToReduceToPointVector(); 478 } 479 } 480 } 481 } 482 flip()483 void flip() 484 { 485 if(maPoints.size() > 1) 486 { 487 // maybe vectors are not needed anymore, try to reduce memory footprint 488 implTryToReduceToPointVector(); 489 490 // calculate half size 491 const sal_uInt32 nHalfSize(maPoints.size() >> 1L); 492 493 // flip point data 494 { 495 SimplePointVector::iterator aStart(maPoints.begin()); 496 SimplePointVector::iterator aEnd(maPoints.end()); 497 498 for(sal_uInt32 a(0); a < nHalfSize; a++) 499 { 500 LocalSimplePointEntry aTemp = *aStart; 501 *aStart++ = *aEnd; 502 *aEnd-- = aTemp; 503 } 504 } 505 506 // flip bezier data 507 if(mpVectors) 508 { 509 SimpleBezierVector::iterator aStart(mpVectors->begin()); 510 SimpleBezierVector::iterator aEnd(mpVectors->end()); 511 512 for(sal_uInt32 a(0); a < nHalfSize; a++) 513 { 514 LocalSimpleBezierEntry aTemp = *aStart; 515 aTemp.doInvertForFlip(); 516 *aStart = *aEnd; 517 aStart->doInvertForFlip(); 518 aStart++; 519 *aEnd-- = aTemp; 520 } 521 522 // also flip vectors of middle point (if existing) 523 if(maPoints.size() % 2) 524 { 525 (*mpVectors)[nHalfSize].doInvertForFlip(); 526 } 527 } 528 } 529 } 530 }; 531 532 ////////////////////////////////////////////////////////////////////////////// 533 534 #endif _POLYGON_POINT_HXX 535