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