1*09dbbe93SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*09dbbe93SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*09dbbe93SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*09dbbe93SAndrew Rist * distributed with this work for additional information 6*09dbbe93SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*09dbbe93SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*09dbbe93SAndrew Rist * "License"); you may not use this file except in compliance 9*09dbbe93SAndrew Rist * with the License. You may obtain a copy of the License at 10*09dbbe93SAndrew Rist * 11*09dbbe93SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*09dbbe93SAndrew Rist * 13*09dbbe93SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*09dbbe93SAndrew Rist * software distributed under the License is distributed on an 15*09dbbe93SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*09dbbe93SAndrew Rist * KIND, either express or implied. See the License for the 17*09dbbe93SAndrew Rist * specific language governing permissions and limitations 18*09dbbe93SAndrew Rist * under the License. 19*09dbbe93SAndrew Rist * 20*09dbbe93SAndrew Rist *************************************************************/ 21*09dbbe93SAndrew Rist 22*09dbbe93SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_basegfx.hxx" 26cdf0e10cSrcweir #include <basegfx/tools/b2dclipstate.hxx> 27cdf0e10cSrcweir 28cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx> 29cdf0e10cSrcweir #include <basegfx/range/b2dpolyrange.hxx> 30cdf0e10cSrcweir #include <basegfx/range/b2drangeclipper.hxx> 31cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 32cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 33cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx> 34cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 35cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 36cdf0e10cSrcweir 37cdf0e10cSrcweir namespace basegfx 38cdf0e10cSrcweir { 39cdf0e10cSrcweir namespace tools 40cdf0e10cSrcweir { 41cdf0e10cSrcweir struct ImplB2DClipState 42cdf0e10cSrcweir { 43cdf0e10cSrcweir public: 44cdf0e10cSrcweir enum Operation {UNION, INTERSECT, XOR, SUBTRACT}; 45cdf0e10cSrcweir ImplB2DClipStatebasegfx::tools::ImplB2DClipState46cdf0e10cSrcweir ImplB2DClipState() : 47cdf0e10cSrcweir maPendingPolygons(), 48cdf0e10cSrcweir maPendingRanges(), 49cdf0e10cSrcweir maClipPoly(), 50cdf0e10cSrcweir mePendingOps(UNION) 51cdf0e10cSrcweir {} 52cdf0e10cSrcweir ImplB2DClipStatebasegfx::tools::ImplB2DClipState53cdf0e10cSrcweir explicit ImplB2DClipState( const B2DRange& rRange ) : 54cdf0e10cSrcweir maPendingPolygons(), 55cdf0e10cSrcweir maPendingRanges(), 56cdf0e10cSrcweir maClipPoly( 57cdf0e10cSrcweir tools::createPolygonFromRect(rRange)), 58cdf0e10cSrcweir mePendingOps(UNION) 59cdf0e10cSrcweir {} 60cdf0e10cSrcweir ImplB2DClipStatebasegfx::tools::ImplB2DClipState61cdf0e10cSrcweir explicit ImplB2DClipState( const B2DPolygon& rPoly ) : 62cdf0e10cSrcweir maPendingPolygons(), 63cdf0e10cSrcweir maPendingRanges(), 64cdf0e10cSrcweir maClipPoly(rPoly), 65cdf0e10cSrcweir mePendingOps(UNION) 66cdf0e10cSrcweir {} 67cdf0e10cSrcweir ImplB2DClipStatebasegfx::tools::ImplB2DClipState68cdf0e10cSrcweir explicit ImplB2DClipState( const B2DPolyPolygon& rPoly ) : 69cdf0e10cSrcweir maPendingPolygons(), 70cdf0e10cSrcweir maPendingRanges(), 71cdf0e10cSrcweir maClipPoly(rPoly), 72cdf0e10cSrcweir mePendingOps(UNION) 73cdf0e10cSrcweir {} 74cdf0e10cSrcweir isClearedbasegfx::tools::ImplB2DClipState75cdf0e10cSrcweir bool isCleared() const 76cdf0e10cSrcweir { 77cdf0e10cSrcweir return !maClipPoly.count() 78cdf0e10cSrcweir && !maPendingPolygons.count() 79cdf0e10cSrcweir && !maPendingRanges.count(); 80cdf0e10cSrcweir } 81cdf0e10cSrcweir makeClearbasegfx::tools::ImplB2DClipState82cdf0e10cSrcweir void makeClear() 83cdf0e10cSrcweir { 84cdf0e10cSrcweir maPendingPolygons.clear(); 85cdf0e10cSrcweir maPendingRanges.clear(); 86cdf0e10cSrcweir maClipPoly.clear(); 87cdf0e10cSrcweir mePendingOps = UNION; 88cdf0e10cSrcweir } 89cdf0e10cSrcweir isNullClipPolybasegfx::tools::ImplB2DClipState90cdf0e10cSrcweir bool isNullClipPoly() const 91cdf0e10cSrcweir { 92cdf0e10cSrcweir return maClipPoly.count() == 1 93cdf0e10cSrcweir && !maClipPoly.getB2DPolygon(0).count(); 94cdf0e10cSrcweir } 95cdf0e10cSrcweir isNullbasegfx::tools::ImplB2DClipState96cdf0e10cSrcweir bool isNull() const 97cdf0e10cSrcweir { 98cdf0e10cSrcweir return !maPendingPolygons.count() 99cdf0e10cSrcweir && !maPendingRanges.count() 100cdf0e10cSrcweir && isNullClipPoly(); 101cdf0e10cSrcweir } 102cdf0e10cSrcweir makeNullbasegfx::tools::ImplB2DClipState103cdf0e10cSrcweir void makeNull() 104cdf0e10cSrcweir { 105cdf0e10cSrcweir maPendingPolygons.clear(); 106cdf0e10cSrcweir maPendingRanges.clear(); 107cdf0e10cSrcweir maClipPoly.clear(); 108cdf0e10cSrcweir maClipPoly.append(B2DPolygon()); 109cdf0e10cSrcweir mePendingOps = UNION; 110cdf0e10cSrcweir } 111cdf0e10cSrcweir operator ==basegfx::tools::ImplB2DClipState112cdf0e10cSrcweir bool operator==(const ImplB2DClipState& rRHS) const 113cdf0e10cSrcweir { 114cdf0e10cSrcweir return maPendingPolygons == rRHS.maPendingPolygons 115cdf0e10cSrcweir && maPendingRanges == rRHS.maPendingRanges 116cdf0e10cSrcweir && maClipPoly == rRHS.maClipPoly 117cdf0e10cSrcweir && mePendingOps == rRHS.mePendingOps; 118cdf0e10cSrcweir } 119cdf0e10cSrcweir addRangebasegfx::tools::ImplB2DClipState120cdf0e10cSrcweir void addRange(const B2DRange& rRange, Operation eOp) 121cdf0e10cSrcweir { 122cdf0e10cSrcweir if( rRange.isEmpty() ) 123cdf0e10cSrcweir return; 124cdf0e10cSrcweir 125cdf0e10cSrcweir commitPendingPolygons(); 126cdf0e10cSrcweir if( mePendingOps != eOp ) 127cdf0e10cSrcweir commitPendingRanges(); 128cdf0e10cSrcweir 129cdf0e10cSrcweir mePendingOps = eOp; 130cdf0e10cSrcweir maPendingRanges.appendElement( 131cdf0e10cSrcweir rRange, 132cdf0e10cSrcweir ORIENTATION_POSITIVE); 133cdf0e10cSrcweir } 134cdf0e10cSrcweir addPolygonbasegfx::tools::ImplB2DClipState135cdf0e10cSrcweir void addPolygon(B2DPolygon aPoly, Operation eOp) 136cdf0e10cSrcweir { 137cdf0e10cSrcweir commitPendingRanges(); 138cdf0e10cSrcweir if( mePendingOps != eOp ) 139cdf0e10cSrcweir commitPendingPolygons(); 140cdf0e10cSrcweir 141cdf0e10cSrcweir mePendingOps = eOp; 142cdf0e10cSrcweir maPendingPolygons.append(aPoly); 143cdf0e10cSrcweir } 144cdf0e10cSrcweir addPolyPolygonbasegfx::tools::ImplB2DClipState145cdf0e10cSrcweir void addPolyPolygon(B2DPolyPolygon aPoly, Operation eOp) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir commitPendingRanges(); 148cdf0e10cSrcweir if( mePendingOps != eOp ) 149cdf0e10cSrcweir commitPendingPolygons(); 150cdf0e10cSrcweir 151cdf0e10cSrcweir mePendingOps = eOp; 152cdf0e10cSrcweir maPendingPolygons.append(aPoly); 153cdf0e10cSrcweir } 154cdf0e10cSrcweir addClipStatebasegfx::tools::ImplB2DClipState155cdf0e10cSrcweir void addClipState(const ImplB2DClipState& rOther, Operation eOp) 156cdf0e10cSrcweir { 157cdf0e10cSrcweir if( rOther.mePendingOps == mePendingOps 158cdf0e10cSrcweir && !rOther.maClipPoly.count() 159cdf0e10cSrcweir && !rOther.maPendingPolygons.count() ) 160cdf0e10cSrcweir { 161cdf0e10cSrcweir maPendingRanges.appendPolyRange( rOther.maPendingRanges ); 162cdf0e10cSrcweir } 163cdf0e10cSrcweir else 164cdf0e10cSrcweir { 165cdf0e10cSrcweir commitPendingRanges(); 166cdf0e10cSrcweir commitPendingPolygons(); 167cdf0e10cSrcweir rOther.commitPendingRanges(); 168cdf0e10cSrcweir rOther.commitPendingPolygons(); 169cdf0e10cSrcweir 170cdf0e10cSrcweir maPendingPolygons = rOther.maClipPoly; 171cdf0e10cSrcweir mePendingOps = eOp; 172cdf0e10cSrcweir } 173cdf0e10cSrcweir } 174cdf0e10cSrcweir unionRangebasegfx::tools::ImplB2DClipState175cdf0e10cSrcweir void unionRange(const B2DRange& rRange) 176cdf0e10cSrcweir { 177cdf0e10cSrcweir if( isCleared() ) 178cdf0e10cSrcweir return; 179cdf0e10cSrcweir 180cdf0e10cSrcweir addRange(rRange,UNION); 181cdf0e10cSrcweir } 182cdf0e10cSrcweir unionPolygonbasegfx::tools::ImplB2DClipState183cdf0e10cSrcweir void unionPolygon(const B2DPolygon& rPoly) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir if( isCleared() ) 186cdf0e10cSrcweir return; 187cdf0e10cSrcweir 188cdf0e10cSrcweir addPolygon(rPoly,UNION); 189cdf0e10cSrcweir } 190cdf0e10cSrcweir unionPolyPolygonbasegfx::tools::ImplB2DClipState191cdf0e10cSrcweir void unionPolyPolygon(const B2DPolyPolygon& rPolyPoly) 192cdf0e10cSrcweir { 193cdf0e10cSrcweir if( isCleared() ) 194cdf0e10cSrcweir return; 195cdf0e10cSrcweir 196cdf0e10cSrcweir addPolyPolygon(rPolyPoly,UNION); 197cdf0e10cSrcweir } 198cdf0e10cSrcweir unionClipStatebasegfx::tools::ImplB2DClipState199cdf0e10cSrcweir void unionClipState(const ImplB2DClipState& rOther) 200cdf0e10cSrcweir { 201cdf0e10cSrcweir if( isCleared() ) 202cdf0e10cSrcweir return; 203cdf0e10cSrcweir 204cdf0e10cSrcweir addClipState(rOther, UNION); 205cdf0e10cSrcweir } 206cdf0e10cSrcweir intersectRangebasegfx::tools::ImplB2DClipState207cdf0e10cSrcweir void intersectRange(const B2DRange& rRange) 208cdf0e10cSrcweir { 209cdf0e10cSrcweir if( isNull() ) 210cdf0e10cSrcweir return; 211cdf0e10cSrcweir 212cdf0e10cSrcweir addRange(rRange,INTERSECT); 213cdf0e10cSrcweir } 214cdf0e10cSrcweir intersectPolygonbasegfx::tools::ImplB2DClipState215cdf0e10cSrcweir void intersectPolygon(const B2DPolygon& rPoly) 216cdf0e10cSrcweir { 217cdf0e10cSrcweir if( isNull() ) 218cdf0e10cSrcweir return; 219cdf0e10cSrcweir 220cdf0e10cSrcweir addPolygon(rPoly,INTERSECT); 221cdf0e10cSrcweir } 222cdf0e10cSrcweir intersectPolyPolygonbasegfx::tools::ImplB2DClipState223cdf0e10cSrcweir void intersectPolyPolygon(const B2DPolyPolygon& rPolyPoly) 224cdf0e10cSrcweir { 225cdf0e10cSrcweir if( isNull() ) 226cdf0e10cSrcweir return; 227cdf0e10cSrcweir 228cdf0e10cSrcweir addPolyPolygon(rPolyPoly,INTERSECT); 229cdf0e10cSrcweir } 230cdf0e10cSrcweir intersectClipStatebasegfx::tools::ImplB2DClipState231cdf0e10cSrcweir void intersectClipState(const ImplB2DClipState& rOther) 232cdf0e10cSrcweir { 233cdf0e10cSrcweir if( isNull() ) 234cdf0e10cSrcweir return; 235cdf0e10cSrcweir 236cdf0e10cSrcweir addClipState(rOther, INTERSECT); 237cdf0e10cSrcweir } 238cdf0e10cSrcweir subtractRangebasegfx::tools::ImplB2DClipState239cdf0e10cSrcweir void subtractRange(const B2DRange& rRange ) 240cdf0e10cSrcweir { 241cdf0e10cSrcweir if( isNull() ) 242cdf0e10cSrcweir return; 243cdf0e10cSrcweir 244cdf0e10cSrcweir addRange(rRange,SUBTRACT); 245cdf0e10cSrcweir } 246cdf0e10cSrcweir subtractPolygonbasegfx::tools::ImplB2DClipState247cdf0e10cSrcweir void subtractPolygon(const B2DPolygon& rPoly) 248cdf0e10cSrcweir { 249cdf0e10cSrcweir if( isNull() ) 250cdf0e10cSrcweir return; 251cdf0e10cSrcweir 252cdf0e10cSrcweir addPolygon(rPoly,SUBTRACT); 253cdf0e10cSrcweir } 254cdf0e10cSrcweir subtractPolyPolygonbasegfx::tools::ImplB2DClipState255cdf0e10cSrcweir void subtractPolyPolygon(const B2DPolyPolygon& rPolyPoly) 256cdf0e10cSrcweir { 257cdf0e10cSrcweir if( isNull() ) 258cdf0e10cSrcweir return; 259cdf0e10cSrcweir 260cdf0e10cSrcweir addPolyPolygon(rPolyPoly,SUBTRACT); 261cdf0e10cSrcweir } 262cdf0e10cSrcweir subtractClipStatebasegfx::tools::ImplB2DClipState263cdf0e10cSrcweir void subtractClipState(const ImplB2DClipState& rOther) 264cdf0e10cSrcweir { 265cdf0e10cSrcweir if( isNull() ) 266cdf0e10cSrcweir return; 267cdf0e10cSrcweir 268cdf0e10cSrcweir addClipState(rOther, SUBTRACT); 269cdf0e10cSrcweir } 270cdf0e10cSrcweir xorRangebasegfx::tools::ImplB2DClipState271cdf0e10cSrcweir void xorRange(const B2DRange& rRange) 272cdf0e10cSrcweir { 273cdf0e10cSrcweir addRange(rRange,XOR); 274cdf0e10cSrcweir } 275cdf0e10cSrcweir xorPolygonbasegfx::tools::ImplB2DClipState276cdf0e10cSrcweir void xorPolygon(const B2DPolygon& rPoly) 277cdf0e10cSrcweir { 278cdf0e10cSrcweir addPolygon(rPoly,XOR); 279cdf0e10cSrcweir } 280cdf0e10cSrcweir xorPolyPolygonbasegfx::tools::ImplB2DClipState281cdf0e10cSrcweir void xorPolyPolygon(const B2DPolyPolygon& rPolyPoly) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir addPolyPolygon(rPolyPoly,XOR); 284cdf0e10cSrcweir } 285cdf0e10cSrcweir xorClipStatebasegfx::tools::ImplB2DClipState286cdf0e10cSrcweir void xorClipState(const ImplB2DClipState& rOther) 287cdf0e10cSrcweir { 288cdf0e10cSrcweir addClipState(rOther, XOR); 289cdf0e10cSrcweir } 290cdf0e10cSrcweir getClipPolybasegfx::tools::ImplB2DClipState291cdf0e10cSrcweir B2DPolyPolygon getClipPoly() const 292cdf0e10cSrcweir { 293cdf0e10cSrcweir commitPendingRanges(); 294cdf0e10cSrcweir commitPendingPolygons(); 295cdf0e10cSrcweir 296cdf0e10cSrcweir return maClipPoly; 297cdf0e10cSrcweir } 298cdf0e10cSrcweir 299cdf0e10cSrcweir private: commitPendingPolygonsbasegfx::tools::ImplB2DClipState300cdf0e10cSrcweir void commitPendingPolygons() const 301cdf0e10cSrcweir { 302cdf0e10cSrcweir if( !maPendingPolygons.count() ) 303cdf0e10cSrcweir return; 304cdf0e10cSrcweir 305cdf0e10cSrcweir // assumption: maClipPoly has kept polygons prepared for 306cdf0e10cSrcweir // clipping; i.e. no neutral polygons & correct 307cdf0e10cSrcweir // orientation 308cdf0e10cSrcweir maPendingPolygons = tools::prepareForPolygonOperation(maPendingPolygons); 309cdf0e10cSrcweir const bool bIsEmpty=isNullClipPoly(); 310cdf0e10cSrcweir const bool bIsCleared=!maClipPoly.count(); 311cdf0e10cSrcweir switch(mePendingOps) 312cdf0e10cSrcweir { 313cdf0e10cSrcweir case UNION: 314cdf0e10cSrcweir OSL_ASSERT( !bIsCleared ); 315cdf0e10cSrcweir 316cdf0e10cSrcweir if( bIsEmpty ) 317cdf0e10cSrcweir maClipPoly = maPendingPolygons; 318cdf0e10cSrcweir else 319cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationOr( 320cdf0e10cSrcweir maClipPoly, 321cdf0e10cSrcweir maPendingPolygons); 322cdf0e10cSrcweir break; 323cdf0e10cSrcweir case INTERSECT: 324cdf0e10cSrcweir OSL_ASSERT( !bIsEmpty ); 325cdf0e10cSrcweir 326cdf0e10cSrcweir if( bIsCleared ) 327cdf0e10cSrcweir maClipPoly = maPendingPolygons; 328cdf0e10cSrcweir else 329cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationAnd( 330cdf0e10cSrcweir maClipPoly, 331cdf0e10cSrcweir maPendingPolygons); 332cdf0e10cSrcweir break; 333cdf0e10cSrcweir case XOR: 334cdf0e10cSrcweir if( bIsEmpty ) 335cdf0e10cSrcweir maClipPoly = maPendingPolygons; 336cdf0e10cSrcweir else if( bIsCleared ) 337cdf0e10cSrcweir { 338cdf0e10cSrcweir // not representable, strictly speaking, 339cdf0e10cSrcweir // using polygons with the common even/odd 340cdf0e10cSrcweir // or nonzero winding number fill rule. If 341cdf0e10cSrcweir // we'd want to represent it, fill rule 342cdf0e10cSrcweir // would need to be "non-negative winding 343cdf0e10cSrcweir // number" (and we then would return 344cdf0e10cSrcweir // 'holes' here) 345cdf0e10cSrcweir 346cdf0e10cSrcweir // going for an ugly hack meanwhile 347cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationXor( 348cdf0e10cSrcweir B2DPolyPolygon( 349cdf0e10cSrcweir tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))), 350cdf0e10cSrcweir maPendingPolygons); 351cdf0e10cSrcweir } 352cdf0e10cSrcweir else 353cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationXor( 354cdf0e10cSrcweir maClipPoly, 355cdf0e10cSrcweir maPendingPolygons); 356cdf0e10cSrcweir break; 357cdf0e10cSrcweir case SUBTRACT: 358cdf0e10cSrcweir OSL_ASSERT( !bIsEmpty ); 359cdf0e10cSrcweir 360cdf0e10cSrcweir // first union all pending ones, subtract en bloc then 361cdf0e10cSrcweir maPendingPolygons = solveCrossovers(maPendingPolygons); 362cdf0e10cSrcweir maPendingPolygons = stripNeutralPolygons(maPendingPolygons); 363cdf0e10cSrcweir maPendingPolygons = stripDispensablePolygons(maPendingPolygons, false); 364cdf0e10cSrcweir 365cdf0e10cSrcweir if( bIsCleared ) 366cdf0e10cSrcweir { 367cdf0e10cSrcweir // not representable, strictly speaking, 368cdf0e10cSrcweir // using polygons with the common even/odd 369cdf0e10cSrcweir // or nonzero winding number fill rule. If 370cdf0e10cSrcweir // we'd want to represent it, fill rule 371cdf0e10cSrcweir // would need to be "non-negative winding 372cdf0e10cSrcweir // number" (and we then would return 373cdf0e10cSrcweir // 'holes' here) 374cdf0e10cSrcweir 375cdf0e10cSrcweir // going for an ugly hack meanwhile 376cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationDiff( 377cdf0e10cSrcweir B2DPolyPolygon( 378cdf0e10cSrcweir tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))), 379cdf0e10cSrcweir maPendingPolygons); 380cdf0e10cSrcweir } 381cdf0e10cSrcweir else 382cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationDiff( 383cdf0e10cSrcweir maClipPoly, 384cdf0e10cSrcweir maPendingPolygons); 385cdf0e10cSrcweir break; 386cdf0e10cSrcweir } 387cdf0e10cSrcweir 388cdf0e10cSrcweir maPendingPolygons.clear(); 389cdf0e10cSrcweir mePendingOps = UNION; 390cdf0e10cSrcweir } 391cdf0e10cSrcweir commitPendingRangesbasegfx::tools::ImplB2DClipState392cdf0e10cSrcweir void commitPendingRanges() const 393cdf0e10cSrcweir { 394cdf0e10cSrcweir if( !maPendingRanges.count() ) 395cdf0e10cSrcweir return; 396cdf0e10cSrcweir 397cdf0e10cSrcweir // use the specialized range clipper for the win 398cdf0e10cSrcweir B2DPolyPolygon aCollectedRanges; 399cdf0e10cSrcweir const bool bIsEmpty=isNullClipPoly(); 400cdf0e10cSrcweir const bool bIsCleared=!maClipPoly.count(); 401cdf0e10cSrcweir switch(mePendingOps) 402cdf0e10cSrcweir { 403cdf0e10cSrcweir case UNION: 404cdf0e10cSrcweir OSL_ASSERT( !bIsCleared ); 405cdf0e10cSrcweir 406cdf0e10cSrcweir aCollectedRanges = maPendingRanges.solveCrossovers(); 407cdf0e10cSrcweir aCollectedRanges = stripNeutralPolygons(aCollectedRanges); 408cdf0e10cSrcweir aCollectedRanges = stripDispensablePolygons(aCollectedRanges, false); 409cdf0e10cSrcweir if( bIsEmpty ) 410cdf0e10cSrcweir maClipPoly = aCollectedRanges; 411cdf0e10cSrcweir else 412cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationOr( 413cdf0e10cSrcweir maClipPoly, 414cdf0e10cSrcweir aCollectedRanges); 415cdf0e10cSrcweir break; 416cdf0e10cSrcweir case INTERSECT: 417cdf0e10cSrcweir OSL_ASSERT( !bIsEmpty ); 418cdf0e10cSrcweir 419cdf0e10cSrcweir aCollectedRanges = maPendingRanges.solveCrossovers(); 420cdf0e10cSrcweir aCollectedRanges = stripNeutralPolygons(aCollectedRanges); 421cdf0e10cSrcweir if( maPendingRanges.count() > 1 ) 422cdf0e10cSrcweir aCollectedRanges = stripDispensablePolygons(aCollectedRanges, true); 423cdf0e10cSrcweir 424cdf0e10cSrcweir if( bIsCleared ) 425cdf0e10cSrcweir maClipPoly = aCollectedRanges; 426cdf0e10cSrcweir else 427cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationAnd( 428cdf0e10cSrcweir maClipPoly, 429cdf0e10cSrcweir aCollectedRanges); 430cdf0e10cSrcweir break; 431cdf0e10cSrcweir case XOR: 432cdf0e10cSrcweir aCollectedRanges = maPendingRanges.solveCrossovers(); 433cdf0e10cSrcweir aCollectedRanges = stripNeutralPolygons(aCollectedRanges); 434cdf0e10cSrcweir aCollectedRanges = correctOrientations(aCollectedRanges); 435cdf0e10cSrcweir 436cdf0e10cSrcweir if( bIsEmpty ) 437cdf0e10cSrcweir maClipPoly = aCollectedRanges; 438cdf0e10cSrcweir else if( bIsCleared ) 439cdf0e10cSrcweir { 440cdf0e10cSrcweir // not representable, strictly speaking, 441cdf0e10cSrcweir // using polygons with the common even/odd 442cdf0e10cSrcweir // or nonzero winding number fill rule. If 443cdf0e10cSrcweir // we'd want to represent it, fill rule 444cdf0e10cSrcweir // would need to be "non-negative winding 445cdf0e10cSrcweir // number" (and we then would return 446cdf0e10cSrcweir // 'holes' here) 447cdf0e10cSrcweir 448cdf0e10cSrcweir // going for an ugly hack meanwhile 449cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationXor( 450cdf0e10cSrcweir B2DPolyPolygon( 451cdf0e10cSrcweir tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))), 452cdf0e10cSrcweir aCollectedRanges); 453cdf0e10cSrcweir } 454cdf0e10cSrcweir else 455cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationXor( 456cdf0e10cSrcweir maClipPoly, 457cdf0e10cSrcweir aCollectedRanges); 458cdf0e10cSrcweir break; 459cdf0e10cSrcweir case SUBTRACT: 460cdf0e10cSrcweir OSL_ASSERT( !bIsEmpty ); 461cdf0e10cSrcweir 462cdf0e10cSrcweir // first union all pending ranges, subtract en bloc then 463cdf0e10cSrcweir aCollectedRanges = maPendingRanges.solveCrossovers(); 464cdf0e10cSrcweir aCollectedRanges = stripNeutralPolygons(aCollectedRanges); 465cdf0e10cSrcweir aCollectedRanges = stripDispensablePolygons(aCollectedRanges, false); 466cdf0e10cSrcweir 467cdf0e10cSrcweir if( bIsCleared ) 468cdf0e10cSrcweir { 469cdf0e10cSrcweir // not representable, strictly speaking, 470cdf0e10cSrcweir // using polygons with the common even/odd 471cdf0e10cSrcweir // or nonzero winding number fill rule. If 472cdf0e10cSrcweir // we'd want to represent it, fill rule 473cdf0e10cSrcweir // would need to be "non-negative winding 474cdf0e10cSrcweir // number" (and we then would return 475cdf0e10cSrcweir // 'holes' here) 476cdf0e10cSrcweir 477cdf0e10cSrcweir // going for an ugly hack meanwhile 478cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationDiff( 479cdf0e10cSrcweir B2DPolyPolygon( 480cdf0e10cSrcweir tools::createPolygonFromRect(B2DRange(-1E20,-1E20,1E20,1E20))), 481cdf0e10cSrcweir aCollectedRanges); 482cdf0e10cSrcweir } 483cdf0e10cSrcweir else 484cdf0e10cSrcweir maClipPoly = tools::solvePolygonOperationDiff( 485cdf0e10cSrcweir maClipPoly, 486cdf0e10cSrcweir aCollectedRanges); 487cdf0e10cSrcweir break; 488cdf0e10cSrcweir } 489cdf0e10cSrcweir 490cdf0e10cSrcweir maPendingRanges.clear(); 491cdf0e10cSrcweir mePendingOps = UNION; 492cdf0e10cSrcweir } 493cdf0e10cSrcweir 494cdf0e10cSrcweir mutable B2DPolyPolygon maPendingPolygons; 495cdf0e10cSrcweir mutable B2DPolyRange maPendingRanges; 496cdf0e10cSrcweir mutable B2DPolyPolygon maClipPoly; 497cdf0e10cSrcweir mutable Operation mePendingOps; 498cdf0e10cSrcweir }; 499cdf0e10cSrcweir B2DClipState()500cdf0e10cSrcweir B2DClipState::B2DClipState() : 501cdf0e10cSrcweir mpImpl() 502cdf0e10cSrcweir {} 503cdf0e10cSrcweir ~B2DClipState()504cdf0e10cSrcweir B2DClipState::~B2DClipState() 505cdf0e10cSrcweir {} 506cdf0e10cSrcweir B2DClipState(const B2DClipState & rOrig)507cdf0e10cSrcweir B2DClipState::B2DClipState( const B2DClipState& rOrig ) : 508cdf0e10cSrcweir mpImpl(rOrig.mpImpl) 509cdf0e10cSrcweir {} 510cdf0e10cSrcweir B2DClipState(const B2DRange & rRange)511cdf0e10cSrcweir B2DClipState::B2DClipState( const B2DRange& rRange ) : 512cdf0e10cSrcweir mpImpl( ImplB2DClipState(rRange) ) 513cdf0e10cSrcweir {} 514cdf0e10cSrcweir B2DClipState(const B2DPolygon & rPoly)515cdf0e10cSrcweir B2DClipState::B2DClipState( const B2DPolygon& rPoly ) : 516cdf0e10cSrcweir mpImpl( ImplB2DClipState(rPoly) ) 517cdf0e10cSrcweir {} 518cdf0e10cSrcweir B2DClipState(const B2DPolyPolygon & rPolyPoly)519cdf0e10cSrcweir B2DClipState::B2DClipState( const B2DPolyPolygon& rPolyPoly ) : 520cdf0e10cSrcweir mpImpl( ImplB2DClipState(rPolyPoly) ) 521cdf0e10cSrcweir {} 522cdf0e10cSrcweir operator =(const B2DClipState & rRHS)523cdf0e10cSrcweir B2DClipState& B2DClipState::operator=( const B2DClipState& rRHS ) 524cdf0e10cSrcweir { 525cdf0e10cSrcweir mpImpl = rRHS.mpImpl; 526cdf0e10cSrcweir return *this; 527cdf0e10cSrcweir } 528cdf0e10cSrcweir makeUnique()529cdf0e10cSrcweir void B2DClipState::makeUnique() 530cdf0e10cSrcweir { 531cdf0e10cSrcweir mpImpl.make_unique(); 532cdf0e10cSrcweir } 533cdf0e10cSrcweir makeNull()534cdf0e10cSrcweir void B2DClipState::makeNull() 535cdf0e10cSrcweir { 536cdf0e10cSrcweir mpImpl->makeNull(); 537cdf0e10cSrcweir } 538cdf0e10cSrcweir isNull() const539cdf0e10cSrcweir bool B2DClipState::isNull() const 540cdf0e10cSrcweir { 541cdf0e10cSrcweir return mpImpl->isNull(); 542cdf0e10cSrcweir } 543cdf0e10cSrcweir makeClear()544cdf0e10cSrcweir void B2DClipState::makeClear() 545cdf0e10cSrcweir { 546cdf0e10cSrcweir mpImpl->makeClear(); 547cdf0e10cSrcweir } 548cdf0e10cSrcweir isCleared() const549cdf0e10cSrcweir bool B2DClipState::isCleared() const 550cdf0e10cSrcweir { 551cdf0e10cSrcweir return mpImpl->isCleared(); 552cdf0e10cSrcweir } 553cdf0e10cSrcweir operator ==(const B2DClipState & rRHS) const554cdf0e10cSrcweir bool B2DClipState::operator==(const B2DClipState& rRHS) const 555cdf0e10cSrcweir { 556cdf0e10cSrcweir if(mpImpl.same_object(rRHS.mpImpl)) 557cdf0e10cSrcweir return true; 558cdf0e10cSrcweir 559cdf0e10cSrcweir return ((*mpImpl) == (*rRHS.mpImpl)); 560cdf0e10cSrcweir } 561cdf0e10cSrcweir operator !=(const B2DClipState & rRHS) const562cdf0e10cSrcweir bool B2DClipState::operator!=(const B2DClipState& rRHS) const 563cdf0e10cSrcweir { 564cdf0e10cSrcweir return !(*this == rRHS); 565cdf0e10cSrcweir } 566cdf0e10cSrcweir unionRange(const B2DRange & rRange)567cdf0e10cSrcweir void B2DClipState::unionRange(const B2DRange& rRange) 568cdf0e10cSrcweir { 569cdf0e10cSrcweir mpImpl->unionRange(rRange); 570cdf0e10cSrcweir } 571cdf0e10cSrcweir unionPolygon(const B2DPolygon & rPoly)572cdf0e10cSrcweir void B2DClipState::unionPolygon(const B2DPolygon& rPoly) 573cdf0e10cSrcweir { 574cdf0e10cSrcweir mpImpl->unionPolygon(rPoly); 575cdf0e10cSrcweir } 576cdf0e10cSrcweir unionPolyPolygon(const B2DPolyPolygon & rPolyPoly)577cdf0e10cSrcweir void B2DClipState::unionPolyPolygon(const B2DPolyPolygon& rPolyPoly) 578cdf0e10cSrcweir { 579cdf0e10cSrcweir mpImpl->unionPolyPolygon(rPolyPoly); 580cdf0e10cSrcweir } 581cdf0e10cSrcweir unionClipState(const B2DClipState & rState)582cdf0e10cSrcweir void B2DClipState::unionClipState(const B2DClipState& rState) 583cdf0e10cSrcweir { 584cdf0e10cSrcweir mpImpl->unionClipState(*rState.mpImpl); 585cdf0e10cSrcweir } 586cdf0e10cSrcweir intersectRange(const B2DRange & rRange)587cdf0e10cSrcweir void B2DClipState::intersectRange(const B2DRange& rRange) 588cdf0e10cSrcweir { 589cdf0e10cSrcweir mpImpl->intersectRange(rRange); 590cdf0e10cSrcweir } 591cdf0e10cSrcweir intersectPolygon(const B2DPolygon & rPoly)592cdf0e10cSrcweir void B2DClipState::intersectPolygon(const B2DPolygon& rPoly) 593cdf0e10cSrcweir { 594cdf0e10cSrcweir mpImpl->intersectPolygon(rPoly); 595cdf0e10cSrcweir } 596cdf0e10cSrcweir intersectPolyPolygon(const B2DPolyPolygon & rPolyPoly)597cdf0e10cSrcweir void B2DClipState::intersectPolyPolygon(const B2DPolyPolygon& rPolyPoly) 598cdf0e10cSrcweir { 599cdf0e10cSrcweir mpImpl->intersectPolyPolygon(rPolyPoly); 600cdf0e10cSrcweir } 601cdf0e10cSrcweir intersectClipState(const B2DClipState & rState)602cdf0e10cSrcweir void B2DClipState::intersectClipState(const B2DClipState& rState) 603cdf0e10cSrcweir { 604cdf0e10cSrcweir mpImpl->intersectClipState(*rState.mpImpl); 605cdf0e10cSrcweir } 606cdf0e10cSrcweir subtractRange(const B2DRange & rRange)607cdf0e10cSrcweir void B2DClipState::subtractRange(const B2DRange& rRange) 608cdf0e10cSrcweir { 609cdf0e10cSrcweir mpImpl->subtractRange(rRange); 610cdf0e10cSrcweir } 611cdf0e10cSrcweir subtractPolygon(const B2DPolygon & rPoly)612cdf0e10cSrcweir void B2DClipState::subtractPolygon(const B2DPolygon& rPoly) 613cdf0e10cSrcweir { 614cdf0e10cSrcweir mpImpl->subtractPolygon(rPoly); 615cdf0e10cSrcweir } 616cdf0e10cSrcweir subtractPolyPolygon(const B2DPolyPolygon & rPolyPoly)617cdf0e10cSrcweir void B2DClipState::subtractPolyPolygon(const B2DPolyPolygon& rPolyPoly) 618cdf0e10cSrcweir { 619cdf0e10cSrcweir mpImpl->subtractPolyPolygon(rPolyPoly); 620cdf0e10cSrcweir } 621cdf0e10cSrcweir subtractClipState(const B2DClipState & rState)622cdf0e10cSrcweir void B2DClipState::subtractClipState(const B2DClipState& rState) 623cdf0e10cSrcweir { 624cdf0e10cSrcweir mpImpl->subtractClipState(*rState.mpImpl); 625cdf0e10cSrcweir } 626cdf0e10cSrcweir xorRange(const B2DRange & rRange)627cdf0e10cSrcweir void B2DClipState::xorRange(const B2DRange& rRange) 628cdf0e10cSrcweir { 629cdf0e10cSrcweir mpImpl->xorRange(rRange); 630cdf0e10cSrcweir } 631cdf0e10cSrcweir xorPolygon(const B2DPolygon & rPoly)632cdf0e10cSrcweir void B2DClipState::xorPolygon(const B2DPolygon& rPoly) 633cdf0e10cSrcweir { 634cdf0e10cSrcweir mpImpl->xorPolygon(rPoly); 635cdf0e10cSrcweir } 636cdf0e10cSrcweir xorPolyPolygon(const B2DPolyPolygon & rPolyPoly)637cdf0e10cSrcweir void B2DClipState::xorPolyPolygon(const B2DPolyPolygon& rPolyPoly) 638cdf0e10cSrcweir { 639cdf0e10cSrcweir mpImpl->xorPolyPolygon(rPolyPoly); 640cdf0e10cSrcweir } 641cdf0e10cSrcweir xorClipState(const B2DClipState & rState)642cdf0e10cSrcweir void B2DClipState::xorClipState(const B2DClipState& rState) 643cdf0e10cSrcweir { 644cdf0e10cSrcweir mpImpl->xorClipState(*rState.mpImpl); 645cdf0e10cSrcweir } 646cdf0e10cSrcweir getClipPoly() const647cdf0e10cSrcweir B2DPolyPolygon B2DClipState::getClipPoly() const 648cdf0e10cSrcweir { 649cdf0e10cSrcweir return mpImpl->getClipPoly(); 650cdf0e10cSrcweir } 651cdf0e10cSrcweir 652cdf0e10cSrcweir } // end of namespace tools 653cdf0e10cSrcweir } // end of namespace basegfx 654cdf0e10cSrcweir 655cdf0e10cSrcweir // eof 656