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