build fix
[LibreOffice.git] / slideshow / source / engine / slide / targetpropertiescreator.cxx
blob6eb1f70b5cdccff551f7c228640a7a344a620b2a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
30 #include <vector>
32 #include "targetpropertiescreator.hxx"
33 #include "tools.hxx"
35 namespace slideshow
37 namespace internal
39 namespace
41 // Vector containing all properties for a given shape
42 typedef ::std::vector< beans::NamedValue > VectorOfNamedValues;
44 /** The hash map key
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.
50 struct ShapeHashKey
52 /// Shape target
53 uno::Reference< drawing::XShape > mxRef;
55 /** Paragraph index.
57 If this is a pure shape target, mnParagraphIndex is
58 set to -1.
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
70 struct ShapeKeyHasher
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.
78 // Yes it has:
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;
95 class NodeFunctor
97 public:
98 explicit NodeFunctor(
99 XShapeHash& rShapeHash,
100 bool bInitial )
101 : mrShapeHash( rShapeHash ),
102 mxTargetShape(),
103 mnParagraphIndex( -1 ),
104 mbInitial( bInitial)
108 NodeFunctor( XShapeHash& rShapeHash,
109 const uno::Reference< drawing::XShape >& rTargetShape,
110 sal_Int16 nParagraphIndex,
111 bool bInitial) :
112 mrShapeHash( rShapeHash ),
113 mxTargetShape( rTargetShape ),
114 mnParagraphIndex( nParagraphIndex ),
115 mbInitial( bInitial )
119 void operator()( const uno::Reference< animations::XAnimationNode >& xNode ) const
121 if( !xNode.is() )
123 OSL_FAIL( "AnimCore: NodeFunctor::operator(): invalid XAnimationNode" );
124 return;
127 uno::Reference< drawing::XShape > xTargetShape( mxTargetShape );
128 sal_Int16 nParagraphIndex( mnParagraphIndex );
130 switch( xNode->getType() )
132 case animations::AnimationNodeType::ITERATE:
134 // extract target shape from iterate node
135 // (will override the target for all children)
137 uno::Reference< animations::XIterateContainer > xIterNode( xNode,
138 uno::UNO_QUERY );
140 // TODO(E1): I'm not too sure what to expect here...
141 if( !xIterNode->getTarget().hasValue() )
143 OSL_FAIL( "animcore: NodeFunctor::operator(): no target on ITERATE node" );
144 return;
147 xTargetShape.set( xIterNode->getTarget(),
148 uno::UNO_QUERY );
150 if( !xTargetShape.is() )
152 css::presentation::ParagraphTarget aTarget;
154 // no shape provided. Maybe a ParagraphTarget?
155 if( !(xIterNode->getTarget() >>= aTarget) )
157 OSL_FAIL( "animcore: NodeFunctor::operator(): could not extract any "
158 "target information" );
159 return;
162 xTargetShape = aTarget.Shape;
163 nParagraphIndex = aTarget.Paragraph;
165 if( !xTargetShape.is() )
167 OSL_FAIL( "animcore: NodeFunctor::operator(): invalid shape in ParagraphTarget" );
168 return;
171 SAL_FALLTHROUGH;
173 case animations::AnimationNodeType::PAR:
174 case animations::AnimationNodeType::SEQ:
176 /// forward bInitial
177 NodeFunctor aFunctor( mrShapeHash,
178 xTargetShape,
179 nParagraphIndex,
180 mbInitial );
181 if( !for_each_childNode( xNode, aFunctor ) )
183 OSL_FAIL( "AnimCore: NodeFunctor::operator(): child node iteration failed, "
184 "or extraneous container nodes encountered" );
187 break;
189 case animations::AnimationNodeType::CUSTOM:
190 // FALLTHROUGH intended
191 case animations::AnimationNodeType::ANIMATE:
192 // FALLTHROUGH intended
193 case animations::AnimationNodeType::ANIMATEMOTION:
194 // FALLTHROUGH intended
195 case animations::AnimationNodeType::ANIMATECOLOR:
196 // FALLTHROUGH intended
197 case animations::AnimationNodeType::ANIMATETRANSFORM:
198 // FALLTHROUGH intended
199 case animations::AnimationNodeType::TRANSITIONFILTER:
200 // FALLTHROUGH intended
201 case animations::AnimationNodeType::AUDIO:
202 // FALLTHROUGH intended
203 /*default:
204 // ignore this node, no valuable content for now.
205 break;*/
207 case animations::AnimationNodeType::SET:
209 // evaluate set node content
210 uno::Reference< animations::XAnimate > xAnimateNode( xNode,
211 uno::UNO_QUERY );
213 if( !xAnimateNode.is() )
214 break; // invalid node
216 // determine target shape (if any)
217 ShapeHashKey aTarget;
218 if( xTargetShape.is() )
220 // override target shape with parent-supplied
221 aTarget.mxRef = xTargetShape;
222 aTarget.mnParagraphIndex = nParagraphIndex;
224 else
226 // no parent-supplied target, retrieve
227 // node target
228 if( (xAnimateNode->getTarget() >>= aTarget.mxRef) )
230 // pure shape target - set paragraph
231 // index to magic
232 aTarget.mnParagraphIndex = -1;
234 else
236 // not a pure shape target - maybe a
237 // ParagraphTarget?
238 presentation::ParagraphTarget aUnoTarget;
240 if( !(xAnimateNode->getTarget() >>= aUnoTarget) )
242 OSL_FAIL( "AnimCore: NodeFunctor::operator(): unknown target type encountered" );
243 break;
246 aTarget.mxRef = aUnoTarget.Shape;
247 aTarget.mnParagraphIndex = aUnoTarget.Paragraph;
251 if( !aTarget.mxRef.is() )
253 OSL_FAIL( "AnimCore: NodeFunctor::operator(): Found target, but XShape is NULL" );
254 break; // invalid target XShape
257 // check whether we already have an entry for
258 // this target (we only take the first set
259 // effect for every shape) - but keep going if
260 // we're requested the final state (which
261 // eventually gets overwritten in the
262 // unordered list, see tdf#96083)
263 if( mbInitial && mrShapeHash.find( aTarget ) != mrShapeHash.end() )
264 break; // already an entry in existence for given XShape
266 // if this is an appear effect, hide shape
267 // initially. This is currently the only place
268 // where a shape effect influences shape
269 // attributes outside it's effective duration.
270 bool bVisible( false );
271 if( xAnimateNode->getAttributeName().equalsIgnoreAsciiCase("visibility") )
274 uno::Any aAny( xAnimateNode->getTo() );
276 // try to extract bool value
277 if( !(aAny >>= bVisible) )
279 // try to extract string
280 OUString aString;
281 if( (aAny >>= aString) )
283 // we also take the strings "true" and "false",
284 // as well as "on" and "off" here
285 if( aString.equalsIgnoreAsciiCase("true") ||
286 aString.equalsIgnoreAsciiCase("on") )
288 bVisible = true;
290 if( aString.equalsIgnoreAsciiCase("false") ||
291 aString.equalsIgnoreAsciiCase("off") )
293 bVisible = false;
299 // if initial anim sets shape visible, set it
300 // to invisible. If we're asked for the final
301 // state, don't do anything obviously
302 if(mbInitial)
303 bVisible = !bVisible;
305 // target is set the 'visible' value,
306 // so we should record the opposite value
307 mrShapeHash.insert(
308 XShapeHash::value_type(
309 aTarget,
310 VectorOfNamedValues(
312 beans::NamedValue(
313 //xAnimateNode->getAttributeName(),
314 OUString("visibility"),
315 uno::makeAny( bVisible ) ) ) ) );
316 break;
321 private:
322 XShapeHash& mrShapeHash;
323 uno::Reference< drawing::XShape > mxTargetShape;
324 sal_Int16 mnParagraphIndex;
326 // get initial or filal state
327 bool mbInitial;
331 uno::Sequence< animations::TargetProperties > SAL_CALL TargetPropertiesCreator::createTargetProperties
333 const uno::Reference< animations::XAnimationNode >& xRootNode,
334 bool bInitial
335 ) //throw (uno::RuntimeException, std::exception)
337 // scan all nodes for visibility changes, and record first
338 // 'visibility=true' for each shape
339 XShapeHash aShapeHash( 101 );
341 NodeFunctor aFunctor(
342 aShapeHash,
343 bInitial );
345 // TODO(F1): Maybe limit functor application to main sequence
346 // alone (CL said something that shape visibility is only
347 // affected by effects in the main sequence for PPT).
349 // OTOH, client code can pass us only the main sequence (which
350 // it actually does right now, for the slideshow implementation).
351 aFunctor( xRootNode );
353 // output to result sequence
354 uno::Sequence< animations::TargetProperties > aRes( aShapeHash.size() );
356 ::std::size_t nCurrIndex(0);
357 for( const auto& rIter : aShapeHash )
359 animations::TargetProperties& rCurrProps( aRes[ nCurrIndex++ ] );
361 if( rIter.first.mnParagraphIndex == -1 )
363 rCurrProps.Target = uno::makeAny( rIter.first.mxRef );
365 else
367 rCurrProps.Target = uno::makeAny(
368 presentation::ParagraphTarget(
369 rIter.first.mxRef,
370 rIter.first.mnParagraphIndex ) );
373 rCurrProps.Properties = ::comphelper::containerToSequence( rIter.second );
376 return aRes;
379 } // namespace internal
380 } // namespace slideshow
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */