tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / slideshow / source / engine / slide / targetpropertiescreator.cxx
blobed3376cf97c8085948cf95b6e9bd0190b02acb35
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 <animations/animationnodehelper.hxx>
21 #include <com/sun/star/animations/XIterateContainer.hpp>
22 #include <com/sun/star/presentation/ParagraphTarget.hpp>
23 #include <com/sun/star/drawing/XShape.hpp>
24 #include <com/sun/star/animations/AnimationNodeType.hpp>
25 #include <com/sun/star/animations/XAnimate.hpp>
26 #include <comphelper/sequence.hxx>
28 #include <unordered_map>
29 #include <utility>
30 #include <vector>
32 #include "targetpropertiescreator.hxx"
33 #include <tools.hxx>
35 namespace slideshow::internal
37 namespace
39 // Vector containing all properties for a given shape
40 typedef ::std::vector< beans::NamedValue > VectorOfNamedValues;
42 /** The hash map key
44 This key contains both XShape reference and a paragraph
45 index, as we somehow have to handle shape and paragraph
46 targets with the same data structure.
48 struct ShapeHashKey
50 /// Shape target
51 uno::Reference< drawing::XShape > mxRef;
53 /** Paragraph index.
55 If this is a pure shape target, mnParagraphIndex is
56 set to -1.
58 sal_Int16 mnParagraphIndex;
60 /// Comparison needed for unordered_map
61 bool operator==( const ShapeHashKey& rRHS ) const
63 return mxRef == rRHS.mxRef && mnParagraphIndex == rRHS.mnParagraphIndex;
67 // A hash functor for ShapeHashKey objects
68 struct ShapeKeyHasher
70 ::std::size_t operator()( const ShapeHashKey& rKey ) const
72 // TODO(P2): Maybe a better hash function would be to
73 // spread mnParagraphIndex to 32 bit: a0b0c0d0e0... Hakmem
74 // should have a formula.
76 // Yes it has:
77 // x = (x & 0x0000FF00) << 8) | (x >> 8) & 0x0000FF00 | x & 0xFF0000FF;
78 // x = (x & 0x00F000F0) << 4) | (x >> 4) & 0x00F000F0 | x & 0xF00FF00F;
79 // x = (x & 0x0C0C0C0C) << 2) | (x >> 2) & 0x0C0C0C0C | x & 0xC3C3C3C3;
80 // x = (x & 0x22222222) << 1) | (x >> 1) & 0x22222222 | x & 0x99999999;
82 // Costs about 17 cycles on a RISC machine with infinite
83 // instruction level parallelism (~42 basic
84 // instructions). Thus I truly doubt this pays off...
85 return reinterpret_cast< ::std::size_t >(rKey.mxRef.get()) ^ (rKey.mnParagraphIndex << 16);
89 // A hash map which maps a XShape to the corresponding vector of initial properties
90 typedef std::unordered_map< ShapeHashKey, VectorOfNamedValues, ShapeKeyHasher > XShapeToNamedValuesMap;
93 class NodeFunctor
95 public:
96 explicit NodeFunctor(
97 XShapeToNamedValuesMap& rShapeHash,
98 bool bInitial )
99 : mrShapeHash( rShapeHash ),
100 mxTargetShape(),
101 mnParagraphIndex( -1 ),
102 mbInitial( bInitial)
106 NodeFunctor( XShapeToNamedValuesMap& rShapeHash,
107 uno::Reference< drawing::XShape > xTargetShape,
108 sal_Int16 nParagraphIndex,
109 bool bInitial) :
110 mrShapeHash( rShapeHash ),
111 mxTargetShape(std::move( xTargetShape )),
112 mnParagraphIndex( nParagraphIndex ),
113 mbInitial( bInitial )
117 void operator()( const uno::Reference< animations::XAnimationNode >& xNode ) const
119 if( !xNode.is() )
121 OSL_FAIL( "AnimCore: NodeFunctor::operator(): invalid XAnimationNode" );
122 return;
125 uno::Reference< drawing::XShape > xTargetShape( mxTargetShape );
126 sal_Int16 nParagraphIndex( mnParagraphIndex );
128 switch( xNode->getType() )
130 case animations::AnimationNodeType::ITERATE:
132 // extract target shape from iterate node
133 // (will override the target for all children)
135 uno::Reference< animations::XIterateContainer > xIterNode( xNode,
136 uno::UNO_QUERY );
138 // TODO(E1): I'm not too sure what to expect here...
139 if( !xIterNode->getTarget().hasValue() )
141 OSL_FAIL( "animcore: NodeFunctor::operator(): no target on ITERATE node" );
142 return;
145 xTargetShape.set( xIterNode->getTarget(),
146 uno::UNO_QUERY );
148 if( !xTargetShape.is() )
150 css::presentation::ParagraphTarget aTarget;
152 // no shape provided. Maybe a ParagraphTarget?
153 if( !(xIterNode->getTarget() >>= aTarget) )
155 OSL_FAIL( "animcore: NodeFunctor::operator(): could not extract any "
156 "target information" );
157 return;
160 xTargetShape = aTarget.Shape;
161 nParagraphIndex = aTarget.Paragraph;
163 if( !xTargetShape.is() )
165 OSL_FAIL( "animcore: NodeFunctor::operator(): invalid shape in ParagraphTarget" );
166 return;
169 [[fallthrough]];
171 case animations::AnimationNodeType::PAR:
172 case animations::AnimationNodeType::SEQ:
174 /// forward bInitial
175 NodeFunctor aFunctor( mrShapeHash,
176 xTargetShape,
177 nParagraphIndex,
178 mbInitial );
179 if( !for_each_childNode( xNode, aFunctor ) )
181 OSL_FAIL( "AnimCore: NodeFunctor::operator(): child node iteration failed, "
182 "or extraneous container nodes encountered" );
185 break;
187 case animations::AnimationNodeType::CUSTOM:
188 case animations::AnimationNodeType::ANIMATE:
189 case animations::AnimationNodeType::ANIMATEMOTION:
190 case animations::AnimationNodeType::ANIMATECOLOR:
191 case animations::AnimationNodeType::ANIMATETRANSFORM:
192 case animations::AnimationNodeType::TRANSITIONFILTER:
193 case animations::AnimationNodeType::AUDIO:
194 /*default:
195 // ignore this node, no valuable content for now.
196 break;*/
198 case animations::AnimationNodeType::SET:
200 // evaluate set node content
201 uno::Reference< animations::XAnimate > xAnimateNode( xNode,
202 uno::UNO_QUERY );
204 if( !xAnimateNode.is() )
205 break; // invalid node
207 // determine target shape (if any)
208 ShapeHashKey aTarget;
209 if( xTargetShape.is() )
211 // override target shape with parent-supplied
212 aTarget.mxRef = std::move(xTargetShape);
213 aTarget.mnParagraphIndex = nParagraphIndex;
215 else
217 // no parent-supplied target, retrieve
218 // node target
219 if( xAnimateNode->getTarget() >>= aTarget.mxRef )
221 // pure shape target - set paragraph
222 // index to magic
223 aTarget.mnParagraphIndex = -1;
225 else
227 // not a pure shape target - maybe a
228 // ParagraphTarget?
229 presentation::ParagraphTarget aUnoTarget;
231 if( !(xAnimateNode->getTarget() >>= aUnoTarget) )
233 OSL_FAIL( "AnimCore: NodeFunctor::operator(): unknown target type encountered" );
234 break;
237 aTarget.mxRef = aUnoTarget.Shape;
238 aTarget.mnParagraphIndex = aUnoTarget.Paragraph;
242 if( !aTarget.mxRef.is() )
244 OSL_FAIL( "AnimCore: NodeFunctor::operator(): Found target, but XShape is NULL" );
245 break; // invalid target XShape
248 // check whether we already have an entry for
249 // this target (we only take the first set
250 // effect for every shape) - but keep going if
251 // we're requested the final state (which
252 // eventually gets overwritten in the
253 // unordered list, see tdf#96083)
254 if( mbInitial && mrShapeHash.find( aTarget ) != mrShapeHash.end() )
255 break; // already an entry in existence for given XShape
257 // if this is an appear effect, hide shape
258 // initially. This is currently the only place
259 // where a shape effect influences shape
260 // attributes outside it's effective duration.
261 bool bVisible = false;
262 anim::getVisibilityProperty(xAnimateNode, bVisible);
264 // if initial anim sets shape visible, set it
265 // to invisible. If we're asked for the final
266 // state, don't do anything obviously
267 if(mbInitial)
268 bVisible = !bVisible;
270 // target is set the 'visible' value,
271 // so we should record the opposite value
272 mrShapeHash.emplace(
273 aTarget,
274 VectorOfNamedValues(
276 beans::NamedValue(
277 //xAnimateNode->getAttributeName(),
278 u"visibility"_ustr,
279 uno::Any( bVisible ) ) ) );
280 break;
285 private:
286 XShapeToNamedValuesMap& mrShapeHash;
287 uno::Reference< drawing::XShape > mxTargetShape;
288 sal_Int16 mnParagraphIndex;
290 // get initial or final state
291 bool mbInitial;
295 uno::Sequence< animations::TargetProperties > TargetPropertiesCreator::createTargetProperties
297 const uno::Reference< animations::XAnimationNode >& xRootNode,
298 bool bInitial
299 ) //throw (uno::RuntimeException, std::exception)
301 // scan all nodes for visibility changes, and record first
302 // 'visibility=true' for each shape
303 XShapeToNamedValuesMap aShapeHash( 101 );
305 NodeFunctor aFunctor(
306 aShapeHash,
307 bInitial );
309 // TODO(F1): Maybe limit functor application to main sequence
310 // alone (CL said something that shape visibility is only
311 // affected by effects in the main sequence for PPT).
313 // OTOH, client code can pass us only the main sequence (which
314 // it actually does right now, for the slideshow implementation).
315 aFunctor( xRootNode );
317 // output to result sequence
318 uno::Sequence< animations::TargetProperties > aRes( aShapeHash.size() );
319 auto aResRange = asNonConstRange(aRes);
321 ::std::size_t nCurrIndex(0);
322 for( const auto& rIter : aShapeHash )
324 animations::TargetProperties& rCurrProps( aResRange[ nCurrIndex++ ] );
326 if( rIter.first.mnParagraphIndex == -1 )
328 rCurrProps.Target <<= rIter.first.mxRef;
330 else
332 rCurrProps.Target <<=
333 presentation::ParagraphTarget(
334 rIter.first.mxRef,
335 rIter.first.mnParagraphIndex );
338 rCurrProps.Properties = ::comphelper::containerToSequence( rIter.second );
341 return aRes;
344 } // namespace slideshow::internal
346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */