1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <tools/diagnose_ex.h>
22 
23 #include <cppuhelper/exc_hlp.hxx>
24 #include <basegfx/numeric/ftools.hxx>
25 #include <basegfx/matrix/b2dhommatrix.hxx>
26 #include <basegfx/polygon/b2dpolypolygontools.hxx>
27 #include <sal/log.hxx>
28 
29 #include <com/sun/star/animations/TransitionType.hpp>
30 #include <com/sun/star/animations/TransitionSubType.hpp>
31 
32 #include <transitionfactory.hxx>
33 #include "transitionfactorytab.hxx"
34 #include "transitiontools.hxx"
35 #include "parametricpolypolygonfactory.hxx"
36 #include <animationfactory.hxx>
37 #include "clippingfunctor.hxx"
38 
39 using namespace ::com::sun::star;
40 
41 namespace slideshow {
42 namespace internal {
43 
44 /***************************************************
45  ***                                             ***
46  ***          Shape Transition Effects           ***
47  ***                                             ***
48  ***************************************************/
49 
50 namespace {
51 
52 class ClippingAnimation : public NumberAnimation
53 {
54 public:
55     ClippingAnimation(
56         const ParametricPolyPolygonSharedPtr&   rPolygon,
57         const ShapeManagerSharedPtr&            rShapeManager,
58         const TransitionInfo&                   rTransitionInfo,
59         bool                                    bDirectionForward,
60         bool                                    bModeIn );
61 
62     virtual ~ClippingAnimation() override;
63 
64     // Animation interface
65 
66     virtual void prefetch() override;
67     virtual void start( const AnimatableShapeSharedPtr&     rShape,
68                         const ShapeAttributeLayerSharedPtr& rAttrLayer ) override;
69     virtual void end() override;
70 
71     // NumberAnimation interface
72 
73     virtual bool operator()( double nValue ) override;
74     virtual double getUnderlyingValue() const override;
75 
76 private:
77     void end_();
78 
79     AnimatableShapeSharedPtr           mpShape;
80     ShapeAttributeLayerSharedPtr       mpAttrLayer;
81     ShapeManagerSharedPtr              mpShapeManager;
82     ClippingFunctor                    maClippingFunctor;
83     bool                               mbSpriteActive;
84 };
85 
ClippingAnimation(const ParametricPolyPolygonSharedPtr & rPolygon,const ShapeManagerSharedPtr & rShapeManager,const TransitionInfo & rTransitionInfo,bool bDirectionForward,bool bModeIn)86 ClippingAnimation::ClippingAnimation(
87     const ParametricPolyPolygonSharedPtr&   rPolygon,
88     const ShapeManagerSharedPtr&            rShapeManager,
89     const TransitionInfo&                   rTransitionInfo,
90     bool                                    bDirectionForward,
91     bool                                    bModeIn ) :
92         mpShape(),
93         mpAttrLayer(),
94         mpShapeManager( rShapeManager ),
95         maClippingFunctor( rPolygon,
96                            rTransitionInfo,
97                            bDirectionForward,
98                            bModeIn ),
99         mbSpriteActive(false)
100 {
101     ENSURE_OR_THROW(
102         rShapeManager,
103         "ClippingAnimation::ClippingAnimation(): Invalid ShapeManager" );
104 }
105 
~ClippingAnimation()106 ClippingAnimation::~ClippingAnimation()
107 {
108     try
109     {
110         end_();
111     }
112     catch (const uno::Exception&)
113     {
114         TOOLS_WARN_EXCEPTION("slideshow", "");
115     }
116 }
117 
prefetch()118 void ClippingAnimation::prefetch()
119 {
120 }
121 
start(const AnimatableShapeSharedPtr & rShape,const ShapeAttributeLayerSharedPtr & rAttrLayer)122 void ClippingAnimation::start( const AnimatableShapeSharedPtr&      rShape,
123                                const ShapeAttributeLayerSharedPtr&  rAttrLayer )
124 {
125     OSL_ENSURE( !mpShape,
126                 "ClippingAnimation::start(): Shape already set" );
127     OSL_ENSURE( !mpAttrLayer,
128                 "ClippingAnimation::start(): Attribute layer already set" );
129     ENSURE_OR_THROW( rShape,
130                       "ClippingAnimation::start(): Invalid shape" );
131     ENSURE_OR_THROW( rAttrLayer,
132                       "ClippingAnimation::start(): Invalid attribute layer" );
133 
134     mpShape = rShape;
135     mpAttrLayer = rAttrLayer;
136 
137     if( !mbSpriteActive )
138     {
139         mpShapeManager->enterAnimationMode( mpShape );
140         mbSpriteActive = true;
141     }
142 }
143 
end()144 void ClippingAnimation::end()
145 {
146     end_();
147 }
148 
end_()149 void ClippingAnimation::end_()
150 {
151     if( mbSpriteActive )
152     {
153         mbSpriteActive = false;
154         mpShapeManager->leaveAnimationMode( mpShape );
155 
156         if( mpShape->isContentChanged() )
157             mpShapeManager->notifyShapeUpdate( mpShape );
158     }
159 }
160 
operator ()(double nValue)161 bool ClippingAnimation::operator()( double nValue )
162 {
163     ENSURE_OR_RETURN_FALSE(
164         mpAttrLayer && mpShape,
165         "ClippingAnimation::operator(): Invalid ShapeAttributeLayer" );
166 
167     // set new clip
168     mpAttrLayer->setClip( maClippingFunctor( nValue,
169                                              mpShape->getDomBounds().getRange() ) );
170 
171     if( mpShape->isContentChanged() )
172         mpShapeManager->notifyShapeUpdate( mpShape );
173 
174     return true;
175 }
176 
getUnderlyingValue() const177 double ClippingAnimation::getUnderlyingValue() const
178 {
179     ENSURE_OR_THROW(
180         mpAttrLayer,
181         "ClippingAnimation::getUnderlyingValue(): Invalid ShapeAttributeLayer" );
182 
183     return 0.0;     // though this should be used in concert with
184                     // ActivitiesFactory::createSimpleActivity, better
185                     // explicitly name our start value.
186                     // Permissible range for operator() above is [0,1]
187 }
188 
createShapeTransitionByType(const ActivitiesFactory::CommonParameters & rParms,const AnimatableShapeSharedPtr & rShape,const ShapeManagerSharedPtr & rShapeManager,const::basegfx::B2DVector & rSlideSize,css::uno::Reference<css::animations::XTransitionFilter> const & xTransition,sal_Int16 nType,sal_Int16 nSubType)189 AnimationActivitySharedPtr createShapeTransitionByType(
190     const ActivitiesFactory::CommonParameters&              rParms,
191     const AnimatableShapeSharedPtr&                         rShape,
192     const ShapeManagerSharedPtr&                            rShapeManager,
193     const ::basegfx::B2DVector&                             rSlideSize,
194     css::uno::Reference< css::animations::XTransitionFilter > const& xTransition,
195     sal_Int16                                               nType,
196     sal_Int16                                               nSubType )
197 {
198     ENSURE_OR_THROW(
199         xTransition.is(),
200         "createShapeTransitionByType(): Invalid XTransition" );
201 
202     const TransitionInfo* pTransitionInfo(
203         getTransitionInfo( nType, nSubType ) );
204 
205     AnimationActivitySharedPtr pGeneratedActivity;
206     if( pTransitionInfo != nullptr )
207     {
208         switch( pTransitionInfo->meTransitionClass )
209         {
210             default:
211             case TransitionInfo::TRANSITION_INVALID:
212                 OSL_FAIL( "createShapeTransitionByType(): Invalid transition type. "
213                             "Don't ask me for a 0 TransitionType, have no XTransitionFilter node instead!" );
214                 return AnimationActivitySharedPtr();
215 
216 
217             case TransitionInfo::TRANSITION_CLIP_POLYPOLYGON:
218             {
219                 // generate parametric poly-polygon
220                 ParametricPolyPolygonSharedPtr pPoly(
221                     ParametricPolyPolygonFactory::createClipPolyPolygon(
222                         nType, nSubType ) );
223 
224                 // create a clip activity from that
225                 pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
226                     rParms,
227                     NumberAnimationSharedPtr(
228                         new ClippingAnimation(
229                             pPoly,
230                             rShapeManager,
231                             *pTransitionInfo,
232                             xTransition->getDirection(),
233                             xTransition->getMode() ) ),
234                     true );
235             }
236             break;
237 
238             case TransitionInfo::TRANSITION_SPECIAL:
239             {
240                 switch( nType )
241                 {
242                     case animations::TransitionType::RANDOM:
243                     {
244                         // select randomly one of the effects from the
245                         // TransitionFactoryTable
246 
247                         const TransitionInfo* pRandomTransitionInfo( getRandomTransitionInfo() );
248 
249                         ENSURE_OR_THROW( pRandomTransitionInfo != nullptr,
250                                           "createShapeTransitionByType(): Got invalid random transition info" );
251 
252                         ENSURE_OR_THROW( pRandomTransitionInfo->mnTransitionType != animations::TransitionType::RANDOM,
253                                           "createShapeTransitionByType(): Got random again for random input!" );
254 
255                         // and recurse
256                         pGeneratedActivity = createShapeTransitionByType( rParms,
257                                                                     rShape,
258                                                                     rShapeManager,
259                                                                     rSlideSize,
260                                                                     xTransition,
261                                                                     pRandomTransitionInfo->mnTransitionType,
262                                                                     pRandomTransitionInfo->mnTransitionSubType );
263                     }
264                     break;
265 
266                     // TODO(F3): Implement slidewipe for shape
267                     case animations::TransitionType::SLIDEWIPE:
268                     {
269                         sal_Int16 nBarWipeSubType(0);
270                         bool      bDirectionForward(true);
271 
272                         // map slidewipe to BARWIPE, for now
273                         switch( nSubType )
274                         {
275                             case animations::TransitionSubType::FROMLEFT:
276                                 nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
277                                 bDirectionForward = true;
278                                 break;
279 
280                             case animations::TransitionSubType::FROMRIGHT:
281                                 nBarWipeSubType = animations::TransitionSubType::LEFTTORIGHT;
282                                 bDirectionForward = false;
283                                 break;
284 
285                             case animations::TransitionSubType::FROMTOP:
286                                 nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
287                                 bDirectionForward = true;
288                                 break;
289 
290                             case animations::TransitionSubType::FROMBOTTOM:
291                                 nBarWipeSubType = animations::TransitionSubType::TOPTOBOTTOM;
292                                 bDirectionForward = false;
293                                 break;
294 
295                             default:
296                                 ENSURE_OR_THROW( false,
297                                                   "createShapeTransitionByType(): Unexpected subtype for SLIDEWIPE" );
298                                 break;
299                         }
300 
301                         // generate parametric poly-polygon
302                         ParametricPolyPolygonSharedPtr pPoly(
303                             ParametricPolyPolygonFactory::createClipPolyPolygon(
304                                 animations::TransitionType::BARWIPE,
305                                 nBarWipeSubType ) );
306 
307                         // create a clip activity from that
308                         pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
309                             rParms,
310                             NumberAnimationSharedPtr(
311                                 new ClippingAnimation(
312                                     pPoly,
313                                     rShapeManager,
314                                     *getTransitionInfo( animations::TransitionType::BARWIPE,
315                                                         nBarWipeSubType ),
316                                     bDirectionForward,
317                                     xTransition->getMode() ) ),
318                             true );
319                     }
320                     break;
321 
322                     default:
323                     {
324                         // TODO(F1): Check whether there's anything left, anyway,
325                         // for _shape_ transitions. AFAIK, there are no special
326                         // effects for shapes...
327 
328                         // for now, map all to fade effect
329                         pGeneratedActivity = ActivitiesFactory::createSimpleActivity(
330                             rParms,
331                             AnimationFactory::createNumberPropertyAnimation(
332                                 "Opacity",
333                                 rShape,
334                                 rShapeManager,
335                                 rSlideSize ),
336                             xTransition->getMode() );
337                     }
338                     break;
339                 }
340             }
341             break;
342         }
343     }
344 
345     if( !pGeneratedActivity )
346     {
347         // No animation generated, maybe no table entry for given
348         // transition?
349         SAL_WARN("slideshow",
350             "createShapeTransitionByType(): Unknown type/subtype combination encountered: "
351             << xTransition->getTransition() << " " << xTransition->getSubtype() );
352     }
353 
354     return pGeneratedActivity;
355 }
356 
357 } // anon namespace
358 
createShapeTransition(const ActivitiesFactory::CommonParameters & rParms,const AnimatableShapeSharedPtr & rShape,const ShapeManagerSharedPtr & rShapeManager,const::basegfx::B2DVector & rSlideSize,uno::Reference<animations::XTransitionFilter> const & xTransition)359 AnimationActivitySharedPtr TransitionFactory::createShapeTransition(
360     const ActivitiesFactory::CommonParameters&          rParms,
361     const AnimatableShapeSharedPtr&                     rShape,
362     const ShapeManagerSharedPtr&                        rShapeManager,
363     const ::basegfx::B2DVector&                         rSlideSize,
364     uno::Reference< animations::XTransitionFilter > const& xTransition )
365 {
366     return createShapeTransitionByType( rParms,
367                                   rShape,
368                                   rShapeManager,
369                                   rSlideSize,
370                                   xTransition,
371                                   xTransition->getTransition(),
372                                   xTransition->getSubtype() );
373 }
374 
375 }
376 }
377 
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
379