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