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