1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <basegfx/polygon/b2dpolypolygontools.hxx> 21 #include <osl/diagnose.h> 22 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> 23 #include <basegfx/polygon/b2dpolypolygon.hxx> 24 #include <basegfx/polygon/b2dpolygon.hxx> 25 #include <basegfx/polygon/b2dpolygontools.hxx> 26 #include <basegfx/numeric/ftools.hxx> 27 28 #include <algorithm> 29 #include <numeric> 30 31 namespace basegfx 32 { 33 namespace utils 34 { correctOrientations(const B2DPolyPolygon & rCandidate)35 B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate) 36 { 37 B2DPolyPolygon aRetval(rCandidate); 38 const sal_uInt32 nCount(aRetval.count()); 39 40 for(sal_uInt32 a(0); a < nCount; a++) 41 { 42 const B2DPolygon& aCandidate(rCandidate.getB2DPolygon(a)); 43 const B2VectorOrientation aOrientation(utils::getOrientation(aCandidate)); 44 sal_uInt32 nDepth(0); 45 46 for(sal_uInt32 b(0); b < nCount; b++) 47 { 48 if(b != a) 49 { 50 const B2DPolygon& aCompare(rCandidate.getB2DPolygon(b)); 51 52 if(utils::isInside(aCompare, aCandidate, true)) 53 { 54 nDepth++; 55 } 56 } 57 } 58 59 const bool bShallBeHole((nDepth & 0x00000001) == 1); 60 const bool bIsHole(aOrientation == B2VectorOrientation::Negative); 61 62 if(bShallBeHole != bIsHole && aOrientation != B2VectorOrientation::Neutral) 63 { 64 B2DPolygon aFlipped(aCandidate); 65 aFlipped.flip(); 66 aRetval.setB2DPolygon(a, aFlipped); 67 } 68 } 69 70 return aRetval; 71 } 72 correctOutmostPolygon(const B2DPolyPolygon & rCandidate)73 B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate) 74 { 75 const sal_uInt32 nCount(rCandidate.count()); 76 77 if(nCount > 1) 78 { 79 for(sal_uInt32 a(0); a < nCount; a++) 80 { 81 const B2DPolygon& aCandidate(rCandidate.getB2DPolygon(a)); 82 sal_uInt32 nDepth(0); 83 84 for(sal_uInt32 b(0); b < nCount; b++) 85 { 86 if(b != a) 87 { 88 const B2DPolygon& aCompare(rCandidate.getB2DPolygon(b)); 89 90 if(utils::isInside(aCompare, aCandidate, true)) 91 { 92 nDepth++; 93 } 94 } 95 } 96 97 if(!nDepth) 98 { 99 B2DPolyPolygon aRetval(rCandidate); 100 101 if(a != 0) 102 { 103 // exchange polygon a and polygon 0 104 aRetval.setB2DPolygon(0, aCandidate); 105 aRetval.setB2DPolygon(a, rCandidate.getB2DPolygon(0)); 106 } 107 108 // exit 109 return aRetval; 110 } 111 } 112 } 113 114 return rCandidate; 115 } 116 adaptiveSubdivideByDistance(const B2DPolyPolygon & rCandidate,double fDistanceBound)117 B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound) 118 { 119 if(rCandidate.areControlPointsUsed()) 120 { 121 B2DPolyPolygon aRetval; 122 123 for(auto const& rPolygon : rCandidate) 124 { 125 if(rPolygon.areControlPointsUsed()) 126 { 127 aRetval.append(utils::adaptiveSubdivideByDistance(rPolygon, fDistanceBound)); 128 } 129 else 130 { 131 aRetval.append(rPolygon); 132 } 133 } 134 135 return aRetval; 136 } 137 else 138 { 139 return rCandidate; 140 } 141 } 142 adaptiveSubdivideByAngle(const B2DPolyPolygon & rCandidate,double fAngleBound)143 B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound) 144 { 145 if(rCandidate.areControlPointsUsed()) 146 { 147 B2DPolyPolygon aRetval; 148 149 for(auto const& rPolygon : rCandidate) 150 { 151 if(rPolygon.areControlPointsUsed()) 152 { 153 aRetval.append(utils::adaptiveSubdivideByAngle(rPolygon, fAngleBound)); 154 } 155 else 156 { 157 aRetval.append(rPolygon); 158 } 159 } 160 161 return aRetval; 162 } 163 else 164 { 165 return rCandidate; 166 } 167 } 168 isInside(const B2DPolyPolygon & rCandidate,const B2DPoint & rPoint,bool bWithBorder)169 bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder) 170 { 171 if(rCandidate.count() == 1) 172 { 173 return isInside(rCandidate.getB2DPolygon(0), rPoint, bWithBorder); 174 } 175 else 176 { 177 sal_Int32 nInsideCount = std::count_if(rCandidate.begin(), rCandidate.end(), [rPoint, bWithBorder](B2DPolygon polygon){ return isInside(polygon, rPoint, bWithBorder); }); 178 179 return (nInsideCount % 2); 180 } 181 } 182 getRange(const B2DPolyPolygon & rCandidate)183 B2DRange getRange(const B2DPolyPolygon& rCandidate) 184 { 185 B2DRange aRetval; 186 187 for(auto const& rPolygon : rCandidate) 188 { 189 aRetval.expand(utils::getRange(rPolygon)); 190 } 191 192 return aRetval; 193 } 194 getSignedArea(const B2DPolyPolygon & rCandidate)195 double getSignedArea(const B2DPolyPolygon& rCandidate) 196 { 197 double fRetval(0.0); 198 199 for(auto const& rPolygon : rCandidate) 200 { 201 fRetval += utils::getSignedArea(rPolygon); 202 } 203 204 return fRetval; 205 } 206 getArea(const B2DPolyPolygon & rCandidate)207 double getArea(const B2DPolyPolygon& rCandidate) 208 { 209 return fabs(getSignedArea(rCandidate)); 210 } 211 applyLineDashing(const B2DPolyPolygon & rCandidate,const std::vector<double> & rDotDashArray,B2DPolyPolygon * pLineTarget,double fFullDashDotLen)212 void applyLineDashing(const B2DPolyPolygon& rCandidate, const std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, double fFullDashDotLen) 213 { 214 if(fFullDashDotLen == 0.0 && !rDotDashArray.empty()) 215 { 216 // calculate fFullDashDotLen from rDotDashArray 217 fFullDashDotLen = std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0); 218 } 219 220 if(rCandidate.count() && fFullDashDotLen > 0.0) 221 { 222 B2DPolyPolygon aLineTarget; 223 224 for(auto const& rPolygon : rCandidate) 225 { 226 applyLineDashing( 227 rPolygon, 228 rDotDashArray, 229 pLineTarget ? &aLineTarget : nullptr, 230 nullptr, 231 fFullDashDotLen); 232 233 if(pLineTarget) 234 { 235 pLineTarget->append(aLineTarget); 236 } 237 } 238 } 239 } 240 isInEpsilonRange(const B2DPolyPolygon & rCandidate,const B2DPoint & rTestPosition,double fDistance)241 bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance) 242 { 243 for(auto const& rPolygon : rCandidate) 244 { 245 if(isInEpsilonRange(rPolygon, rTestPosition, fDistance)) 246 { 247 return true; 248 } 249 } 250 251 return false; 252 } 253 createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon & rCandidate,double fZCoordinate)254 B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate) 255 { 256 B3DPolyPolygon aRetval; 257 258 for(auto const& rPolygon : rCandidate) 259 { 260 aRetval.append(createB3DPolygonFromB2DPolygon(rPolygon, fZCoordinate)); 261 } 262 263 return aRetval; 264 } 265 createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon & rCandidate,const B3DHomMatrix & rMat)266 B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat) 267 { 268 B2DPolyPolygon aRetval; 269 270 for(auto const& rPolygon : rCandidate) 271 { 272 aRetval.append(createB2DPolygonFromB3DPolygon(rPolygon, rMat)); 273 } 274 275 return aRetval; 276 } 277 getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon & rCandidate,const B2DPoint & rTestPoint,sal_uInt32 & rPolygonIndex,sal_uInt32 & rEdgeIndex,double & rCut)278 double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut) 279 { 280 double fRetval(DBL_MAX); 281 const double fZero(0.0); 282 const sal_uInt32 nPolygonCount(rCandidate.count()); 283 284 for(sal_uInt32 a(0); a < nPolygonCount; a++) 285 { 286 const B2DPolygon& aCandidate(rCandidate.getB2DPolygon(a)); 287 sal_uInt32 nNewEdgeIndex; 288 double fNewCut(0.0); 289 const double fNewDistance(getSmallestDistancePointToPolygon(aCandidate, rTestPoint, nNewEdgeIndex, fNewCut)); 290 291 if(fRetval == DBL_MAX || fNewDistance < fRetval) 292 { 293 fRetval = fNewDistance; 294 rPolygonIndex = a; 295 rEdgeIndex = nNewEdgeIndex; 296 rCut = fNewCut; 297 298 if(fTools::equal(fRetval, fZero)) 299 { 300 // already found zero distance, cannot get better. Ensure numerical zero value and end loop. 301 fRetval = 0.0; 302 break; 303 } 304 } 305 } 306 307 return fRetval; 308 } 309 distort(const B2DPolyPolygon & rCandidate,const B2DRange & rOriginal,const B2DPoint & rTopLeft,const B2DPoint & rTopRight,const B2DPoint & rBottomLeft,const B2DPoint & rBottomRight)310 B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight) 311 { 312 B2DPolyPolygon aRetval; 313 314 for(auto const& rPolygon : rCandidate) 315 { 316 aRetval.append(distort(rPolygon, rOriginal, rTopLeft, rTopRight, rBottomLeft, rBottomRight)); 317 } 318 319 return aRetval; 320 } 321 expandToCurve(const B2DPolyPolygon & rCandidate)322 B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate) 323 { 324 B2DPolyPolygon aRetval; 325 326 for(auto const& rPolygon : rCandidate) 327 { 328 aRetval.append(expandToCurve(rPolygon)); 329 } 330 331 return aRetval; 332 } 333 growInNormalDirection(const B2DPolyPolygon & rCandidate,double fValue)334 B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue) 335 { 336 if(fValue != 0.0) 337 { 338 B2DPolyPolygon aRetval; 339 340 for(auto const& rPolygon : rCandidate) 341 { 342 aRetval.append(growInNormalDirection(rPolygon, fValue)); 343 } 344 345 return aRetval; 346 } 347 else 348 { 349 return rCandidate; 350 } 351 } 352 reSegmentPolyPolygon(const B2DPolyPolygon & rCandidate,sal_uInt32 nSegments)353 B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments) 354 { 355 B2DPolyPolygon aRetval; 356 357 for(auto const& rPolygon : rCandidate) 358 { 359 aRetval.append(reSegmentPolygon(rPolygon, nSegments)); 360 } 361 362 return aRetval; 363 } 364 interpolate(const B2DPolyPolygon & rOld1,const B2DPolyPolygon & rOld2,double t)365 B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t) 366 { 367 OSL_ENSURE(rOld1.count() == rOld2.count(), "B2DPolyPolygon interpolate: Different geometry (!)"); 368 B2DPolyPolygon aRetval; 369 370 for(sal_uInt32 a(0); a < rOld1.count(); a++) 371 { 372 aRetval.append(interpolate(rOld1.getB2DPolygon(a), rOld2.getB2DPolygon(a), t)); 373 } 374 375 return aRetval; 376 } 377 isRectangle(const B2DPolyPolygon & rPoly)378 bool isRectangle( const B2DPolyPolygon& rPoly ) 379 { 380 // exclude some cheap cases first 381 if( rPoly.count() != 1 ) 382 return false; 383 384 return isRectangle( rPoly.getB2DPolygon(0) ); 385 } 386 387 // #i76891# simplifyCurveSegments(const B2DPolyPolygon & rCandidate)388 B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate) 389 { 390 if(rCandidate.areControlPointsUsed()) 391 { 392 B2DPolyPolygon aRetval; 393 394 for(auto const& rPolygon : rCandidate) 395 { 396 aRetval.append(simplifyCurveSegments(rPolygon)); 397 } 398 399 return aRetval; 400 } 401 else 402 { 403 return rCandidate; 404 } 405 } 406 snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon & rCandidate)407 B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate) 408 { 409 B2DPolyPolygon aRetval; 410 411 for(auto const& rPolygon : rCandidate) 412 { 413 aRetval.append(snapPointsOfHorizontalOrVerticalEdges(rPolygon)); 414 } 415 416 return aRetval; 417 } 418 createSevenSegmentPolyPolygon(sal_Char nNumber,bool bLitSegments)419 B2DPolyPolygon createSevenSegmentPolyPolygon(sal_Char nNumber, bool bLitSegments) 420 { 421 // config here 422 // { 423 const double fTotalSize=1.0; 424 const double fPosMiddleSegment=0.6; 425 const double fSegmentEndChopHoriz=0.08; 426 const double fSegmentEndChopVert =0.04; 427 // } 428 // config here 429 430 const double fLeft=0.0; 431 const double fRight=fTotalSize; 432 const double fTop=0.0; 433 const double fMiddle=fPosMiddleSegment; 434 const double fBottom=fTotalSize; 435 436 // from 0 to 5: pair of segment corner coordinates 437 438 // segment corner indices are these: 439 440 // 0 - 1 441 // | | 442 // 2 - 3 443 // | | 444 // 4 - 5 445 446 static const double corners[] = 447 { 448 fLeft, fTop, 449 fRight, fTop, 450 fLeft, fMiddle, 451 fRight, fMiddle, 452 fLeft, fBottom, 453 fRight, fBottom 454 }; 455 456 // from 0 to 9: which segments are 'lit' for this number? 457 458 // array denotes graph edges to traverse, with -1 means 459 // stop (the vertices are the corner indices from above): 460 // 0 461 // - 462 // 1 | | 2 463 // - 3 464 // 4 | | 5 465 // - 466 // 6 467 468 static const int numbers[] = 469 { 470 1, 1, 1, 0, 1, 1, 1, // 0 471 0, 0, 1, 0, 0, 1, 0, // 1 472 1, 0, 1, 1, 1, 0, 1, // 2 473 1, 0, 1, 1, 0, 1, 1, // 3 474 0, 1, 1, 1, 0, 1, 0, // 4 475 1, 1, 0, 1, 0, 1, 1, // 5 476 1, 1, 0, 1, 1, 1, 1, // 6 477 1, 0, 1, 0, 0, 1, 0, // 1 478 1, 1, 1, 1, 1, 1, 1, // 8 479 1, 1, 1, 1, 0, 1, 1, // 9 480 0, 0, 0, 1, 0, 0, 0, // '-' 481 1, 1, 0, 1, 1, 0, 1, // 'E' 482 }; 483 484 // maps segment index to two corner ids: 485 static const int index2corner[] = 486 { 487 0, 2, // 0 488 0, 4, // 1 489 2, 6, // 2 490 4, 6, // 3 491 4, 8, // 4 492 6, 10, // 5 493 8, 10, // 6 494 }; 495 496 B2DPolyPolygon aRes; 497 if( nNumber == '-' ) 498 { 499 nNumber = 10; 500 } 501 else if( nNumber == 'E' ) 502 { 503 nNumber = 11; 504 } 505 else if( nNumber == '.' ) 506 { 507 if( bLitSegments ) 508 aRes.append(createPolygonFromCircle(B2DPoint(fTotalSize/2, fTotalSize), 509 fSegmentEndChopHoriz)); 510 return aRes; 511 } 512 else 513 { 514 nNumber=std::clamp<sal_uInt32>(nNumber,'0','9') - '0'; 515 } 516 517 B2DPolygon aCurrSegment; 518 const size_t sliceSize=SAL_N_ELEMENTS(numbers)/12; 519 const int* pCurrSegment=numbers + nNumber*sliceSize; 520 for( size_t i=0; i<sliceSize; i++, pCurrSegment++) 521 { 522 if( !(*pCurrSegment ^ int(bLitSegments)) ) 523 { 524 const size_t j=2*i; 525 aCurrSegment.clear(); 526 B2DPoint start(corners[index2corner[j]], 527 corners[index2corner[j]+1] ); 528 B2DPoint end (corners[index2corner[j+1]], 529 corners[index2corner[j+1]+1]); 530 531 if( rtl::math::approxEqual(start.getX(), end.getX()) ) 532 { 533 start.setY(start.getY()+fSegmentEndChopVert); 534 end.setY(end.getY()-fSegmentEndChopVert); 535 } 536 else 537 { 538 start.setX(start.getX()+fSegmentEndChopHoriz); 539 end.setX(end.getX()-fSegmentEndChopHoriz); 540 } 541 542 aCurrSegment.append(start); 543 aCurrSegment.append(end); 544 } 545 aRes.append(aCurrSegment); 546 } 547 548 return aRes; 549 } 550 551 // converters for css::drawing::PointSequence 552 UnoPointSequenceSequenceToB2DPolyPolygon(const css::drawing::PointSequenceSequence & rPointSequenceSequenceSource)553 B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon( 554 const css::drawing::PointSequenceSequence& rPointSequenceSequenceSource) 555 { 556 B2DPolyPolygon aRetval; 557 const css::drawing::PointSequence* pPointSequence = rPointSequenceSequenceSource.getConstArray(); 558 const css::drawing::PointSequence* pPointSeqEnd = pPointSequence + rPointSequenceSequenceSource.getLength(); 559 560 for(;pPointSequence != pPointSeqEnd; pPointSequence++) 561 { 562 const B2DPolygon aNewPolygon = UnoPointSequenceToB2DPolygon(*pPointSequence); 563 aRetval.append(aNewPolygon); 564 } 565 566 return aRetval; 567 } 568 B2DPolyPolygonToUnoPointSequenceSequence(const B2DPolyPolygon & rPolyPolygon,css::drawing::PointSequenceSequence & rPointSequenceSequenceRetval)569 void B2DPolyPolygonToUnoPointSequenceSequence( 570 const B2DPolyPolygon& rPolyPolygon, 571 css::drawing::PointSequenceSequence& rPointSequenceSequenceRetval) 572 { 573 const sal_uInt32 nCount(rPolyPolygon.count()); 574 575 if(nCount) 576 { 577 rPointSequenceSequenceRetval.realloc(nCount); 578 css::drawing::PointSequence* pPointSequence = rPointSequenceSequenceRetval.getArray(); 579 580 for(auto const& rPolygon : rPolyPolygon) 581 { 582 B2DPolygonToUnoPointSequence(rPolygon, *pPointSequence); 583 pPointSequence++; 584 } 585 } 586 else 587 { 588 rPointSequenceSequenceRetval.realloc(0); 589 } 590 } 591 592 // converters for css::drawing::PolyPolygonBezierCoords (curved polygons) 593 UnoPolyPolygonBezierCoordsToB2DPolyPolygon(const css::drawing::PolyPolygonBezierCoords & rPolyPolygonBezierCoordsSource)594 B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon( 595 const css::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource) 596 { 597 B2DPolyPolygon aRetval; 598 const sal_uInt32 nSequenceCount(static_cast<sal_uInt32>(rPolyPolygonBezierCoordsSource.Coordinates.getLength())); 599 600 if(nSequenceCount) 601 { 602 OSL_ENSURE(nSequenceCount == static_cast<sal_uInt32>(rPolyPolygonBezierCoordsSource.Flags.getLength()), 603 "UnoPolyPolygonBezierCoordsToB2DPolyPolygon: unequal number of Points and Flags (!)"); 604 const css::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsSource.Coordinates.getConstArray(); 605 const css::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsSource.Flags.getConstArray(); 606 607 for(sal_uInt32 a(0); a < nSequenceCount; a++) 608 { 609 const B2DPolygon aNewPolygon(UnoPolygonBezierCoordsToB2DPolygon( 610 *pPointSequence, 611 *pFlagSequence)); 612 613 pPointSequence++; 614 pFlagSequence++; 615 aRetval.append(aNewPolygon); 616 } 617 } 618 619 return aRetval; 620 } 621 B2DPolyPolygonToUnoPolyPolygonBezierCoords(const B2DPolyPolygon & rPolyPolygon,css::drawing::PolyPolygonBezierCoords & rPolyPolygonBezierCoordsRetval)622 void B2DPolyPolygonToUnoPolyPolygonBezierCoords( 623 const B2DPolyPolygon& rPolyPolygon, 624 css::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval) 625 { 626 const sal_uInt32 nCount(rPolyPolygon.count()); 627 628 if(nCount) 629 { 630 // prepare return value memory 631 rPolyPolygonBezierCoordsRetval.Coordinates.realloc(static_cast<sal_Int32>(nCount)); 632 rPolyPolygonBezierCoordsRetval.Flags.realloc(static_cast<sal_Int32>(nCount)); 633 634 // get pointers to arrays 635 css::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsRetval.Coordinates.getArray(); 636 css::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsRetval.Flags.getArray(); 637 638 for(auto const& rSource : rPolyPolygon) 639 { 640 B2DPolygonToUnoPolygonBezierCoords( 641 rSource, 642 *pPointSequence, 643 *pFlagSequence); 644 pPointSequence++; 645 pFlagSequence++; 646 } 647 } 648 else 649 { 650 rPolyPolygonBezierCoordsRetval.Coordinates.realloc(0); 651 rPolyPolygonBezierCoordsRetval.Flags.realloc(0); 652 } 653 } 654 655 } // end of namespace utils 656 } // end of namespace basegfx 657 658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 659