1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/uno/XComponentContext.hpp>
21 #include <com/sun/star/lang/XTypeProvider.hpp>
22 #include <com/sun/star/animations/XIterateContainer.hpp>
23 #include <com/sun/star/presentation/ParagraphTarget.hpp>
24 #include <com/sun/star/registry/XRegistryKey.hpp>
25 #include <com/sun/star/drawing/XShape.hpp>
26 #include <com/sun/star/animations/AnimationNodeType.hpp>
27 #include <com/sun/star/animations/XAnimate.hpp>
29 #include <unordered_map>
32 #include "targetpropertiescreator.hxx"
41 // Vector containing all properties for a given shape
42 typedef ::std::vector
< beans::NamedValue
> VectorOfNamedValues
;
46 This key contains both XShape reference and a paragraph
47 index, as we somehow have to handle shape and paragraph
48 targets with the same data structure.
53 uno::Reference
< drawing::XShape
> mxRef
;
57 If this is a pure shape target, mnParagraphIndex is
60 sal_Int16 mnParagraphIndex
;
62 /// Comparison needed for unordered_map
63 bool operator==( const ShapeHashKey
& rRHS
) const
65 return mxRef
== rRHS
.mxRef
&& mnParagraphIndex
== rRHS
.mnParagraphIndex
;
69 // A hash functor for ShapeHashKey objects
72 ::std::size_t operator()( const ShapeHashKey
& rKey
) const
74 // TODO(P2): Maybe a better hash function would be to
75 // spread mnParagraphIndex to 32 bit: a0b0c0d0e0... Hakmem
76 // should have a formula.
79 // x = (x & 0x0000FF00) << 8) | (x >> 8) & 0x0000FF00 | x & 0xFF0000FF;
80 // x = (x & 0x00F000F0) << 4) | (x >> 4) & 0x00F000F0 | x & 0xF00FF00F;
81 // x = (x & 0x0C0C0C0C) << 2) | (x >> 2) & 0x0C0C0C0C | x & 0xC3C3C3C3;
82 // x = (x & 0x22222222) << 1) | (x >> 1) & 0x22222222 | x & 0x99999999;
84 // Costs about 17 cycles on a RISC machine with infinite
85 // instruction level parallelism (~42 basic
86 // instructions). Thus I truly doubt this pays off...
87 return reinterpret_cast< ::std::size_t >(rKey
.mxRef
.get()) ^ (rKey
.mnParagraphIndex
<< 16L);
91 // A hash map which maps a XShape to the corresponding vector of initial properties
92 typedef std::unordered_map
< ShapeHashKey
, VectorOfNamedValues
, ShapeKeyHasher
> XShapeHash
;
98 explicit NodeFunctor( XShapeHash
& rShapeHash
) :
99 mrShapeHash( rShapeHash
),
101 mnParagraphIndex( -1 )
105 NodeFunctor( XShapeHash
& rShapeHash
,
106 const uno::Reference
< drawing::XShape
>& rTargetShape
,
107 sal_Int16 nParagraphIndex
) :
108 mrShapeHash( rShapeHash
),
109 mxTargetShape( rTargetShape
),
110 mnParagraphIndex( nParagraphIndex
)
114 void operator()( const uno::Reference
< animations::XAnimationNode
>& xNode
) const
118 OSL_FAIL( "AnimCore: NodeFunctor::operator(): invalid XAnimationNode" );
122 uno::Reference
< drawing::XShape
> xTargetShape( mxTargetShape
);
123 sal_Int16
nParagraphIndex( mnParagraphIndex
);
125 switch( xNode
->getType() )
127 case animations::AnimationNodeType::ITERATE
:
129 // extract target shape from iterate node
130 // (will override the target for all children)
132 uno::Reference
< animations::XIterateContainer
> xIterNode( xNode
,
135 // TODO(E1): I'm not too sure what to expect here...
136 if( !xIterNode
->getTarget().hasValue() )
138 OSL_FAIL( "animcore: NodeFunctor::operator(): no target on ITERATE node" );
142 xTargetShape
.set( xIterNode
->getTarget(),
145 if( !xTargetShape
.is() )
147 ::com::sun::star::presentation::ParagraphTarget aTarget
;
149 // no shape provided. Maybe a ParagraphTarget?
150 if( !(xIterNode
->getTarget() >>= aTarget
) )
152 OSL_FAIL( "animcore: NodeFunctor::operator(): could not extract any "
153 "target information" );
157 xTargetShape
= aTarget
.Shape
;
158 nParagraphIndex
= aTarget
.Paragraph
;
160 if( !xTargetShape
.is() )
162 OSL_FAIL( "animcore: NodeFunctor::operator(): invalid shape in ParagraphTarget" );
167 // FALLTHROUGH intended
168 case animations::AnimationNodeType::PAR
:
169 // FALLTHROUGH intended
170 case animations::AnimationNodeType::SEQ
:
172 NodeFunctor
aFunctor( mrShapeHash
,
175 if( !for_each_childNode( xNode
, aFunctor
) )
177 OSL_FAIL( "AnimCore: NodeFunctor::operator(): child node iteration failed, "
178 "or extraneous container nodes encountered" );
183 case animations::AnimationNodeType::CUSTOM
:
184 // FALLTHROUGH intended
185 case animations::AnimationNodeType::ANIMATE
:
186 // FALLTHROUGH intended
187 case animations::AnimationNodeType::ANIMATEMOTION
:
188 // FALLTHROUGH intended
189 case animations::AnimationNodeType::ANIMATECOLOR
:
190 // FALLTHROUGH intended
191 case animations::AnimationNodeType::ANIMATETRANSFORM
:
192 // FALLTHROUGH intended
193 case animations::AnimationNodeType::TRANSITIONFILTER
:
194 // FALLTHROUGH intended
195 case animations::AnimationNodeType::AUDIO
:
196 // FALLTHROUGH intended
198 // ignore this node, no valuable content for now.
201 case animations::AnimationNodeType::SET
:
203 // evaluate set node content
204 uno::Reference
< animations::XAnimate
> xAnimateNode( xNode
,
207 if( !xAnimateNode
.is() )
208 break; // invalid node
210 // determine target shape (if any)
211 ShapeHashKey aTarget
;
212 if( xTargetShape
.is() )
214 // override target shape with parent-supplied
215 aTarget
.mxRef
= xTargetShape
;
216 aTarget
.mnParagraphIndex
= nParagraphIndex
;
220 // no parent-supplied target, retrieve
222 if( (xAnimateNode
->getTarget() >>= aTarget
.mxRef
) )
224 // pure shape target - set paragraph
226 aTarget
.mnParagraphIndex
= -1;
230 // not a pure shape target - maybe a
232 presentation::ParagraphTarget aUnoTarget
;
234 if( !(xAnimateNode
->getTarget() >>= aUnoTarget
) )
236 OSL_FAIL( "AnimCore: NodeFunctor::operator(): unknown target type encountered" );
240 aTarget
.mxRef
= aUnoTarget
.Shape
;
241 aTarget
.mnParagraphIndex
= aUnoTarget
.Paragraph
;
245 if( !aTarget
.mxRef
.is() )
247 OSL_FAIL( "AnimCore: NodeFunctor::operator(): Found target, but XShape is NULL" );
248 break; // invalid target XShape
251 // check whether we already have an entry for
252 // this target (we only take the first set
253 // effect for every shape)
254 XShapeHash::const_iterator aIter
;
255 if( (aIter
=mrShapeHash
.find( aTarget
)) != mrShapeHash
.end() )
256 break; // already an entry in existence for given XShape
258 // if this is an appear effect, hide shape
259 // initially. This is currently the only place
260 // where a shape effect influences shape
261 // attributes outside it's effective duration.
262 bool bVisible( false );
263 if( xAnimateNode
->getAttributeName().equalsIgnoreAsciiCase("visibility") )
266 uno::Any
aAny( xAnimateNode
->getTo() );
268 // try to extract bool value
269 if( !(aAny
>>= bVisible
) )
271 // try to extract string
273 if( (aAny
>>= aString
) )
275 // we also take the strings "true" and "false",
276 // as well as "on" and "off" here
277 if( aString
.equalsIgnoreAsciiCase("true") ||
278 aString
.equalsIgnoreAsciiCase("on") )
282 if( aString
.equalsIgnoreAsciiCase("false") ||
283 aString
.equalsIgnoreAsciiCase("off") )
290 // target is set the 'visible' value,
291 // so we should record the opposite value
293 XShapeHash::value_type(
298 //xAnimateNode->getAttributeName(),
299 OUString("visibility"),
300 uno::makeAny( !bVisible
) ) ) ) );
307 XShapeHash
& mrShapeHash
;
308 uno::Reference
< drawing::XShape
> mxTargetShape
;
309 sal_Int16 mnParagraphIndex
;
313 uno::Sequence
< animations::TargetProperties
> SAL_CALL
TargetPropertiesCreator::createInitialTargetProperties
315 const uno::Reference
< animations::XAnimationNode
>& xRootNode
316 ) //throw (uno::RuntimeException, std::exception)
318 // scan all nodes for visibility changes, and record first
319 // 'visibility=true' for each shape
320 XShapeHash
aShapeHash( 101 );
322 NodeFunctor
aFunctor( aShapeHash
);
324 // TODO(F1): Maybe limit functor application to main sequence
325 // alone (CL said something that shape visibility is only
326 // affected by effects in the main sequence for PPT).
328 // OTOH, client code can pass us only the main sequence (which
329 // it actually does right now, for the slideshow implementation).
330 aFunctor( xRootNode
);
332 // output to result sequence
333 uno::Sequence
< animations::TargetProperties
> aRes( aShapeHash
.size() );
335 ::std::size_t nCurrIndex(0);
336 XShapeHash::const_iterator
aCurr( aShapeHash
.begin() );
337 const XShapeHash::const_iterator
aEnd ( aShapeHash
.end() );
338 while( aCurr
!= aEnd
)
340 animations::TargetProperties
& rCurrProps( aRes
[ nCurrIndex
++ ] );
342 if( aCurr
->first
.mnParagraphIndex
== -1 )
344 rCurrProps
.Target
= uno::makeAny( aCurr
->first
.mxRef
);
348 rCurrProps
.Target
= uno::makeAny(
349 presentation::ParagraphTarget(
351 aCurr
->first
.mnParagraphIndex
) );
354 rCurrProps
.Properties
= ::comphelper::containerToSequence( aCurr
->second
);
362 } // namespace internal
363 } // namespace slideshow
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */