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 
34 #include <comphelper/anytostring.hxx>
35 #include <cppuhelper/exc_hlp.hxx>
36 #include <basegfx/numeric/ftools.hxx>
37 #include <basegfx/matrix/b2dhommatrix.hxx>
38 #include <basegfx/polygon/b2dpolypolygontools.hxx>
39 
40 #include <com/sun/star/animations/TransitionType.hpp>
41 #include <com/sun/star/animations/TransitionSubType.hpp>
42 
43 #include "transitionfactory.hxx"
44 #include "transitiontools.hxx"
45 #include "parametricpolypolygonfactory.hxx"
46 #include "animationfactory.hxx"
47 #include "clippingfunctor.hxx"
48 
49 #include <boost/bind.hpp>
50 
51 
52 using namespace ::com::sun::star;
53 
54 namespace slideshow {
55 namespace internal {
56 
57 /***************************************************
58  ***                                             ***
59  ***          Shape Transition Effects           ***
60  ***                                             ***
61  ***************************************************/
62 
63 namespace {
64 
65 class ClippingAnimation : public NumberAnimation
66 {
67 public:
68     ClippingAnimation(
69         const ParametricPolyPolygonSharedPtr&   rPolygon,
70         const ShapeManagerSharedPtr&            rShapeManager,
71         const TransitionInfo&                   rTransitionInfo,
72         bool                                    bDirectionForward,
73         bool                                    bModeIn );
74 
75     ~ClippingAnimation();
76 
77     // Animation interface
78     // -------------------
79     virtual void prefetch( const AnimatableShapeSharedPtr&     rShape,
80                            const ShapeAttributeLayerSharedPtr& rAttrLayer );
81     virtual void start( const AnimatableShapeSharedPtr& 	rShape,
82                         const ShapeAttributeLayerSharedPtr& rAttrLayer );
83     virtual void end();
84 
85     // NumberAnimation interface
86     // -----------------------
87     virtual bool operator()( double nValue );
88     virtual double getUnderlyingValue() const;
89 
90 private:
91     void end_();
92 
93     AnimatableShapeSharedPtr           mpShape;
94     ShapeAttributeLayerSharedPtr       mpAttrLayer;
95     ShapeManagerSharedPtr              mpShapeManager;
96     ClippingFunctor					   maClippingFunctor;
97     bool							   mbSpriteActive;
98 };
99 
100 ClippingAnimation::ClippingAnimation(
101     const ParametricPolyPolygonSharedPtr&   rPolygon,
102     const ShapeManagerSharedPtr&            rShapeManager,
103     const TransitionInfo&                   rTransitionInfo,
104     bool                                    bDirectionForward,
105     bool                                    bModeIn ) :
106         mpShape(),
107         mpAttrLayer(),
108         mpShapeManager( rShapeManager ),
109         maClippingFunctor( rPolygon,
110                            rTransitionInfo,
111                            bDirectionForward,
112                            bModeIn ),
113         mbSpriteActive(false)
114 {
115     ENSURE_OR_THROW(
116         rShapeManager,
117         "ClippingAnimation::ClippingAnimation(): Invalid ShapeManager" );
118 }
119 
120 ClippingAnimation::~ClippingAnimation()
121 {
122     try
123     {
124         end_();
125     }
126     catch (uno::Exception &)
127     {
128         OSL_ENSURE( false, rtl::OUStringToOString(
129                         comphelper::anyToString(
130                             cppu::getCaughtException() ),
131                         RTL_TEXTENCODING_UTF8 ).getStr() );
132     }
133 }
134 
135 void ClippingAnimation::prefetch( const AnimatableShapeSharedPtr&,
136                                   const ShapeAttributeLayerSharedPtr& )
137 {
138 }
139 
140 void ClippingAnimation::start( const AnimatableShapeSharedPtr& 		rShape,
141                                const ShapeAttributeLayerSharedPtr& 	rAttrLayer )
142 {
143     OSL_ENSURE( !mpShape,
144                 "ClippingAnimation::start(): Shape already set" );
145     OSL_ENSURE( !mpAttrLayer,
146                 "ClippingAnimation::start(): Attribute layer already set" );
147 
148     mpShape = rShape;
149     mpAttrLayer = rAttrLayer;
150 
151     ENSURE_OR_THROW( rShape,
152                       "ClippingAnimation::start(): Invalid shape" );
153     ENSURE_OR_THROW( rAttrLayer,
154                       "ClippingAnimation::start(): Invalid attribute layer" );
155 
156     mpShape = rShape;
157     mpAttrLayer = rAttrLayer;
158 
159     if( !mbSpriteActive )
160     {
161         mpShapeManager->enterAnimationMode( mpShape );
162         mbSpriteActive = true;
163     }
164 }
165 
166 void ClippingAnimation::end()
167 {
168     end_();
169 }
170 
171 void ClippingAnimation::end_()
172 {
173     if( mbSpriteActive )
174     {
175         mbSpriteActive = false;
176         mpShapeManager->leaveAnimationMode( mpShape );
177 
178         if( mpShape->isContentChanged() )
179             mpShapeManager->notifyShapeUpdate( mpShape );
180     }
181 }
182 
183 bool ClippingAnimation::operator()( double nValue )
184 {
185     ENSURE_OR_RETURN_FALSE(
186         mpAttrLayer && mpShape,
187         "ClippingAnimation::operator(): Invalid ShapeAttributeLayer" );
188 
189     // set new clip
190     mpAttrLayer->setClip( maClippingFunctor( nValue,
191                                              mpShape->getDomBounds().getRange() ) );
192 
193     if( mpShape->isContentChanged() )
194         mpShapeManager->notifyShapeUpdate( mpShape );
195 
196     return true;
197 }
198 
199 double ClippingAnimation::getUnderlyingValue() const
200 {
201     ENSURE_OR_THROW(
202         mpAttrLayer,
203         "ClippingAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
204 
205     return 0.0;     // though this should be used in concert with
206 				    // ActivitiesFactory::createSimpleActivity, better
207     				// explicitely name our start value.
208 				    // Permissible range for operator() above is [0,1]
209 }
210 
211 } // anon namespace
212 
213 
214 AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
215     const ActivitiesFactory::CommonParameters&          rParms,
216     const AnimatableShapeSharedPtr&                     rShape,
217     const ShapeManagerSharedPtr&                        rShapeManager,
218     const ::basegfx::B2DVector&                         rSlideSize,
219     uno::Reference< animations::XTransitionFilter > const& xTransition )
220 {
221     return createShapeTransition( rParms,
222                                   rShape,
223                                   rShapeManager,
224                                   rSlideSize,
225                                   xTransition,
226                                   xTransition->getTransition(),
227                                   xTransition->getSubtype() );
228 }
229 
230 AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
231     const ActivitiesFactory::CommonParameters& 				rParms,
232     const AnimatableShapeSharedPtr& 						rShape,
233     const ShapeManagerSharedPtr& 							rShapeManager,
234     const ::basegfx::B2DVector&                             rSlideSize,
235     ::com::sun::star::uno::Reference<
236     	::com::sun::star::animations::XTransitionFilter > const& xTransition,
237     sal_Int16               								nType,
238     sal_Int16               								nSubType )
239 {
240     ENSURE_OR_THROW(
241         xTransition.is(),
242         "TransitionFactory::createShapeTransition(): Invalid XTransition" );
243 
244     const TransitionInfo* pTransitionInfo(
245         getTransitionInfo( nType, nSubType ) );
246 
247     AnimationActivitySharedPtr pGeneratedActivity;
248     if( pTransitionInfo != NULL )
249     {
250         switch( pTransitionInfo->meTransitionClass )
251         {
252             default:
253             case TransitionInfo::TRANSITION_INVALID:
254                 OSL_ENSURE( false,
255                             "TransitionFactory::createShapeTransition(): Invalid transition type. "
256                             "Don't ask me for a 0 TransitionType, have no XTransitionFilter node instead!" );
257                 return AnimationActivitySharedPtr();
258 
259 
260             case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON:
261             {
262                 // generate parametric poly-polygon
263                 ParametricPolyPolygonSharedPtr pPoly(
264                     ParametricPolyPolygonFactory::createClipPolyPolygon(
265                         nType, nSubType ) );
266 
267                 // create a clip activity from that
268                 pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
269                     rParms,
270                     NumberAnimationSharedPtr(
271                         new ClippingAnimation(
272                             pPoly,
273                             rShapeManager,
274                             *pTransitionInfo,
275                             xTransition->getDirection(),
276                             xTransition->getMode() ) ),
277                     true );
278             }
279             break;
280 
281             case TransitionInfo::TRANSITION_SPECIAL:
282             {
283                 switch( nType )
284                 {
285                     case animations::TransitionType::RANDOM:
286                     {
287                         // select randomly one of the effects from the
288                         // TransitionFactoryTable
289 
290                         const TransitionInfo* pRandomTransitionInfo( getRandomTransitionInfo() );
291 
292                         ENSURE_OR_THROW( pRandomTransitionInfo != NULL,
293                                           "TransitionFactory::createShapeTransition(): Got invalid random transition info" );
294 
295                         ENSURE_OR_THROW( pRandomTransitionInfo->mnTransitionType != animations::TransitionType::RANDOM,
296                                           "TransitionFactory::createShapeTransition(): Got random again for random input!" );
297 
298                         // and recurse
299                         pGeneratedActivity = createShapeTransition( rParms,
300                                                                     rShape,
301                                                                     rShapeManager,
302                                                                     rSlideSize,
303                                                                     xTransition,
304                                                                     pRandomTransitionInfo->mnTransitionType,
305                                                                     pRandomTransitionInfo->mnTransitionSubType );
306                     }
307                     break;
308 
309                     // TODO(F3): Implement slidewipe for shape
310                     case animations::TransitionType::SLIDEWIPE:
311                     {
312                         sal_Int16 nBarWipeSubType(0);
313                         bool	  bDirectionForward(true);
314 
315                         // map slidewipe to BARWIPE, for now
316                         switch( nSubType )
317                         {
318                             case animations::TransitionSubType::FROMLEFT:
319                                 nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
320                                 bDirectionForward = true;
321                                 break;
322 
323                             case animations::TransitionSubType::FROMRIGHT:
324                                 nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
325                                 bDirectionForward = false;
326                                 break;
327 
328                             case animations::TransitionSubType::FROMTOP:
329                                 nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
330                                 bDirectionForward = true;
331                                 break;
332 
333                             case animations::TransitionSubType::FROMBOTTOM:
334                                 nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
335                                 bDirectionForward = false;
336                                 break;
337 
338                             default:
339                                 ENSURE_OR_THROW( false,
340                                                   "TransitionFactory::createShapeTransition(): Unexpected subtype for SLIDEWIPE" );
341                                 break;
342                         }
343 
344                         // generate parametric poly-polygon
345                         ParametricPolyPolygonSharedPtr pPoly(
346                             ParametricPolyPolygonFactory::createClipPolyPolygon(
347                                 animations::TransitionType::BARWIPE,
348                                 nBarWipeSubType ) );
349 
350                         // create a clip activity from that
351                         pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
352                             rParms,
353                             NumberAnimationSharedPtr(
354                                 new ClippingAnimation(
355                                     pPoly,
356                                     rShapeManager,
357                                     *getTransitionInfo( animations::TransitionType::BARWIPE,
358                                                         nBarWipeSubType ),
359                                     bDirectionForward,
360                                     xTransition->getMode() ) ),
361                             true );
362                     }
363                     break;
364 
365                     default:
366                     {
367                         // TODO(F1): Check whether there's anything left, anyway,
368                         // for _shape_ transitions. AFAIK, there are no special
369                         // effects for shapes...
370 
371                         // for now, map all to fade effect
372                         pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
373                             rParms,
374                             AnimationFactory::createNumberPropertyAnimation(
375                                 ::rtl::OUString(
376                                     RTL_CONSTASCII_USTRINGPARAM("Opacity") ),
377                                 rShape,
378                                 rShapeManager,
379                                 rSlideSize ),
380                             xTransition->getMode() );
381                     }
382                     break;
383                 }
384             }
385             break;
386         }
387     }
388 
389     if( !pGeneratedActivity )
390     {
391         // No animation generated, maybe no table entry for given
392         // transition?
393         OSL_TRACE(
394             "TransitionFactory::createShapeTransition(): Unknown type/subtype (%d/%d) "
395             "combination encountered",
396             xTransition->getTransition(),
397             xTransition->getSubtype() );
398         OSL_ENSURE(
399             false,
400             "TransitionFactory::createShapeTransition(): Unknown type/subtype "
401             "combination encountered" );
402     }
403 
404     return pGeneratedActivity;
405 }
406 
407 }
408 }
409