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