1*70f497fbSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*70f497fbSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*70f497fbSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*70f497fbSAndrew Rist * distributed with this work for additional information 6*70f497fbSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*70f497fbSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*70f497fbSAndrew Rist * "License"); you may not use this file except in compliance 9*70f497fbSAndrew Rist * with the License. You may obtain a copy of the License at 10*70f497fbSAndrew Rist * 11*70f497fbSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*70f497fbSAndrew Rist * 13*70f497fbSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*70f497fbSAndrew Rist * software distributed under the License is distributed on an 15*70f497fbSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*70f497fbSAndrew Rist * KIND, either express or implied. See the License for the 17*70f497fbSAndrew Rist * specific language governing permissions and limitations 18*70f497fbSAndrew Rist * under the License. 19*70f497fbSAndrew Rist * 20*70f497fbSAndrew Rist *************************************************************/ 21*70f497fbSAndrew Rist 22*70f497fbSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_slideshow.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <canvas/debug.hxx> 28cdf0e10cSrcweir #include <tools/diagnose_ex.h> 29cdf0e10cSrcweir #include "clippingfunctor.hxx" 30cdf0e10cSrcweir #include "transitiontools.hxx" 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 33cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx> 34cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 35cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 36cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx> 37cdf0e10cSrcweir 38cdf0e10cSrcweir namespace slideshow 39cdf0e10cSrcweir { 40cdf0e10cSrcweir namespace internal 41cdf0e10cSrcweir { ClippingFunctor(const ParametricPolyPolygonSharedPtr & rPolygon,const TransitionInfo & rTransitionInfo,bool bDirectionForward,bool bModeIn)42cdf0e10cSrcweir ClippingFunctor::ClippingFunctor(const ParametricPolyPolygonSharedPtr& rPolygon, 43cdf0e10cSrcweir const TransitionInfo& rTransitionInfo, 44cdf0e10cSrcweir bool bDirectionForward, 45cdf0e10cSrcweir bool bModeIn ) : 46cdf0e10cSrcweir mpParametricPoly( rPolygon ), 47cdf0e10cSrcweir maStaticTransformation(), 48cdf0e10cSrcweir // AW: Not needed 49cdf0e10cSrcweir // maBackgroundRect( createUnitRect() ), 50cdf0e10cSrcweir mbForwardParameterSweep( true ), 51cdf0e10cSrcweir mbSubtractPolygon( false ), 52cdf0e10cSrcweir mbScaleIsotrophically( rTransitionInfo.mbScaleIsotrophically ), 53cdf0e10cSrcweir mbFlip(false) 54cdf0e10cSrcweir { 55cdf0e10cSrcweir ENSURE_OR_THROW( rPolygon, 56cdf0e10cSrcweir "ClippingFunctor::ClippingFunctor(): Invalid parametric polygon" ); 57cdf0e10cSrcweir 58cdf0e10cSrcweir // maBackgroundRect serves as the minuent when 59cdf0e10cSrcweir // subtracting a given clip polygon from the 60cdf0e10cSrcweir // background. To speed up the clipper algo, avoid 61cdf0e10cSrcweir // actual intersections of the generated 62cdf0e10cSrcweir // poly-polygon with the minuent - i.e. choose the 63cdf0e10cSrcweir // polygon to subtract from sufficiently large. 64cdf0e10cSrcweir 65cdf0e10cSrcweir // blow up unit rect to (-1,-1),(2,2) 66cdf0e10cSrcweir // AW: Not needed, just use range 67cdf0e10cSrcweir // ::basegfx::B2DHomMatrix aMatrix; 68cdf0e10cSrcweir // aMatrix.scale(3.0,3.0); 69cdf0e10cSrcweir // aMatrix.translate(-1.0,-1.0); 70cdf0e10cSrcweir // maBackgroundRect.transform( aMatrix ); 71cdf0e10cSrcweir 72cdf0e10cSrcweir // extract modification info from maTransitionInfo 73cdf0e10cSrcweir // ----------------------------------------------- 74cdf0e10cSrcweir 75cdf0e10cSrcweir // perform general transformations _before_ the reverse 76cdf0e10cSrcweir // mode changes. This allows the Transition table to be 77cdf0e10cSrcweir // filled more constitently (otherwise, when e.g. rotating 78cdf0e10cSrcweir // a clip 90 degrees, the REVERSEMETHOD_FLIP_X becomes 79cdf0e10cSrcweir // REVERSEMETHOD_FLIP_Y instead) 80cdf0e10cSrcweir if (rTransitionInfo.mnRotationAngle != 0.0 || 81cdf0e10cSrcweir rTransitionInfo.mnScaleX != 1.0 || 82cdf0e10cSrcweir rTransitionInfo.mnScaleY != 1.0) 83cdf0e10cSrcweir { 84cdf0e10cSrcweir maStaticTransformation.translate( -0.5, -0.5 ); 85cdf0e10cSrcweir // apply further transformations: 86cdf0e10cSrcweir if (rTransitionInfo.mnRotationAngle != 0.0) 87cdf0e10cSrcweir { 88cdf0e10cSrcweir maStaticTransformation.rotate( 89cdf0e10cSrcweir basegfx::deg2rad(rTransitionInfo.mnRotationAngle) ); 90cdf0e10cSrcweir } 91cdf0e10cSrcweir if (rTransitionInfo.mnScaleX != 1.0 || 92cdf0e10cSrcweir rTransitionInfo.mnScaleY != 1.0) 93cdf0e10cSrcweir { 94cdf0e10cSrcweir maStaticTransformation.scale( 95cdf0e10cSrcweir rTransitionInfo.mnScaleX, 96cdf0e10cSrcweir rTransitionInfo.mnScaleY ); 97cdf0e10cSrcweir } 98cdf0e10cSrcweir maStaticTransformation.translate( 0.5, 0.5 ); 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir if( !bDirectionForward ) 102cdf0e10cSrcweir { 103cdf0e10cSrcweir // Client has requested reversed 104cdf0e10cSrcweir // direction. Apply TransitionInfo's choice 105cdf0e10cSrcweir // for that 106cdf0e10cSrcweir switch( rTransitionInfo.meReverseMethod ) 107cdf0e10cSrcweir { 108cdf0e10cSrcweir default: 109cdf0e10cSrcweir ENSURE_OR_THROW( 110cdf0e10cSrcweir false, 111cdf0e10cSrcweir "TransitionFactory::TransitionFactory(): Unexpected reverse method" ); 112cdf0e10cSrcweir break; 113cdf0e10cSrcweir 114cdf0e10cSrcweir case TransitionInfo::REVERSEMETHOD_IGNORE: 115cdf0e10cSrcweir break; 116cdf0e10cSrcweir 117cdf0e10cSrcweir case TransitionInfo::REVERSEMETHOD_INVERT_SWEEP: 118cdf0e10cSrcweir mbForwardParameterSweep = !mbForwardParameterSweep; 119cdf0e10cSrcweir break; 120cdf0e10cSrcweir 121cdf0e10cSrcweir case TransitionInfo::REVERSEMETHOD_SUBTRACT_POLYGON: 122cdf0e10cSrcweir mbSubtractPolygon = !mbSubtractPolygon; 123cdf0e10cSrcweir break; 124cdf0e10cSrcweir 125cdf0e10cSrcweir case TransitionInfo::REVERSEMETHOD_SUBTRACT_AND_INVERT: 126cdf0e10cSrcweir mbForwardParameterSweep = !mbForwardParameterSweep; 127cdf0e10cSrcweir mbSubtractPolygon = !mbSubtractPolygon; 128cdf0e10cSrcweir break; 129cdf0e10cSrcweir 130cdf0e10cSrcweir case TransitionInfo::REVERSEMETHOD_ROTATE_180: 131cdf0e10cSrcweir maStaticTransformation = basegfx::tools::createRotateAroundPoint(0.5, 0.5, M_PI) 132cdf0e10cSrcweir * maStaticTransformation; 133cdf0e10cSrcweir break; 134cdf0e10cSrcweir 135cdf0e10cSrcweir case TransitionInfo::REVERSEMETHOD_FLIP_X: 136cdf0e10cSrcweir maStaticTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(-1.0, 1.0, 1.0, 0.0) 137cdf0e10cSrcweir * maStaticTransformation; 138cdf0e10cSrcweir mbFlip = true; 139cdf0e10cSrcweir break; 140cdf0e10cSrcweir 141cdf0e10cSrcweir case TransitionInfo::REVERSEMETHOD_FLIP_Y: 142cdf0e10cSrcweir maStaticTransformation = basegfx::tools::createScaleTranslateB2DHomMatrix(1.0, -1.0, 0.0, 1.0) 143cdf0e10cSrcweir * maStaticTransformation; 144cdf0e10cSrcweir mbFlip = true; 145cdf0e10cSrcweir break; 146cdf0e10cSrcweir } 147cdf0e10cSrcweir } 148cdf0e10cSrcweir 149cdf0e10cSrcweir if( !bModeIn ) 150cdf0e10cSrcweir { 151cdf0e10cSrcweir // client has requested 'out' mode. Apply 152cdf0e10cSrcweir // TransitionInfo's method of choice 153cdf0e10cSrcweir if( rTransitionInfo.mbOutInvertsSweep ) 154cdf0e10cSrcweir mbForwardParameterSweep = !mbForwardParameterSweep; 155cdf0e10cSrcweir else 156cdf0e10cSrcweir mbSubtractPolygon = !mbSubtractPolygon; 157cdf0e10cSrcweir } 158cdf0e10cSrcweir } 159cdf0e10cSrcweir operator ()(double nValue,const::basegfx::B2DSize & rTargetSize)160cdf0e10cSrcweir ::basegfx::B2DPolyPolygon ClippingFunctor::operator()( double nValue, 161cdf0e10cSrcweir const ::basegfx::B2DSize& rTargetSize ) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir // modify clip polygon according to static 164cdf0e10cSrcweir // transformation plus current shape size 165cdf0e10cSrcweir ::basegfx::B2DHomMatrix aMatrix( maStaticTransformation ); 166cdf0e10cSrcweir 167cdf0e10cSrcweir // retrieve current clip polygon 168cdf0e10cSrcweir ::basegfx::B2DPolyPolygon aClipPoly = (*mpParametricPoly)( 169cdf0e10cSrcweir mbForwardParameterSweep ? nValue : 1.0 - nValue ); 170cdf0e10cSrcweir 171cdf0e10cSrcweir // TODO(Q4): workaround here, better be fixed in cppcanvas 172cdf0e10cSrcweir if (aClipPoly.count() == 0) 173cdf0e10cSrcweir aClipPoly.append( basegfx::B2DPolygon() ); 174cdf0e10cSrcweir 175cdf0e10cSrcweir if (mbFlip) 176cdf0e10cSrcweir aClipPoly.flip(); 177cdf0e10cSrcweir 178cdf0e10cSrcweir // currently, clipper cannot cope with curves. Subdivide first 179cdf0e10cSrcweir // AW: Should be no longer necessary; clipping tools are now bezier-safe 180cdf0e10cSrcweir // if( aClipPoly.areControlPointsUsed() ) 181cdf0e10cSrcweir // aClipPoly = ::basegfx::tools::adaptiveSubdivideByAngle(aClipPoly); 182cdf0e10cSrcweir 183cdf0e10cSrcweir if( mbSubtractPolygon ) 184cdf0e10cSrcweir { 185cdf0e10cSrcweir // subtract given polygon from background 186cdf0e10cSrcweir // rect. Do that before any transformations. 187cdf0e10cSrcweir 188cdf0e10cSrcweir // calc maBackgroundRect \ aClipPoly 189cdf0e10cSrcweir // ================================= 190cdf0e10cSrcweir 191cdf0e10cSrcweir // AW: Simplified 192cdf0e10cSrcweir // use a range with fixed size (-1,-1),(2,2) 193cdf0e10cSrcweir const basegfx::B2DRange aBackgroundRange(-1, -1, 2, 2); 194cdf0e10cSrcweir const basegfx::B2DRange aClipPolyRange(aClipPoly.getB2DRange()); 195cdf0e10cSrcweir 196cdf0e10cSrcweir if(aBackgroundRange.isInside(aClipPolyRange)) 197cdf0e10cSrcweir { 198cdf0e10cSrcweir // combine polygons; make the clip polygon the hole 199cdf0e10cSrcweir aClipPoly = ::basegfx::tools::correctOrientations(aClipPoly); 200cdf0e10cSrcweir aClipPoly.flip(); 201cdf0e10cSrcweir aClipPoly.insert(0, basegfx::tools::createPolygonFromRect(aBackgroundRange)); 202cdf0e10cSrcweir } 203cdf0e10cSrcweir else 204cdf0e10cSrcweir { 205cdf0e10cSrcweir // when not completely inside aBackgroundRange clipping is needed 206cdf0e10cSrcweir // substract aClipPoly from aBackgroundRange 207cdf0e10cSrcweir const basegfx::B2DPolyPolygon aBackgroundPolyPoly(basegfx::tools::createPolygonFromRect(aBackgroundRange)); 208cdf0e10cSrcweir aClipPoly = basegfx::tools::solvePolygonOperationDiff(aBackgroundPolyPoly, aClipPoly); 209cdf0e10cSrcweir } 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir // scale polygon up to current shape size 213cdf0e10cSrcweir if( mbScaleIsotrophically ) 214cdf0e10cSrcweir { 215cdf0e10cSrcweir const double nScale( ::std::max( rTargetSize.getX(), 216cdf0e10cSrcweir rTargetSize.getY() ) ); 217cdf0e10cSrcweir aMatrix.scale( nScale, nScale ); 218cdf0e10cSrcweir aMatrix.translate( -(nScale-rTargetSize.getX())/2.0, 219cdf0e10cSrcweir -(nScale-rTargetSize.getY())/2.0 ); 220cdf0e10cSrcweir } 221cdf0e10cSrcweir else 222cdf0e10cSrcweir { 223cdf0e10cSrcweir aMatrix.scale( rTargetSize.getX(), 224cdf0e10cSrcweir rTargetSize.getY() ); 225cdf0e10cSrcweir } 226cdf0e10cSrcweir 227cdf0e10cSrcweir // apply cumulative transformation to clip polygon 228cdf0e10cSrcweir aClipPoly.transform( aMatrix ); 229cdf0e10cSrcweir 230cdf0e10cSrcweir return aClipPoly; 231cdf0e10cSrcweir } 232cdf0e10cSrcweir 233cdf0e10cSrcweir } 234cdf0e10cSrcweir } 235