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