1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_slideshow.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <canvas/debug.hxx> 32*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 33*cdf0e10cSrcweir #include <canvas/elapsedtime.hxx> 34*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir #include <comphelper/anytostring.hxx> 37*cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx> 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir #include <rtl/math.hxx> 40*cdf0e10cSrcweir #include <vcl/metric.hxx> 41*cdf0e10cSrcweir #include <vcl/salbtype.hxx> 42*cdf0e10cSrcweir #include <vcl/canvastools.hxx> 43*cdf0e10cSrcweir #include <vcl/metaact.hxx> 44*cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 45*cdf0e10cSrcweir #include <com/sun/star/drawing/TextAnimationKind.hpp> 46*cdf0e10cSrcweir #include <com/sun/star/drawing/TextAnimationDirection.hpp> 47*cdf0e10cSrcweir #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> 48*cdf0e10cSrcweir #include <com/sun/star/drawing/TextVerticalAdjust.hpp> 49*cdf0e10cSrcweir #include <com/sun/star/drawing/HomogenMatrix3.hpp> 50*cdf0e10cSrcweir #include <com/sun/star/awt/Rectangle.hpp> 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir #include "activity.hxx" 53*cdf0e10cSrcweir #include "wakeupevent.hxx" 54*cdf0e10cSrcweir #include "eventqueue.hxx" 55*cdf0e10cSrcweir #include "drawshapesubsetting.hxx" 56*cdf0e10cSrcweir #include "drawshape.hxx" 57*cdf0e10cSrcweir #include "shapesubset.hxx" 58*cdf0e10cSrcweir #include "shapeattributelayerholder.hxx" 59*cdf0e10cSrcweir #include "slideshowcontext.hxx" 60*cdf0e10cSrcweir #include "tools.hxx" 61*cdf0e10cSrcweir #include "gdimtftools.hxx" 62*cdf0e10cSrcweir #include "eventmultiplexer.hxx" 63*cdf0e10cSrcweir #include "intrinsicanimationactivity.hxx" 64*cdf0e10cSrcweir #include "intrinsicanimationeventhandler.hxx" 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir #include <boost/weak_ptr.hpp> 67*cdf0e10cSrcweir #include <boost/enable_shared_from_this.hpp> 68*cdf0e10cSrcweir #include <boost/noncopyable.hpp> 69*cdf0e10cSrcweir #include <vector> 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir using namespace com::sun::star; 72*cdf0e10cSrcweir using namespace ::slideshow::internal; 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir namespace { 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir class ScrollTextAnimNode 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir sal_uInt32 mnDuration; // single duration 79*cdf0e10cSrcweir sal_uInt32 mnRepeat; // 0 -> endless 80*cdf0e10cSrcweir double mfStart; 81*cdf0e10cSrcweir double mfStop; 82*cdf0e10cSrcweir sal_uInt32 mnFrequency; // in ms 83*cdf0e10cSrcweir // forth and back change at mnRepeat%2: 84*cdf0e10cSrcweir bool mbAlternate; 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir public: 87*cdf0e10cSrcweir ScrollTextAnimNode( 88*cdf0e10cSrcweir sal_uInt32 nDuration, sal_uInt32 nRepeat, double fStart, double fStop, 89*cdf0e10cSrcweir sal_uInt32 nFrequency, bool bAlternate) 90*cdf0e10cSrcweir : mnDuration(nDuration), 91*cdf0e10cSrcweir mnRepeat(nRepeat), 92*cdf0e10cSrcweir mfStart(fStart), 93*cdf0e10cSrcweir mfStop(fStop), 94*cdf0e10cSrcweir mnFrequency(nFrequency), 95*cdf0e10cSrcweir mbAlternate(bAlternate) 96*cdf0e10cSrcweir {} 97*cdf0e10cSrcweir 98*cdf0e10cSrcweir sal_uInt32 GetDuration() const { return mnDuration; } 99*cdf0e10cSrcweir sal_uInt32 GetRepeat() const { return mnRepeat; } 100*cdf0e10cSrcweir sal_uInt32 GetFullTime() const { return mnDuration * mnRepeat; } 101*cdf0e10cSrcweir double GetStart() const { return mfStart; } 102*cdf0e10cSrcweir double GetStop() const { return mfStop; } 103*cdf0e10cSrcweir sal_uInt32 GetFrequency() const { return mnFrequency; } 104*cdf0e10cSrcweir bool DoAlternate() const { return mbAlternate; } 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir double GetStateAtRelativeTime(sal_uInt32 nRelativeTime) const; 107*cdf0e10cSrcweir }; 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir double ScrollTextAnimNode::GetStateAtRelativeTime( 110*cdf0e10cSrcweir sal_uInt32 nRelativeTime) const 111*cdf0e10cSrcweir { 112*cdf0e10cSrcweir // #151174# Avoid division by zero. 113*cdf0e10cSrcweir if( mnDuration == 0 ) 114*cdf0e10cSrcweir return mfStop; 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir if(mnRepeat) 117*cdf0e10cSrcweir { 118*cdf0e10cSrcweir // ending 119*cdf0e10cSrcweir const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration); 120*cdf0e10cSrcweir sal_uInt32 nFrameTime(nRelativeTime - (nRepeatCount * mnDuration)); 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir if(DoAlternate() && (nRepeatCount + 1L) % 2L) 123*cdf0e10cSrcweir nFrameTime = mnDuration - nFrameTime; 124*cdf0e10cSrcweir 125*cdf0e10cSrcweir return mfStart + ((mfStop - mfStart) * 126*cdf0e10cSrcweir (double(nFrameTime) / mnDuration)); 127*cdf0e10cSrcweir } 128*cdf0e10cSrcweir else 129*cdf0e10cSrcweir { 130*cdf0e10cSrcweir // endless 131*cdf0e10cSrcweir sal_uInt32 nFrameTime(nRelativeTime % mnDuration); 132*cdf0e10cSrcweir 133*cdf0e10cSrcweir if(DoAlternate()) 134*cdf0e10cSrcweir { 135*cdf0e10cSrcweir const sal_uInt32 nRepeatCount(nRelativeTime / mnDuration); 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir if((nRepeatCount + 1L) % 2L) 138*cdf0e10cSrcweir nFrameTime = mnDuration - nFrameTime; 139*cdf0e10cSrcweir } 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir return mfStart + ((mfStop - mfStart) * (double(nFrameTime) / mnDuration)); 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir } 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir class ActivityImpl : public Activity, 146*cdf0e10cSrcweir public boost::enable_shared_from_this<ActivityImpl>, 147*cdf0e10cSrcweir private boost::noncopyable 148*cdf0e10cSrcweir { 149*cdf0e10cSrcweir public: 150*cdf0e10cSrcweir virtual ~ActivityImpl(); 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir ActivityImpl( 153*cdf0e10cSrcweir SlideShowContext const& rContext, 154*cdf0e10cSrcweir boost::shared_ptr<WakeupEvent> const& pWakeupEvent, 155*cdf0e10cSrcweir boost::shared_ptr<DrawShape> const& pDrawShape ); 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir bool enableAnimations(); 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir // Disposable: 160*cdf0e10cSrcweir virtual void dispose(); 161*cdf0e10cSrcweir // Activity: 162*cdf0e10cSrcweir virtual double calcTimeLag() const; 163*cdf0e10cSrcweir virtual bool perform(); 164*cdf0e10cSrcweir virtual bool isActive() const; 165*cdf0e10cSrcweir virtual void dequeued(); 166*cdf0e10cSrcweir virtual void end(); 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir private: 169*cdf0e10cSrcweir void updateShapeAttributes( double fTime, 170*cdf0e10cSrcweir basegfx::B2DRectangle const& parentBounds ); 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir // Access to VisibleWhenSTarted flags 173*cdf0e10cSrcweir sal_Bool IsVisibleWhenStarted() const { return mbVisibleWhenStarted; } 174*cdf0e10cSrcweir sal_Bool IsVisibleWhenStopped() const { return mbVisibleWhenStopped; } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir // scroll horizontal? if sal_False, scroll is vertical. 177*cdf0e10cSrcweir bool ScrollHorizontal() const { 178*cdf0e10cSrcweir return (drawing::TextAnimationDirection_LEFT == meDirection || 179*cdf0e10cSrcweir drawing::TextAnimationDirection_RIGHT == meDirection); 180*cdf0e10cSrcweir } 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir // Access to StepWidth in logical units 183*cdf0e10cSrcweir sal_uInt32 GetStepWidthLogic() const; 184*cdf0e10cSrcweir 185*cdf0e10cSrcweir // is the animation direction opposite? 186*cdf0e10cSrcweir bool DoScrollForward() const { 187*cdf0e10cSrcweir return (drawing::TextAnimationDirection_RIGHT == meDirection || 188*cdf0e10cSrcweir drawing::TextAnimationDirection_DOWN == meDirection); 189*cdf0e10cSrcweir } 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir // do alternate text directions? 192*cdf0e10cSrcweir bool DoAlternate() const { return mbAlternate; } 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir // do scroll in? 195*cdf0e10cSrcweir bool DoScrollIn() const { return mbScrollIn; } 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir // Scroll helper methods 198*cdf0e10cSrcweir void ImpForceScrollTextAnimNodes(); 199*cdf0e10cSrcweir ScrollTextAnimNode* ImpGetScrollTextAnimNode( 200*cdf0e10cSrcweir sal_uInt32 nTime, sal_uInt32& rRelativeTime ); 201*cdf0e10cSrcweir sal_uInt32 ImpRegisterAgainScrollTextMixerState( 202*cdf0e10cSrcweir sal_uInt32 nTime); 203*cdf0e10cSrcweir 204*cdf0e10cSrcweir // calculate the MixerState value for given time 205*cdf0e10cSrcweir double GetMixerState(sal_uInt32 nTime); 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir //////////////////////////////////////////////////////////////////// 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir SlideShowContext maContext; 210*cdf0e10cSrcweir boost::shared_ptr<WakeupEvent> mpWakeupEvent; 211*cdf0e10cSrcweir boost::weak_ptr<DrawShape> mpParentDrawShape; 212*cdf0e10cSrcweir DrawShapeSharedPtr mpDrawShape; 213*cdf0e10cSrcweir ShapeAttributeLayerHolder maShapeAttrLayer; 214*cdf0e10cSrcweir GDIMetaFileSharedPtr mpMetaFile; 215*cdf0e10cSrcweir IntrinsicAnimationEventHandlerSharedPtr mpListener; 216*cdf0e10cSrcweir canvas::tools::ElapsedTime maTimer; 217*cdf0e10cSrcweir double mfRotationAngle; 218*cdf0e10cSrcweir bool mbIsShapeAnimated; 219*cdf0e10cSrcweir bool mbIsDisposed; 220*cdf0e10cSrcweir bool mbIsActive; 221*cdf0e10cSrcweir drawing::TextAnimationKind meAnimKind; 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir // The blink frequency in ms 224*cdf0e10cSrcweir sal_uInt32 mnFrequency; 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir // The repeat count, init to 0L which means endless 227*cdf0e10cSrcweir sal_uInt32 mnRepeat; 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir // Flag to decide if text will be shown when animation has ended 230*cdf0e10cSrcweir bool mbVisibleWhenStopped; 231*cdf0e10cSrcweir bool mbVisibleWhenStarted; 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir // Flag decides if TextScroll alternates. Default is sal_False. 234*cdf0e10cSrcweir bool mbAlternate; 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir // Flag to remember if this is a simple scrollin text 237*cdf0e10cSrcweir bool mbScrollIn; 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir // start time for this animation 240*cdf0e10cSrcweir sal_uInt32 mnStartTime; 241*cdf0e10cSrcweir 242*cdf0e10cSrcweir // The AnimationDirection 243*cdf0e10cSrcweir drawing::TextAnimationDirection meDirection; 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir // Get width per Step. Negative means pixel, positive logical units 246*cdf0e10cSrcweir sal_Int32 mnStepWidth; 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir // The single anim steps 249*cdf0e10cSrcweir std::vector< ScrollTextAnimNode > maVector; 250*cdf0e10cSrcweir 251*cdf0e10cSrcweir // the scroll rectangle 252*cdf0e10cSrcweir Rectangle maScrollRectangleLogic; 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir // the paint rectangle 255*cdf0e10cSrcweir Rectangle maPaintRectangleLogic; 256*cdf0e10cSrcweir }; 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir class IntrinsicAnimationListener : public IntrinsicAnimationEventHandler, 261*cdf0e10cSrcweir private boost::noncopyable 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir public: 264*cdf0e10cSrcweir explicit IntrinsicAnimationListener( ActivityImpl& rActivity ) : 265*cdf0e10cSrcweir mrActivity( rActivity ) 266*cdf0e10cSrcweir {} 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir private: 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir virtual bool enableAnimations() { return mrActivity.enableAnimations(); } 271*cdf0e10cSrcweir virtual bool disableAnimations() { mrActivity.end(); return true; } 272*cdf0e10cSrcweir 273*cdf0e10cSrcweir ActivityImpl& mrActivity; 274*cdf0e10cSrcweir }; 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir double ActivityImpl::GetMixerState( sal_uInt32 nTime ) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir if( meAnimKind == drawing::TextAnimationKind_BLINK ) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir // from AInfoBlinkText: 283*cdf0e10cSrcweir double fRetval(0.0); 284*cdf0e10cSrcweir sal_Bool bDone(sal_False); 285*cdf0e10cSrcweir const sal_uInt32 nLoopTime(2 * mnFrequency); 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir if(mnRepeat) 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir const sal_uInt32 nEndTime(mnRepeat * nLoopTime); 290*cdf0e10cSrcweir 291*cdf0e10cSrcweir if(nTime >= nEndTime) 292*cdf0e10cSrcweir { 293*cdf0e10cSrcweir if(mbVisibleWhenStopped) 294*cdf0e10cSrcweir fRetval = 0.0; 295*cdf0e10cSrcweir else 296*cdf0e10cSrcweir fRetval = 1.0; 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir bDone = sal_True; 299*cdf0e10cSrcweir } 300*cdf0e10cSrcweir } 301*cdf0e10cSrcweir 302*cdf0e10cSrcweir if(!bDone) 303*cdf0e10cSrcweir { 304*cdf0e10cSrcweir sal_uInt32 nTimeInLoop(nTime % nLoopTime); 305*cdf0e10cSrcweir fRetval = double(nTimeInLoop) / nLoopTime; 306*cdf0e10cSrcweir } 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir return fRetval; 309*cdf0e10cSrcweir } 310*cdf0e10cSrcweir else 311*cdf0e10cSrcweir { 312*cdf0e10cSrcweir // from AInfoScrollText: 313*cdf0e10cSrcweir double fRetval(0.0); 314*cdf0e10cSrcweir ImpForceScrollTextAnimNodes(); 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir if(!maVector.empty()) 317*cdf0e10cSrcweir { 318*cdf0e10cSrcweir sal_uInt32 nRelativeTime; 319*cdf0e10cSrcweir ScrollTextAnimNode* pNode = 320*cdf0e10cSrcweir ImpGetScrollTextAnimNode(nTime, nRelativeTime); 321*cdf0e10cSrcweir 322*cdf0e10cSrcweir if(pNode) 323*cdf0e10cSrcweir { 324*cdf0e10cSrcweir // use node 325*cdf0e10cSrcweir fRetval = pNode->GetStateAtRelativeTime(nRelativeTime); 326*cdf0e10cSrcweir } 327*cdf0e10cSrcweir else 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir // end of animation, take last entry's end 330*cdf0e10cSrcweir fRetval = maVector[maVector.size() - 1L].GetStop(); 331*cdf0e10cSrcweir } 332*cdf0e10cSrcweir } 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir return fRetval; 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir // Access to StepWidth in logical units 339*cdf0e10cSrcweir sal_uInt32 ActivityImpl::GetStepWidthLogic() const 340*cdf0e10cSrcweir { 341*cdf0e10cSrcweir // #i69847# Assuming higher DPI 342*cdf0e10cSrcweir sal_uInt32 const PIXEL_TO_LOGIC = 30; 343*cdf0e10cSrcweir 344*cdf0e10cSrcweir sal_uInt32 nRetval(0L); 345*cdf0e10cSrcweir 346*cdf0e10cSrcweir if(mnStepWidth < 0L) 347*cdf0e10cSrcweir { 348*cdf0e10cSrcweir // is in pixels, convert to logical units 349*cdf0e10cSrcweir nRetval = (-mnStepWidth * PIXEL_TO_LOGIC); 350*cdf0e10cSrcweir } 351*cdf0e10cSrcweir else if(mnStepWidth > 0L) 352*cdf0e10cSrcweir { 353*cdf0e10cSrcweir // is in logical units 354*cdf0e10cSrcweir nRetval = mnStepWidth; 355*cdf0e10cSrcweir } 356*cdf0e10cSrcweir 357*cdf0e10cSrcweir if(0L == nRetval) 358*cdf0e10cSrcweir { 359*cdf0e10cSrcweir // step 1 pixel, canned value 360*cdf0e10cSrcweir 361*cdf0e10cSrcweir // #128389# with very high DPIs like in PDF export, this can 362*cdf0e10cSrcweir // still get zero. for that cases, set a default, too (taken 363*cdf0e10cSrcweir // from ainfoscrolltext.cxx) 364*cdf0e10cSrcweir nRetval = 100L; 365*cdf0e10cSrcweir } 366*cdf0e10cSrcweir 367*cdf0e10cSrcweir return nRetval; 368*cdf0e10cSrcweir } 369*cdf0e10cSrcweir 370*cdf0e10cSrcweir void ActivityImpl::ImpForceScrollTextAnimNodes() 371*cdf0e10cSrcweir { 372*cdf0e10cSrcweir if(maVector.empty()) 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir // prepare values 375*cdf0e10cSrcweir sal_uInt32 nLoopTime; 376*cdf0e10cSrcweir double fZeroLogic, fOneLogic, fInitLogic, fDistanceLogic; 377*cdf0e10cSrcweir double fZeroLogicAlternate = 0.0, fOneLogicAlternate = 0.0; 378*cdf0e10cSrcweir double fZeroRelative, fOneRelative, fInitRelative,fDistanceRelative; 379*cdf0e10cSrcweir 380*cdf0e10cSrcweir if(ScrollHorizontal()) 381*cdf0e10cSrcweir { 382*cdf0e10cSrcweir if(DoAlternate()) 383*cdf0e10cSrcweir { 384*cdf0e10cSrcweir if(maPaintRectangleLogic.GetWidth() > 385*cdf0e10cSrcweir maScrollRectangleLogic.GetWidth()) 386*cdf0e10cSrcweir { 387*cdf0e10cSrcweir fZeroLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth(); 388*cdf0e10cSrcweir fOneLogicAlternate = maScrollRectangleLogic.Left(); 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir else 391*cdf0e10cSrcweir { 392*cdf0e10cSrcweir fZeroLogicAlternate = maScrollRectangleLogic.Left(); 393*cdf0e10cSrcweir fOneLogicAlternate = maScrollRectangleLogic.Right() - maPaintRectangleLogic.GetWidth(); 394*cdf0e10cSrcweir } 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir fZeroLogic = maScrollRectangleLogic.Left() - maPaintRectangleLogic.GetWidth(); 398*cdf0e10cSrcweir fOneLogic = maScrollRectangleLogic.Right(); 399*cdf0e10cSrcweir fInitLogic = maPaintRectangleLogic.Left(); 400*cdf0e10cSrcweir } 401*cdf0e10cSrcweir else 402*cdf0e10cSrcweir { 403*cdf0e10cSrcweir if(DoAlternate()) 404*cdf0e10cSrcweir { 405*cdf0e10cSrcweir if(maPaintRectangleLogic.GetHeight() > maScrollRectangleLogic.GetHeight()) 406*cdf0e10cSrcweir { 407*cdf0e10cSrcweir fZeroLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight(); 408*cdf0e10cSrcweir fOneLogicAlternate = maScrollRectangleLogic.Top(); 409*cdf0e10cSrcweir } 410*cdf0e10cSrcweir else 411*cdf0e10cSrcweir { 412*cdf0e10cSrcweir fZeroLogicAlternate = maScrollRectangleLogic.Top(); 413*cdf0e10cSrcweir fOneLogicAlternate = maScrollRectangleLogic.Bottom() - maPaintRectangleLogic.GetHeight(); 414*cdf0e10cSrcweir } 415*cdf0e10cSrcweir } 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir fZeroLogic = maScrollRectangleLogic.Top() - maPaintRectangleLogic.GetHeight(); 418*cdf0e10cSrcweir fOneLogic = maScrollRectangleLogic.Bottom(); 419*cdf0e10cSrcweir fInitLogic = maPaintRectangleLogic.Top(); 420*cdf0e10cSrcweir } 421*cdf0e10cSrcweir 422*cdf0e10cSrcweir fDistanceLogic = fOneLogic - fZeroLogic; 423*cdf0e10cSrcweir fInitRelative = (fInitLogic - fZeroLogic) / fDistanceLogic; 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir if(DoAlternate()) 426*cdf0e10cSrcweir { 427*cdf0e10cSrcweir fZeroRelative = 428*cdf0e10cSrcweir (fZeroLogicAlternate - fZeroLogic) / fDistanceLogic; 429*cdf0e10cSrcweir fOneRelative = 430*cdf0e10cSrcweir (fOneLogicAlternate - fZeroLogic) / fDistanceLogic; 431*cdf0e10cSrcweir fDistanceRelative = fOneRelative - fZeroRelative; 432*cdf0e10cSrcweir } 433*cdf0e10cSrcweir else 434*cdf0e10cSrcweir { 435*cdf0e10cSrcweir fZeroRelative = 0.0; 436*cdf0e10cSrcweir fOneRelative = 1.0; 437*cdf0e10cSrcweir fDistanceRelative = 1.0; 438*cdf0e10cSrcweir } 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir if(mnStartTime) 441*cdf0e10cSrcweir { 442*cdf0e10cSrcweir // Start time loop 443*cdf0e10cSrcweir ScrollTextAnimNode aStartNode( 444*cdf0e10cSrcweir mnStartTime, 1L, 0.0, 0.0, mnStartTime, false); 445*cdf0e10cSrcweir maVector.push_back(aStartNode); 446*cdf0e10cSrcweir } 447*cdf0e10cSrcweir 448*cdf0e10cSrcweir if(IsVisibleWhenStarted()) 449*cdf0e10cSrcweir { 450*cdf0e10cSrcweir double fRelativeStartValue, fRelativeEndValue,fRelativeDistance; 451*cdf0e10cSrcweir 452*cdf0e10cSrcweir if(DoScrollForward()) 453*cdf0e10cSrcweir { 454*cdf0e10cSrcweir fRelativeStartValue = fInitRelative; 455*cdf0e10cSrcweir fRelativeEndValue = fOneRelative; 456*cdf0e10cSrcweir fRelativeDistance = fRelativeEndValue - fRelativeStartValue; 457*cdf0e10cSrcweir } 458*cdf0e10cSrcweir else 459*cdf0e10cSrcweir { 460*cdf0e10cSrcweir fRelativeStartValue = fInitRelative; 461*cdf0e10cSrcweir fRelativeEndValue = fZeroRelative; 462*cdf0e10cSrcweir fRelativeDistance = fRelativeStartValue - fRelativeEndValue; 463*cdf0e10cSrcweir } 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir const double fNumberSteps = 466*cdf0e10cSrcweir (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic(); 467*cdf0e10cSrcweir nLoopTime = FRound(fNumberSteps * mnFrequency); 468*cdf0e10cSrcweir 469*cdf0e10cSrcweir // init loop 470*cdf0e10cSrcweir ScrollTextAnimNode aInitNode( 471*cdf0e10cSrcweir nLoopTime, 1L, 472*cdf0e10cSrcweir fRelativeStartValue, fRelativeEndValue, 473*cdf0e10cSrcweir mnFrequency, false); 474*cdf0e10cSrcweir maVector.push_back(aInitNode); 475*cdf0e10cSrcweir } 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir // prepare main loop values 478*cdf0e10cSrcweir { 479*cdf0e10cSrcweir double fRelativeStartValue, fRelativeEndValue, fRelativeDistance; 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir if(DoScrollForward()) 482*cdf0e10cSrcweir { 483*cdf0e10cSrcweir fRelativeStartValue = fZeroRelative; 484*cdf0e10cSrcweir fRelativeEndValue = fOneRelative; 485*cdf0e10cSrcweir fRelativeDistance = fRelativeEndValue - fRelativeStartValue; 486*cdf0e10cSrcweir } 487*cdf0e10cSrcweir else 488*cdf0e10cSrcweir { 489*cdf0e10cSrcweir fRelativeStartValue = fOneRelative; 490*cdf0e10cSrcweir fRelativeEndValue = fZeroRelative; 491*cdf0e10cSrcweir fRelativeDistance = fRelativeStartValue - fRelativeEndValue; 492*cdf0e10cSrcweir } 493*cdf0e10cSrcweir 494*cdf0e10cSrcweir const double fNumberSteps = 495*cdf0e10cSrcweir (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic(); 496*cdf0e10cSrcweir nLoopTime = FRound(fNumberSteps * mnFrequency); 497*cdf0e10cSrcweir 498*cdf0e10cSrcweir if(0L == mnRepeat) 499*cdf0e10cSrcweir { 500*cdf0e10cSrcweir if(!DoScrollIn()) 501*cdf0e10cSrcweir { 502*cdf0e10cSrcweir // endless main loop 503*cdf0e10cSrcweir ScrollTextAnimNode aMainNode( 504*cdf0e10cSrcweir nLoopTime, 0L, 505*cdf0e10cSrcweir fRelativeStartValue, fRelativeEndValue, 506*cdf0e10cSrcweir mnFrequency, DoAlternate()); 507*cdf0e10cSrcweir maVector.push_back(aMainNode); 508*cdf0e10cSrcweir } 509*cdf0e10cSrcweir } 510*cdf0e10cSrcweir else 511*cdf0e10cSrcweir { 512*cdf0e10cSrcweir sal_uInt32 nNumRepeat(mnRepeat); 513*cdf0e10cSrcweir 514*cdf0e10cSrcweir if(DoAlternate() && (nNumRepeat + 1L) % 2L) 515*cdf0e10cSrcweir nNumRepeat += 1L; 516*cdf0e10cSrcweir 517*cdf0e10cSrcweir // ending main loop 518*cdf0e10cSrcweir ScrollTextAnimNode aMainNode( 519*cdf0e10cSrcweir nLoopTime, nNumRepeat, 520*cdf0e10cSrcweir fRelativeStartValue, fRelativeEndValue, 521*cdf0e10cSrcweir mnFrequency, DoAlternate()); 522*cdf0e10cSrcweir maVector.push_back(aMainNode); 523*cdf0e10cSrcweir } 524*cdf0e10cSrcweir } 525*cdf0e10cSrcweir 526*cdf0e10cSrcweir if(IsVisibleWhenStopped()) 527*cdf0e10cSrcweir { 528*cdf0e10cSrcweir double fRelativeStartValue, fRelativeEndValue, fRelativeDistance; 529*cdf0e10cSrcweir 530*cdf0e10cSrcweir if(DoScrollForward()) 531*cdf0e10cSrcweir { 532*cdf0e10cSrcweir fRelativeStartValue = fZeroRelative; 533*cdf0e10cSrcweir fRelativeEndValue = fInitRelative; 534*cdf0e10cSrcweir fRelativeDistance = fRelativeEndValue - fRelativeStartValue; 535*cdf0e10cSrcweir } 536*cdf0e10cSrcweir else 537*cdf0e10cSrcweir { 538*cdf0e10cSrcweir fRelativeStartValue = fOneRelative; 539*cdf0e10cSrcweir fRelativeEndValue = fInitRelative; 540*cdf0e10cSrcweir fRelativeDistance = fRelativeStartValue - fRelativeEndValue; 541*cdf0e10cSrcweir } 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir const double fNumberSteps = 544*cdf0e10cSrcweir (fRelativeDistance * fDistanceLogic) / GetStepWidthLogic(); 545*cdf0e10cSrcweir nLoopTime = FRound(fNumberSteps * mnFrequency); 546*cdf0e10cSrcweir 547*cdf0e10cSrcweir // exit loop 548*cdf0e10cSrcweir ScrollTextAnimNode aExitNode( 549*cdf0e10cSrcweir nLoopTime, 1L, 550*cdf0e10cSrcweir fRelativeStartValue, fRelativeEndValue, mnFrequency, false); 551*cdf0e10cSrcweir maVector.push_back(aExitNode); 552*cdf0e10cSrcweir } 553*cdf0e10cSrcweir } 554*cdf0e10cSrcweir } 555*cdf0e10cSrcweir 556*cdf0e10cSrcweir ScrollTextAnimNode* ActivityImpl::ImpGetScrollTextAnimNode( 557*cdf0e10cSrcweir sal_uInt32 nTime, sal_uInt32& rRelativeTime ) 558*cdf0e10cSrcweir { 559*cdf0e10cSrcweir ScrollTextAnimNode* pRetval = 0L; 560*cdf0e10cSrcweir ImpForceScrollTextAnimNodes(); 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir if(!maVector.empty()) 563*cdf0e10cSrcweir { 564*cdf0e10cSrcweir rRelativeTime = nTime; 565*cdf0e10cSrcweir 566*cdf0e10cSrcweir for(sal_uInt32 a(0L); !pRetval && a < maVector.size(); a++) 567*cdf0e10cSrcweir { 568*cdf0e10cSrcweir ScrollTextAnimNode & rNode = maVector[a]; 569*cdf0e10cSrcweir if(!rNode.GetRepeat()) 570*cdf0e10cSrcweir { 571*cdf0e10cSrcweir // endless loop, use it 572*cdf0e10cSrcweir pRetval = &rNode; 573*cdf0e10cSrcweir } 574*cdf0e10cSrcweir else if(rNode.GetFullTime() > rRelativeTime) 575*cdf0e10cSrcweir { 576*cdf0e10cSrcweir // ending node 577*cdf0e10cSrcweir pRetval = &rNode; 578*cdf0e10cSrcweir } 579*cdf0e10cSrcweir else 580*cdf0e10cSrcweir { 581*cdf0e10cSrcweir // look at next 582*cdf0e10cSrcweir rRelativeTime -= rNode.GetFullTime(); 583*cdf0e10cSrcweir } 584*cdf0e10cSrcweir } 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir 587*cdf0e10cSrcweir return pRetval; 588*cdf0e10cSrcweir } 589*cdf0e10cSrcweir 590*cdf0e10cSrcweir sal_uInt32 ActivityImpl::ImpRegisterAgainScrollTextMixerState(sal_uInt32 nTime) 591*cdf0e10cSrcweir { 592*cdf0e10cSrcweir sal_uInt32 nRetval(0L); 593*cdf0e10cSrcweir ImpForceScrollTextAnimNodes(); 594*cdf0e10cSrcweir 595*cdf0e10cSrcweir if(maVector.size()) 596*cdf0e10cSrcweir { 597*cdf0e10cSrcweir sal_uInt32 nRelativeTime; 598*cdf0e10cSrcweir ScrollTextAnimNode* pNode = ImpGetScrollTextAnimNode(nTime, nRelativeTime); 599*cdf0e10cSrcweir 600*cdf0e10cSrcweir if(pNode) 601*cdf0e10cSrcweir { 602*cdf0e10cSrcweir // take register time 603*cdf0e10cSrcweir nRetval = pNode->GetFrequency(); 604*cdf0e10cSrcweir } 605*cdf0e10cSrcweir } 606*cdf0e10cSrcweir else 607*cdf0e10cSrcweir { 608*cdf0e10cSrcweir // #i38135# not initialized, return default 609*cdf0e10cSrcweir nRetval = mnFrequency; 610*cdf0e10cSrcweir } 611*cdf0e10cSrcweir 612*cdf0e10cSrcweir return nRetval; 613*cdf0e10cSrcweir } 614*cdf0e10cSrcweir 615*cdf0e10cSrcweir void ActivityImpl::updateShapeAttributes( 616*cdf0e10cSrcweir double fTime, basegfx::B2DRectangle const& parentBounds ) 617*cdf0e10cSrcweir { 618*cdf0e10cSrcweir OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE ); 619*cdf0e10cSrcweir if( meAnimKind == drawing::TextAnimationKind_NONE ) 620*cdf0e10cSrcweir return; 621*cdf0e10cSrcweir 622*cdf0e10cSrcweir double const fMixerState = GetMixerState( 623*cdf0e10cSrcweir static_cast<sal_uInt32>(fTime * 1000.0) ); 624*cdf0e10cSrcweir 625*cdf0e10cSrcweir if( meAnimKind == drawing::TextAnimationKind_BLINK ) 626*cdf0e10cSrcweir { 627*cdf0e10cSrcweir // show/hide text: 628*cdf0e10cSrcweir maShapeAttrLayer.get()->setVisibility( fMixerState < 0.5 ); 629*cdf0e10cSrcweir } 630*cdf0e10cSrcweir else if(mpMetaFile) // scroll mode: 631*cdf0e10cSrcweir { 632*cdf0e10cSrcweir // 633*cdf0e10cSrcweir // keep care: the below code is highly sensible to changes... 634*cdf0e10cSrcweir // 635*cdf0e10cSrcweir 636*cdf0e10cSrcweir // rectangle of the pure text: 637*cdf0e10cSrcweir double const fPaintWidth = maPaintRectangleLogic.GetWidth(); 638*cdf0e10cSrcweir double const fPaintHeight = maPaintRectangleLogic.GetHeight(); 639*cdf0e10cSrcweir // rectangle where the scrolling takes place (-> clipping): 640*cdf0e10cSrcweir double const fScrollWidth = maScrollRectangleLogic.GetWidth(); 641*cdf0e10cSrcweir double const fScrollHeight = maScrollRectangleLogic.GetHeight(); 642*cdf0e10cSrcweir 643*cdf0e10cSrcweir basegfx::B2DPoint pos, clipPos; 644*cdf0e10cSrcweir 645*cdf0e10cSrcweir if(ScrollHorizontal()) 646*cdf0e10cSrcweir { 647*cdf0e10cSrcweir double const fOneEquiv( fScrollWidth ); 648*cdf0e10cSrcweir double const fZeroEquiv( -fPaintWidth ); 649*cdf0e10cSrcweir 650*cdf0e10cSrcweir pos.setX( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) ); 651*cdf0e10cSrcweir 652*cdf0e10cSrcweir clipPos.setX( -pos.getX() ); 653*cdf0e10cSrcweir clipPos.setY( -pos.getY() ); 654*cdf0e10cSrcweir 655*cdf0e10cSrcweir // #i69844# Compensation for text-wider-than-shape case 656*cdf0e10cSrcweir if( fPaintWidth > fScrollWidth ) 657*cdf0e10cSrcweir pos.setX( pos.getX() + (fPaintWidth-fScrollWidth) / 2.0 ); 658*cdf0e10cSrcweir } 659*cdf0e10cSrcweir else 660*cdf0e10cSrcweir { 661*cdf0e10cSrcweir // scroll vertical: 662*cdf0e10cSrcweir double const fOneEquiv( fScrollHeight ); 663*cdf0e10cSrcweir double const fZeroEquiv( -fPaintHeight ); 664*cdf0e10cSrcweir 665*cdf0e10cSrcweir pos.setY( fZeroEquiv + (fMixerState * (fOneEquiv - fZeroEquiv)) ); 666*cdf0e10cSrcweir 667*cdf0e10cSrcweir clipPos.setX( -pos.getX() ); 668*cdf0e10cSrcweir clipPos.setY( -pos.getY() ); 669*cdf0e10cSrcweir 670*cdf0e10cSrcweir // #i69844# Compensation for text-higher-than-shape case 671*cdf0e10cSrcweir if( fPaintHeight > fScrollHeight ) 672*cdf0e10cSrcweir pos.setY( pos.getY() + (fPaintHeight-fScrollHeight) / 2.0 ); 673*cdf0e10cSrcweir } 674*cdf0e10cSrcweir 675*cdf0e10cSrcweir basegfx::B2DPolygon clipPoly( 676*cdf0e10cSrcweir basegfx::tools::createPolygonFromRect( 677*cdf0e10cSrcweir basegfx::B2DRectangle( clipPos.getX(), 678*cdf0e10cSrcweir clipPos.getY(), 679*cdf0e10cSrcweir clipPos.getX() + fScrollWidth, 680*cdf0e10cSrcweir clipPos.getY() + fScrollHeight ) ) ); 681*cdf0e10cSrcweir 682*cdf0e10cSrcweir if( !::basegfx::fTools::equalZero( mfRotationAngle )) 683*cdf0e10cSrcweir { 684*cdf0e10cSrcweir maShapeAttrLayer.get()->setRotationAngle( mfRotationAngle ); 685*cdf0e10cSrcweir double const fRotate = (mfRotationAngle * M_PI / 180.0); 686*cdf0e10cSrcweir basegfx::B2DHomMatrix aTransform; 687*cdf0e10cSrcweir // position: 688*cdf0e10cSrcweir aTransform.rotate( fRotate ); 689*cdf0e10cSrcweir pos *= aTransform; 690*cdf0e10cSrcweir } 691*cdf0e10cSrcweir 692*cdf0e10cSrcweir pos += parentBounds.getCenter(); 693*cdf0e10cSrcweir maShapeAttrLayer.get()->setPosition( pos ); 694*cdf0e10cSrcweir maShapeAttrLayer.get()->setClip( basegfx::B2DPolyPolygon(clipPoly) ); 695*cdf0e10cSrcweir } 696*cdf0e10cSrcweir } 697*cdf0e10cSrcweir 698*cdf0e10cSrcweir bool ActivityImpl::perform() 699*cdf0e10cSrcweir { 700*cdf0e10cSrcweir if( !isActive() ) 701*cdf0e10cSrcweir return false; 702*cdf0e10cSrcweir 703*cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE( 704*cdf0e10cSrcweir mpDrawShape, 705*cdf0e10cSrcweir "ActivityImpl::perform(): still active, but NULL draw shape" ); 706*cdf0e10cSrcweir 707*cdf0e10cSrcweir DrawShapeSharedPtr const pParentDrawShape( mpParentDrawShape ); 708*cdf0e10cSrcweir if( !pParentDrawShape ) 709*cdf0e10cSrcweir return false; // parent has vanished 710*cdf0e10cSrcweir 711*cdf0e10cSrcweir if( pParentDrawShape->isVisible() ) 712*cdf0e10cSrcweir { 713*cdf0e10cSrcweir if( !mbIsShapeAnimated ) 714*cdf0e10cSrcweir { 715*cdf0e10cSrcweir mpDrawShape->setVisibility(true); // shape may be initially hidden 716*cdf0e10cSrcweir maContext.mpSubsettableShapeManager->enterAnimationMode( mpDrawShape ); 717*cdf0e10cSrcweir maTimer.reset(); 718*cdf0e10cSrcweir mbIsShapeAnimated = true; 719*cdf0e10cSrcweir } 720*cdf0e10cSrcweir // update attributes related to current time: 721*cdf0e10cSrcweir basegfx::B2DRectangle const parentBounds( 722*cdf0e10cSrcweir pParentDrawShape->getBounds() ); 723*cdf0e10cSrcweir 724*cdf0e10cSrcweir const double nCurrTime( maTimer.getElapsedTime() ); 725*cdf0e10cSrcweir updateShapeAttributes( nCurrTime, parentBounds ); 726*cdf0e10cSrcweir 727*cdf0e10cSrcweir const sal_uInt32 nFrequency( 728*cdf0e10cSrcweir ImpRegisterAgainScrollTextMixerState( 729*cdf0e10cSrcweir static_cast<sal_uInt32>(nCurrTime * 1000.0)) ); 730*cdf0e10cSrcweir 731*cdf0e10cSrcweir if(nFrequency) 732*cdf0e10cSrcweir { 733*cdf0e10cSrcweir mpWakeupEvent->start(); 734*cdf0e10cSrcweir mpWakeupEvent->setNextTimeout( 735*cdf0e10cSrcweir std::max(0.1,nFrequency/1000.0) ); 736*cdf0e10cSrcweir maContext.mrEventQueue.addEvent( mpWakeupEvent ); 737*cdf0e10cSrcweir 738*cdf0e10cSrcweir if( mpDrawShape->isContentChanged() ) 739*cdf0e10cSrcweir maContext.mpSubsettableShapeManager->notifyShapeUpdate( mpDrawShape ); 740*cdf0e10cSrcweir } 741*cdf0e10cSrcweir // else: finished, not need to wake up again. 742*cdf0e10cSrcweir } 743*cdf0e10cSrcweir else 744*cdf0e10cSrcweir { 745*cdf0e10cSrcweir // busy-wait, until parent shape gets visible 746*cdf0e10cSrcweir mpWakeupEvent->start(); 747*cdf0e10cSrcweir mpWakeupEvent->setNextTimeout( 2.0 ); 748*cdf0e10cSrcweir } 749*cdf0e10cSrcweir 750*cdf0e10cSrcweir // don't reinsert, WakeupEvent will perform that after the given timeout: 751*cdf0e10cSrcweir return false; 752*cdf0e10cSrcweir } 753*cdf0e10cSrcweir 754*cdf0e10cSrcweir ActivityImpl::ActivityImpl( 755*cdf0e10cSrcweir SlideShowContext const& rContext, 756*cdf0e10cSrcweir boost::shared_ptr<WakeupEvent> const& pWakeupEvent, 757*cdf0e10cSrcweir boost::shared_ptr<DrawShape> const& pParentDrawShape ) 758*cdf0e10cSrcweir : maContext(rContext), 759*cdf0e10cSrcweir mpWakeupEvent(pWakeupEvent), 760*cdf0e10cSrcweir mpParentDrawShape(pParentDrawShape), 761*cdf0e10cSrcweir mpListener( new IntrinsicAnimationListener(*this) ), 762*cdf0e10cSrcweir maTimer(rContext.mrEventQueue.getTimer()), 763*cdf0e10cSrcweir mbIsShapeAnimated(false), 764*cdf0e10cSrcweir mbIsDisposed(false), 765*cdf0e10cSrcweir mbIsActive(true), 766*cdf0e10cSrcweir meAnimKind(drawing::TextAnimationKind_NONE), 767*cdf0e10cSrcweir mnStartTime(0L) 768*cdf0e10cSrcweir { 769*cdf0e10cSrcweir // get doctreenode: 770*cdf0e10cSrcweir sal_Int32 const nNodes = pParentDrawShape->getNumberOfTreeNodes( 771*cdf0e10cSrcweir DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ); 772*cdf0e10cSrcweir 773*cdf0e10cSrcweir DocTreeNode scrollTextNode( 774*cdf0e10cSrcweir pParentDrawShape->getTreeNode( 775*cdf0e10cSrcweir 0, DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH )); 776*cdf0e10cSrcweir // xxx todo: remove this hack 777*cdf0e10cSrcweir if( nNodes > 1 ) 778*cdf0e10cSrcweir scrollTextNode.setEndIndex( 779*cdf0e10cSrcweir pParentDrawShape->getTreeNode( 780*cdf0e10cSrcweir nNodes - 1, 781*cdf0e10cSrcweir DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH ).getEndIndex()); 782*cdf0e10cSrcweir 783*cdf0e10cSrcweir // TODO(Q3): Doing this manually, instead of using 784*cdf0e10cSrcweir // ShapeSubset. This is because of lifetime issues (ShapeSubset 785*cdf0e10cSrcweir // generates circular references to parent shape) 786*cdf0e10cSrcweir mpDrawShape = boost::dynamic_pointer_cast<DrawShape>( 787*cdf0e10cSrcweir maContext.mpSubsettableShapeManager->getSubsetShape( 788*cdf0e10cSrcweir pParentDrawShape, 789*cdf0e10cSrcweir scrollTextNode )); 790*cdf0e10cSrcweir 791*cdf0e10cSrcweir mpMetaFile = mpDrawShape->forceScrollTextMetaFile(); 792*cdf0e10cSrcweir 793*cdf0e10cSrcweir // make scroll text invisible for slide transition bitmaps 794*cdf0e10cSrcweir mpDrawShape->setVisibility(false); 795*cdf0e10cSrcweir 796*cdf0e10cSrcweir basegfx::B2DRectangle aScrollRect, aPaintRect; 797*cdf0e10cSrcweir ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect, 798*cdf0e10cSrcweir aPaintRect, 799*cdf0e10cSrcweir mpMetaFile ), 800*cdf0e10cSrcweir "ActivityImpl::ActivityImpl(): Could not extract " 801*cdf0e10cSrcweir "scroll anim rectangles from mtf" ); 802*cdf0e10cSrcweir 803*cdf0e10cSrcweir maScrollRectangleLogic = vcl::unotools::rectangleFromB2DRectangle( 804*cdf0e10cSrcweir aScrollRect ); 805*cdf0e10cSrcweir maPaintRectangleLogic = vcl::unotools::rectangleFromB2DRectangle( 806*cdf0e10cSrcweir aPaintRect ); 807*cdf0e10cSrcweir 808*cdf0e10cSrcweir maShapeAttrLayer.createAttributeLayer(mpDrawShape); 809*cdf0e10cSrcweir 810*cdf0e10cSrcweir uno::Reference<drawing::XShape> const xShape( mpDrawShape->getXShape() ); 811*cdf0e10cSrcweir uno::Reference<beans::XPropertySet> const xProps( xShape, uno::UNO_QUERY_THROW ); 812*cdf0e10cSrcweir 813*cdf0e10cSrcweir getPropertyValue( meAnimKind, xProps, OUSTR("TextAnimationKind") ); 814*cdf0e10cSrcweir OSL_ASSERT( meAnimKind != drawing::TextAnimationKind_NONE ); 815*cdf0e10cSrcweir mbAlternate = (meAnimKind == drawing::TextAnimationKind_ALTERNATE); 816*cdf0e10cSrcweir mbScrollIn = (meAnimKind == drawing::TextAnimationKind_SLIDE); 817*cdf0e10cSrcweir 818*cdf0e10cSrcweir // adopted from in AInfoBlinkText::ImplInit(): 819*cdf0e10cSrcweir sal_Int16 nRepeat(0); 820*cdf0e10cSrcweir getPropertyValue( nRepeat, xProps, OUSTR("TextAnimationCount") ); 821*cdf0e10cSrcweir mnRepeat = nRepeat; 822*cdf0e10cSrcweir 823*cdf0e10cSrcweir if(mbAlternate) 824*cdf0e10cSrcweir { 825*cdf0e10cSrcweir // force visible when started for scroll-forth-and-back, because 826*cdf0e10cSrcweir // slide has been coming in with visible text in the middle: 827*cdf0e10cSrcweir mbVisibleWhenStarted = true; 828*cdf0e10cSrcweir } 829*cdf0e10cSrcweir else 830*cdf0e10cSrcweir { 831*cdf0e10cSrcweir getPropertyValue( mbVisibleWhenStarted, xProps, 832*cdf0e10cSrcweir OUSTR("TextAnimationStartInside") ); 833*cdf0e10cSrcweir } 834*cdf0e10cSrcweir 835*cdf0e10cSrcweir // set visible when stopped 836*cdf0e10cSrcweir getPropertyValue( mbVisibleWhenStopped, xProps, 837*cdf0e10cSrcweir OUSTR("TextAnimatiogonStopInside") ); 838*cdf0e10cSrcweir // rotation: 839*cdf0e10cSrcweir getPropertyValue( mfRotationAngle, xProps, 840*cdf0e10cSrcweir OUSTR("RotateAngle") ); 841*cdf0e10cSrcweir mfRotationAngle /= -100.0; // (switching direction) 842*cdf0e10cSrcweir 843*cdf0e10cSrcweir // set frequency 844*cdf0e10cSrcweir sal_Int16 nDelay(0); 845*cdf0e10cSrcweir getPropertyValue( nDelay, xProps, OUSTR("TextAnimationDelay") ); 846*cdf0e10cSrcweir // set delay if not automatic 847*cdf0e10cSrcweir mnFrequency = (nDelay ? nDelay : 848*cdf0e10cSrcweir // default: 849*cdf0e10cSrcweir meAnimKind == drawing::TextAnimationKind_BLINK 850*cdf0e10cSrcweir ? 250L : 50L ); 851*cdf0e10cSrcweir 852*cdf0e10cSrcweir // adopted from in AInfoScrollText::ImplInit(): 853*cdf0e10cSrcweir 854*cdf0e10cSrcweir // If it is a simple m_bScrollIn, reset some parameters 855*cdf0e10cSrcweir if( DoScrollIn() ) 856*cdf0e10cSrcweir { 857*cdf0e10cSrcweir // most parameters are set correctly from the dialog logic, but 858*cdf0e10cSrcweir // eg VisisbleWhenStopped is grayed out and needs to be corrected here. 859*cdf0e10cSrcweir mbVisibleWhenStopped = true; 860*cdf0e10cSrcweir mbVisibleWhenStarted = false; 861*cdf0e10cSrcweir mnRepeat = 0L; 862*cdf0e10cSrcweir } 863*cdf0e10cSrcweir 864*cdf0e10cSrcweir // Get animation direction 865*cdf0e10cSrcweir getPropertyValue( meDirection, xProps, OUSTR("TextAnimationDirection") ); 866*cdf0e10cSrcweir 867*cdf0e10cSrcweir // Get step width. Negative means pixel, positive logical units 868*cdf0e10cSrcweir getPropertyValue( mnStepWidth, xProps, OUSTR("TextAnimationAmount") ); 869*cdf0e10cSrcweir 870*cdf0e10cSrcweir maContext.mpSubsettableShapeManager->addIntrinsicAnimationHandler( 871*cdf0e10cSrcweir mpListener ); 872*cdf0e10cSrcweir } 873*cdf0e10cSrcweir 874*cdf0e10cSrcweir bool ActivityImpl::enableAnimations() 875*cdf0e10cSrcweir { 876*cdf0e10cSrcweir mbIsActive = true; 877*cdf0e10cSrcweir return maContext.mrActivitiesQueue.addActivity( 878*cdf0e10cSrcweir shared_from_this() ); 879*cdf0e10cSrcweir } 880*cdf0e10cSrcweir 881*cdf0e10cSrcweir ActivityImpl::~ActivityImpl() 882*cdf0e10cSrcweir { 883*cdf0e10cSrcweir } 884*cdf0e10cSrcweir 885*cdf0e10cSrcweir void ActivityImpl::dispose() 886*cdf0e10cSrcweir { 887*cdf0e10cSrcweir if( !mbIsDisposed ) 888*cdf0e10cSrcweir { 889*cdf0e10cSrcweir end(); 890*cdf0e10cSrcweir 891*cdf0e10cSrcweir // only remove subset here, since end() is called on slide end 892*cdf0e10cSrcweir // (and we must not spoil the slide preview bitmap with scroll 893*cdf0e10cSrcweir // text) 894*cdf0e10cSrcweir maShapeAttrLayer.reset(); 895*cdf0e10cSrcweir if( mpDrawShape ) 896*cdf0e10cSrcweir { 897*cdf0e10cSrcweir // TODO(Q3): Doing this manually, instead of using 898*cdf0e10cSrcweir // ShapeSubset. This is because of lifetime issues 899*cdf0e10cSrcweir // (ShapeSubset generates circular references to parent 900*cdf0e10cSrcweir // shape) 901*cdf0e10cSrcweir DrawShapeSharedPtr pParent( mpParentDrawShape.lock() ); 902*cdf0e10cSrcweir if( pParent ) 903*cdf0e10cSrcweir maContext.mpSubsettableShapeManager->revokeSubset( 904*cdf0e10cSrcweir pParent, 905*cdf0e10cSrcweir mpDrawShape ); 906*cdf0e10cSrcweir } 907*cdf0e10cSrcweir 908*cdf0e10cSrcweir mpMetaFile.reset(); 909*cdf0e10cSrcweir mpDrawShape.reset(); 910*cdf0e10cSrcweir mpParentDrawShape.reset(); 911*cdf0e10cSrcweir mpWakeupEvent.reset(); 912*cdf0e10cSrcweir maContext.dispose(); 913*cdf0e10cSrcweir mbIsDisposed = true; 914*cdf0e10cSrcweir 915*cdf0e10cSrcweir maContext.mpSubsettableShapeManager->removeIntrinsicAnimationHandler( 916*cdf0e10cSrcweir mpListener ); 917*cdf0e10cSrcweir } 918*cdf0e10cSrcweir } 919*cdf0e10cSrcweir 920*cdf0e10cSrcweir double ActivityImpl::calcTimeLag() const 921*cdf0e10cSrcweir { 922*cdf0e10cSrcweir return 0.0; 923*cdf0e10cSrcweir } 924*cdf0e10cSrcweir 925*cdf0e10cSrcweir bool ActivityImpl::isActive() const 926*cdf0e10cSrcweir { 927*cdf0e10cSrcweir return mbIsActive; 928*cdf0e10cSrcweir } 929*cdf0e10cSrcweir 930*cdf0e10cSrcweir void ActivityImpl::dequeued() 931*cdf0e10cSrcweir { 932*cdf0e10cSrcweir // not used here 933*cdf0e10cSrcweir } 934*cdf0e10cSrcweir 935*cdf0e10cSrcweir void ActivityImpl::end() 936*cdf0e10cSrcweir { 937*cdf0e10cSrcweir // not used here 938*cdf0e10cSrcweir mbIsActive = false; 939*cdf0e10cSrcweir 940*cdf0e10cSrcweir if( mbIsShapeAnimated ) 941*cdf0e10cSrcweir { 942*cdf0e10cSrcweir maContext.mpSubsettableShapeManager->leaveAnimationMode( mpDrawShape ); 943*cdf0e10cSrcweir mbIsShapeAnimated = false; 944*cdf0e10cSrcweir } 945*cdf0e10cSrcweir } 946*cdf0e10cSrcweir 947*cdf0e10cSrcweir } // anon namespace 948*cdf0e10cSrcweir 949*cdf0e10cSrcweir namespace slideshow { 950*cdf0e10cSrcweir namespace internal { 951*cdf0e10cSrcweir 952*cdf0e10cSrcweir boost::shared_ptr<Activity> createDrawingLayerAnimActivity( 953*cdf0e10cSrcweir SlideShowContext const& rContext, 954*cdf0e10cSrcweir boost::shared_ptr<DrawShape> const& pDrawShape ) 955*cdf0e10cSrcweir { 956*cdf0e10cSrcweir boost::shared_ptr<Activity> pActivity; 957*cdf0e10cSrcweir 958*cdf0e10cSrcweir try 959*cdf0e10cSrcweir { 960*cdf0e10cSrcweir boost::shared_ptr<WakeupEvent> const pWakeupEvent( 961*cdf0e10cSrcweir new WakeupEvent( rContext.mrEventQueue.getTimer(), 962*cdf0e10cSrcweir rContext.mrActivitiesQueue ) ); 963*cdf0e10cSrcweir pActivity.reset( new ActivityImpl( rContext, pWakeupEvent, pDrawShape ) ); 964*cdf0e10cSrcweir pWakeupEvent->setActivity( pActivity ); 965*cdf0e10cSrcweir } 966*cdf0e10cSrcweir catch( uno::RuntimeException& ) 967*cdf0e10cSrcweir { 968*cdf0e10cSrcweir throw; 969*cdf0e10cSrcweir } 970*cdf0e10cSrcweir catch( uno::Exception& ) 971*cdf0e10cSrcweir { 972*cdf0e10cSrcweir // translate any error into empty factory product. 973*cdf0e10cSrcweir OSL_ENSURE( false, 974*cdf0e10cSrcweir rtl::OUStringToOString( 975*cdf0e10cSrcweir comphelper::anyToString( cppu::getCaughtException() ), 976*cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ).getStr() ); 977*cdf0e10cSrcweir } 978*cdf0e10cSrcweir 979*cdf0e10cSrcweir return pActivity; 980*cdf0e10cSrcweir } 981*cdf0e10cSrcweir 982*cdf0e10cSrcweir } // namespace internal 983*cdf0e10cSrcweir } // namespace presentation 984*cdf0e10cSrcweir 985